2017-03-17 67 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