2015-05-07 70 views
1

ZF2項目的Zend \ Db的模式 - 無主義,使用本機的Zend \ Db的:具有以下結構:與兒童模式

Controller 
    ProductController 
Model 
    Product 
    ProductTable 
    ProductType 
    ProductTypeTable 

產品是模型,具有對應於「產品」表中的字段變量。

的productTable是連接到經由tableGateway數據庫表類。的productTable具有的getItem()方法由「ID」來檢索請求的產品。

ProductType是模型,具有對應像ID,名稱,描述變量到「產品」 pes「表字段。

ProductTypeTable就像ProductTable一樣是表類。

每個產品屬於某個ProductType

products.productTypeId = productTypes.id 

是的關係。

在ProductTable-> getItem()方法中,我可以簡單地獲取productTypeId。 我可以使用連接來獲取productTypes.name,productTypes.description或「productTypes」表中的任何字段。 但我不想這樣做 - 而是處理產品實體中的新變量,如productTypeName,productTypeDesc, 我想要Product->getProductType()並將其設置爲ProductType對象,因此我可以獲得Product->getProductType() ->getName()以獲得產品類型名稱。

只是我想分配一個子模型作爲父模型的變量。

我能做到這一點在控制器象下面這樣:

$product = $this->getProductTable()->getItem(7); // id = 7 
$product->setProductType($this->getProductTypeTable() 
        ->getItem($product->getProductTypeId()); 

,但我想,使其在產品表類的getItem發生()方法。所以我不必在每個控制器中考慮它,而且它是封裝的。

這樣做的正確方法是什麼?

謝謝。

回答

1

您擁有的問題是Table Gateway pattern僅僅是將抽象數據庫訪問抽象爲單個數據庫表的真正好處。反正它不允許實體的水合或關係的管理。對象關係映射器(ORM's)(如Doctrine)解決了這個問題。

如果主義,不管是什麼原因,是不適合你的使用情況的替代,可以實現Data Mapper Pattern

數據映射器是,在內存中的對象從數據庫中分離的軟件層。其職責是兩個,也之間傳輸數據給他們相互

數據映射器隔離會使用表網關獲取每個表所需的數據和構建Product實例,包括它的關聯ProductType。然後你會將映射器公開給控制器(而不是表格網關)。

一個簡單的例子ProductMapper

class ProductMapper 
{ 
    // @var \Zend\Db\TableGateway\TableGateway 
    protected $productTable; 

    protected $productTypeMapper; 

    // an 'identity map' of loaded products 
    protected $loaded = []; 

    public function __construct(ProductTable $productTable, ProductTypeMapper $productTypeMapper) 
    { 
     $this->productTable = $productTable; 
     $this->productTypeMapper = $productTypeMapper; 
    } 

    protected function hydrate(Product $product, array $data) 
    { 
     $product->setId($data['id']); 
     $product->setName($data['name']); 
     $product->setFoo($data['foo']); 

     if (isset($data['type_id'])) { 
      // Load a fully constructed product type from the database 
      $type = $this->productTypeMapper->findById($data['type_id']); 
      $product->setType($type); 
     } 

     return $product; 
    } 

    public function findById($id) 
    { 
     if (isset($this->loaded[$id])) { 
      return $this->loaded[$id]; 
     } 
     // Get the data 
     $row = $this->productTable->select(['id' => $id]); 

     if (empty($row)) { 
      throw new SomeCustomException("No product could be found with id $id"); 
     } 
     // Create and hydrate the product 
     $product = $this->hydrate(new Product, $row->current()) 
     $this->loaded[$id] = $product; 

     return $product; 
    } 

    public function save(array $data); 

    public function update($data); 

    public function delete($id); 
} 
+0

只要我可以按照你的詳細描述,這是非常好的。這很棒,因爲我知道必須有一種方法,但我對ZF2並不是100%熟悉的。我試圖避免學說使用本地方法 - 學習。我目前無法對其進行測試,但是我想感謝您爲解釋這一點做出的努力。當我週末回到電腦時,我會給出結果。 – smozgur

+0

我做了一些關於DataMapper的研究,我可以看到這是我需要的,我必須學習的東西。然而,我太過專注於TableGateway--意味着到目前爲止只熟悉ZF2中的TableGateway模式,而且如果沒有適當的文檔,我就很難開始工作,而且我沒有發現任何關於DataMapper的內容,而是另一大圖片的一小部分幫助初學者。你可以參考一個教程或某個地方的一個良好的開端,我可以像傳統的指南一樣遵循?除此之外,我的理解是,DataMapper正是我的問題的答案。謝謝! – smozgur

+0

我強烈推薦Martin Fowler的書[企業應用程序架構模式(PoEAA)](http://www.amazon.co.uk/Enterprise-Application-Architecture-Addison-Wesley-Signature/dp/0321127420)。儘管第一次在2002年發佈,並且大多數示例都是Java,但它仍然提供了有關Web應用程序設計模式的非常相關和簡明的細節(Data Mapper模式僅爲衆多示例之一)。 – AlexP

0

你可以做到這一點,你只需要遵循以下3個步驟:

  1. 讓您Product->exchangeArray()功能更聰明
  2. 獲取所有所需ProductType領域,使用前綴有助於例如:type_
  3. Add @var ProductType所以你會有適當的自動運行(適用於Eclipse的我)

    <?php 
    namespace Product\Model\Product; 
    
    class Product { 
        public $id; 
        ... 
        /** 
        * @var ProductType 
        */ 
        public $productType; 
        ... 
        public function exchangeArray($data) { 
         $this->id = (isset($data['id'])) ? $data['id'] : null; 
         ... 
         $productType = new ProductType(); 
         $typeData = array(
          'id' => $data['type_id'], 
          'value' => $data['type_value'] 
         ); 
         $productType->exchangeArray($typeData); 
         $this->productType = $productType; 
        } 
    } 
    
+0

感謝您的詳細回覆。但是,我正在通過成功地加入,這就是我想要避免的。我不想填充ProductType對象,我想通過產品附帶的productTypeId字段值創建相關的ProductType對象實例,並將其作爲鏈接到產品模型的對象變量使用。謝謝。 – smozgur