2017-03-17 75 views
2

我有一个REST API。我需要创建演示文稿(DTO)对象,但该对象的构建取决于请求 - 它有15%的差异。 我不知道我应该使用什么样的模式。基于多个参数创建不同的对象

我的情况:

//presentation-DTO 
class Item { 
    private $name; 
    private $price; 
    private $tags; 
    private $liked; //is Liked by logged user 
    ... 

    public function __construct(Item $item, bool $liked, ...) 
    { 
     $this->name = $item->getName(); 
     $this->price = $item->getPrice(); 
     $this->tags = $item->getTags(); 
     $this->liked = $liked; 
     ... 
    } 
} 

当没有登录的用户 - 我不需要$喜欢

当显示的产品清单 - 我不需要$标签

而且还有更多的属性可以像上面那样工作。

我的第一个想法是使用Builder原理。

$itemBuilder = new ItemBuilder(); 
$itemBuilder->setItem($item); 
... 
if($user) { 
    $itemBuilder->setUserLiked($userLiked); 
    ... 
} 
return $itemBuilder->build(); 

它解决了我在构造函数中有太多参数的问题。

但是,我还不需要构建所有参数 - 例如。我不需要标签(在列表上)。由于我使用延迟加载,我不想让我的dto构造函数调用它们。

所以我想,也许工厂..但是然后我的问题与太多(和可选)参数返回。

你将如何解决这个问题?

+0

**当** [1]你不想没有登录用户通过'$ liked'作为构造函数的参数? **或** [2]可以将'$ liked'作为参数传递给构造函数,但不想调用'$ this-> liked = $ item-> getLiked();'因为'当用户未被记录在 - 我不需要$喜欢'。多解释一下。 – sameerkn

+0

有两种情况。 [a]关于$喜欢的信息来自分开的数据。我无法从$ item对象获取它们 - 需要将它们作为参数传递。 [b]关于$ tokes的信息来自$ item对象,但我不希望它们在构造函数中被调用,当我不需要它们时。所以在[a]的情况下,我不想通过它们[1]。如果[b] - 我不想打给他们。在bot病例中,我不想在dto对象中拥有这个属性 - 如果我不需要它们的话。 – Anna

回答

0

对不起,我没有要求发表评论,因此一个答案。

你想用Item做什么?你的班级是Item,第一个参数也是Item。我无法想象它将如何工作。

我会宁愿保持业务登录在一个单独的类设置适当的属性:

/** 
* A class for business logic to set the proper properties 
*/ 
class ItemProperties { 
    private $item; 
    public $isLogin = false; 
    public $showList = false; 
    ..... 

    public function __construct(Item &$item) { 
     // set all properties; 
    } 


    public function getProperties() { 
     $retVal  = []; 
     if($this->isLogin == true) { 
      $retVal['liked'] = true; 
     } 

     if($this->showList == true) { 
      $retVal['tags'] = $this->item->getTags(); 
     } 

     if(....) { 
      $retVal['...'] = $this->item->.....(); 
     } 

     return $retVal; 
    } 
} 

/** 
* DTO 
*/ 
class Item { 
    public function __construct(ItemProperties $itemProps) { 
     $this->setItemProps($itemProps); 
    } 

    // If you prefer lazy loading here...maybe make it public 
    // and remove call from constructor. 
    private function setItemProps(&$itemProps) { 
     $properties = $itemProps->getProperties(); 
     foreach($properties AS $propName => $propValue) { 
      $this->$propName = $propValue; 
     } 
    } 
} 


// Usage: 
$itemProps = new ItemProperties($Item); 
// set other properties if you need to... 
$itemProps->isLogin = false; 

$item = new Item($itemProps); 
+0

你理解得很好。 Item类是DTO,它获取item属性,即ORM实体。 – Anna

+0

谢谢你的回答,它给了我一个全新的面貌。只有一个想法需要重新考虑。在你的解决方案中,ItemProperties类就像构建器一样工作(存储创建对象所需的信息),并存储关于DTO对象具有哪些属性的信息 - 因此它有多个责任。我认为,ItemProperties类应该只存储数据并验证是否设置了适当的类型......并且应该有不同的类来确定DTO具有的属性。此外,getProperties方法将很难保持简单并开发它。 – Anna