$ _referenceMap Отношения с Zend_Db_Table_Abstract создают слишком много запросов

Я впервые использую Zend Framework для приложения, и я не знаю, полностью ли разбираюсь в моделях.

У меня есть четыре таблицы: shopping_cart, product, product_unit, distribution. корзина покупок имеет идентификаторы cart_id, product_id, unit_id и dist_id (корзина покупок присоединяется к другим таблицам с соответствующими идентификаторами).

До Zend я бы создал такой класс:

class ShoppingCart
{
function getItems()
{
$sql ="select * from shopping_cart, product, product_unit, distributor 
where 
shopping_cart.product_id = product.id AND
shopping_cart.unit_id = product_unit.id AND  
shopping_cart.dist_id = distributor.id AND
cart_id = xxx";

$items = $this->db->getAll($sql);
}

Один запрос для получения всей информации из объединенных таблиц.

Когда я настраивал отображение отношений в Zend_Db_Table_Abstract:

Модель моей корзины покупок:

class Application_Model_ShoppingCart
{
    function __construct()
    {
        $this->ShoppingCartTable = new Application_Model_DbTable_ShoppingCart();
    }

    function getItems()
    {
        $cart_items = $this->ShoppingCartTable->getItems($this->GetCartId());
        return $cart_items;
    }
}

class Application_Model_DbTable_ShoppingCart расширяет Zend_Db_Table_Abstract {

protected $_name = 'shopping_cart';

protected $_rowClass = 'Application_Model_DbTable_ShoppingCart_Item';

protected $_referenceMap    = array(
    'Product' => array(
        'columns'           => 'product_id',
        'refTableClass'     => 'Application_Model_DbTable_Product',
        'refColumns'        => 'id'
        ),
    'Distributor' => array(
        'columns'           => 'dist_id',
        'refTableClass'     => 'Application_Model_DbTable_Distributor',
        'refColumns'        => 'id'
        ),
    'Unit' => array(
        'columns'           => 'unit_id',
        'refTableClass'     => 'Application_Model_DbTable_ProductUnit',
        'refColumns'        => 'id'
        )
);

public function getItems($cart_id)
{
    $where = $this->getAdapter()->quoteInto('cart_id = ?', $cart_id);

    return $this->fetchAll($where);
}

}

В моем контроллере:

$this->_shoppingCartModel = new Application_Model_ShoppingCart();
$items = $this->_shoppingCartModel->getItems();

По-моему :

foreach($this->items AS $item) 
{
    $item_product = $item->findParentRow('Application_Model_DbTable_Product');
    $item_dist = $item->findParentRow('Application_Model_DbTable_Distributor');
    $item_unit = $item->findParentRow('Application_Model_DbTable_ProductUnit');
}

когда у меня в корзине десять товаров, профилировщик db показывает более шестидесяти запросов (WHOA) для просмотра товаров (отображается информация по всем четырем таблицам - название продукта, описание единицы, название дистрибьютора). Для каждого элемента он запрашивает shopping_cart, затем запрашивает таблицу продуктов, затем единицу продукта, затем таблицу distributionor_table.

Есть ли способ выполнить это как один запрос, объединяющий все таблицы через отношения Zend_Db_Table_Abstract?
Придется ли мне вернуться к использованию адаптера db в моем классе Application_Model_ShoppingCart?

Я хочу абстрагировать весь доступ к данным для моделей таблиц (Application_Model_DbTable_ShoppingCart) и не связывать Application_Model_ShoppingCart с обработчиком db.

Заранее благодарю за совет, мне нравится Zend Framework, но мне все еще трудно понять модели, учитывая различные противоречивые способы их использования.


person marko.vujo    schedule 16.09.2010    source источник


Ответы (1)


Короче говоря, нет, к сожалению, невозможно получить набор строк таблицы вместе с их связями в одном запросе.

Просто все методы, работающие с отношениями, определены для строки, а не для таблицы.

Но, по крайней мере, вы можете сформировать свой sql с помощью Zend_Db_Table_Select вместо того, чтобы писать все это вручную.

Upd: Ваш код для получения ShoppingCarts, по моему мнению, должен принадлежать таблице (DbTable_ShoppingCart). Итак, код, который вы предоставили в начале, можно преобразовать в следующий:

class Application_Model_DbTable_ShoppingCart extends Zend_Db_Table_Abstract {
   public function getItem($cart_id) {
      $select = $this->select()
                     ->from( array('sc' => 'shopping_cart'), array(Zend_Db_Select::SQL_WILDCARD) )
                     ->join( array('p' => 'product'), 'sp.product_id = p.id', array(Zend_Db_Select::SQL_WILDCARD) )
                     ->join( array('pu' => 'product_unit'), 'sp.unit_id = pu.id', array(Zend_Db_Select::SQL_WILDCARD) )
                     ->join( array('d' => 'distributor'), 'sp.dist_id = d.id', array(Zend_Db_Select::SQL_WILDCARD) )
                     ->where('sp.cart_id = ?', $cart_id)
                     ->setIntegrityCheck(false);
      return $this->fetchAll($select);
   }
}
person Vika    schedule 16.09.2010
comment
Вика, спасибо за быстрый ответ ... если я использую Zend table select ... что лучше выполнять пользовательские объединения в классе модели Application_Model_ShoppingCart или в Application_Model_ShoppingCart_DbTable? - person marko.vujo; 17.09.2010