2015-05-07 8 views
1

ZF2 проекта - нет доктрины, используя родной Zend \ Db: иметь следующую структуру:Zend Db Модель детей моделей

Controller 
    ProductController 
Model 
    Product 
    ProductTable 
    ProductType 
    ProductTypeTable 

Продукт является модель, имеет переменные, соответствующие «продукции» полей таблицы.

ProductTable настольный класс, который подключается к базе данных через tableGateway. ProductTable имеет GetItem() метод для получения запрошенного продукта «ID».

ProductType является моделью, имеет переменные, такие как идентификатор, имя, описание соответствующего к "productTy pes ".

ProductTypeTable - это класс таблицы, аналогичный ProductTable.

Каждый продукт относится к определенному ProductType

products.productTypeId = productTypes.id 

это отношение.

В методе ProductTable-> getItem() я могу просто получить productTypeId. Я могу использовать объединения для получения productTypes.name, productTypes.description или любого поля из таблицы «productTypes». Но я не хочу этого делать - вместо этого, имея дело с новыми переменными в Product Product, таких как 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), такие как 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

Это действительно хорошо, насколько я могу следовать вашему подробному описанию. Это здорово, потому что я знал, что должен быть способ, но я не на 100% знаком с ZF2. Я стараюсь избегать Доктрины, чтобы использовать собственные методы - учиться. В настоящее время я не могу проверить это, но я хотел поблагодарить вас за ваши усилия, чтобы объяснить это хорошо. Я дам результаты, когда вернусь на свой компьютер в эти выходные. – smozgur

+0

Я сделал несколько исследований о DataMapper, и я вижу, что это то, что мне нужно, и чему я должен научиться. Однако я слишком сосредоточен на TableGateway, что означает только знакомство с шаблоном TableGateway в ZF2 до сих пор, и мне сложно начать работу без надлежащей документации, и ничего, что я нашел, было только о DataMapper, а какая-то небольшая часть другой большой картины, которая не помогите новичкам. Можете ли вы обратиться к учебнику или о каком-то месте для хорошего начала, за которым я могу следовать, как обычный гид? Кроме того, я понимаю, DataMapper - это точно ответ на мой вопрос. Благодаря! – smozgur

+0

Я бы очень рекомендовал книгу [Шаблоны архитектуры корпоративных приложений (PoEAA)] (http://www.amazon.co.uk/Enterprise-Application-Architecture-Addison-Wesley-Signature/dp/0321127420) Мартина Фаулера. Несмотря на то, что он впервые был опубликован в 2002 году, и большинство примеров находятся на Java, он по-прежнему предлагает очень актуальные и краткие сведения о шаблонах проектирования веб-приложений (шаблон Data Mapper является всего лишь одним из многих). – AlexP

0

Вы можете достичь этого, вы просто должны выполнить следующие 3 шага:

  1. Сделайте Product->exchangeArray() функция умнее
  2. Получить все необходимые ProductType поля, используя префикс помогает, например: type_
  3. Добавьте @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, я хотел бы создать связанный экземпляр объекта ProductType по типу productTypeId, входящему в Продукт, и использовать его как связанный с моделью продукта как переменную объекта. Спасибо. – smozgur

 Смежные вопросы

  • Нет связанных вопросов^_^