$ _referenceMap Relationships с Zend_Db_Table_Abstract создает слишком много запросов - PullRequest
1 голос
/ 17 сентября 2010

Это мой первый раз, когда я использую Zend Framework для приложения, и я не знаю, полностью ли я освоил Модели.

У меня есть четыре таблицы: shopping_cart, product, product_unit, distributor.У корзины покупок есть 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;
    }
}

класс Application_Model_DbTable_ShoppingCart extends 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');
}

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

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

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

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

1 Ответ

1 голос
/ 17 сентября 2010

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

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

Но, по крайней мере, вы можете создать свой 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);
   }
}
...