Koleksiyonda grup yan tümcesi kullanıldığında ızgara sayfalama çalışmıyor


9

Ürün ızgarasında çalışıyorum ancak sayfalandırma veya ürün sayısı çalışmıyor (yanlış sayım gösterdiği için). benim blok _preparecollection işlevi aşağıdaki gibidir. koleksiyonda kategori filtre kodu ekledim, bu yüzden zaten aynı kimliğin hatalarını önlemek için grup cümlesini kullanmak zorundayım.

    protected function _prepareCollection()
    {
        $store = $this->_getStore();
        $collection = Mage::getModel('catalog/product')->getCollection()
            ->addAttributeToSelect('sku')
            ->addAttributeToSelect('name')
            ->addAttributeToSelect('attribute_set_id')
            ->addAttributeToSelect('type_id')
            ->joinField('category_id',
                'catalog/category_product',
                'category_id',
                'product_id=entity_id',
                null,
                'left');
$collection->addAttributeToFilter('category_id', array('in' => array(4,10)))
            ->distinct(true);
            $collection->getSelect()->group('e.entity_id');


        if (Mage::helper('catalog')->isModuleEnabled('Mage_CatalogInventory')) {
            $collection->joinField('qty',
                'cataloginventory/stock_item',
                'qty',
                'product_id=entity_id',
                '{{table}}.stock_id=1',
                'left');
        }
        $collection->joinField('position',
                'catalog/category_product',
                'position',
                'product_id=entity_id',
                null,
                'left');
        $collection->joinField('websites',
            'catalog/product_website',
            'website_id',
            'product_id=entity_id',
            null,
            'left');
        if ($store->getId()) {
            //$collection->setStoreId($store->getId());
            $adminStore = Mage_Core_Model_App::ADMIN_STORE_ID;
            $collection->addStoreFilter($store);
            $collection->joinAttribute(
                'name',
                'catalog_product/name',
                'entity_id',
                null,
                'inner',
                $adminStore
            );

            $collection->joinAttribute(
                'custom_name',
                'catalog_product/name',
                'entity_id',
                null,
                'inner',
                $store->getId()
            );
            $collection->joinAttribute(
                'status',
                'catalog_product/status',
                'entity_id',
                null,
                'inner',
                $store->getId()
            );
            $collection->joinAttribute(
                'visibility',
                'catalog_product/visibility',
                'entity_id',
                null,
                'inner',
                $store->getId()
            );
            $collection->joinAttribute(
                'price',
                'catalog_product/price',
                'entity_id',
                null,
                'left',
                $store->getId()
            );
        }
        else {
            $collection->addAttributeToSelect('price');
            $collection->joinAttribute('status', 'catalog_product/status', 'entity_id', null, 'inner');
            $collection->joinAttribute('visibility', 'catalog_product/visibility', 'entity_id', null, 'inner');
        }

        $this->setCollection($collection);

        parent::_prepareCollection();
        $this->getCollection()->addWebsiteNamesToResult();
        return $this;
    }

Google'ım vardı ve cevap aldım ve lib/varian/data/collection/db.php

    public function getSelectCountSql()
{
     $this->_renderFilters();

        $countSelect = clone $this->getSelect();
        $countSelect->reset(Zend_Db_Select::ORDER);
        $countSelect->reset(Zend_Db_Select::LIMIT_COUNT);
        $countSelect->reset(Zend_Db_Select::LIMIT_OFFSET);
        $countSelect->reset(Zend_Db_Select::COLUMNS);

        if(count($this->getSelect()->getPart(Zend_Db_Select::GROUP)) > 0) {
            $countSelect->reset(Zend_Db_Select::GROUP);
            $countSelect->distinct(true);
            $group = $this->getSelect()->getPart(Zend_Db_Select::GROUP);
            $countSelect->columns("COUNT(DISTINCT ".implode(", ", $group).")");
        } else {
            $countSelect->columns('COUNT(*)');
        }
        return $countSelect;
}

resim açıklamasını buraya girin Ama şans yok, lütfen bunu çözmek için yardım edin


Hangi sınıfı genişletiyorsunuz? Mage_Adminhtml_Block_Widget_Grid?
B00MER

Evet uzatıyorumMage_Adminhtml_Block_Widget_Grid
Zaheerabbas

Hangi sorgu getSelectCountSql çağrısını döndürür?
Amasty

Yanıtlar:


17

Magento'da Koleksiyonlar ve Tembel Yükleme

Sayfa numaralandırmanın çalışmamasının nedeni, koleksiyonların nasıl sayıldığı ve tembel yüklemenin koleksiyonlarla nasıl çalıştığıdır.

Magento'daki koleksiyonlar sınıfı uygular Countable. Magento'daki koleksiyonların tembel olarak yüklenmesi nedeniyle, yöntem count()her çağrıldığında verilerin yüklenmesi gerekir. Bunun bir çözümü olarak, koleksiyonlar adlı bir yöntem uygular getSize(). SQL ifadenizi klonlar, içine alır COUNT()ve sonucu döndürür. Bu, bir koleksiyonun tüm verileri yüklemeden toplam sayım elde etmesini sağladı. Bu, filtreler gibi şeylerin son dakikada eklenmesini sağlar.

Bu Varien_Data_Collection_Db::getSize()ve ortağı getSelectCountSql()şöyle görünür:

/**
     * Get collection size
     *
     * @return int
     */
    public function getSize()
    {
        if (is_null($this->_totalRecords)) {
            $sql = $this->getSelectCountSql();
            $this->_totalRecords = $this->getConnection()->fetchOne($sql, $this->_bindParams);
        }
        return intval($this->_totalRecords);
    }

    /**
     * Get SQL for get record count
     *
     * @return Varien_Db_Select
     */
    public function getSelectCountSql()
    {
        $this->_renderFilters();

        $countSelect = clone $this->getSelect();
        $countSelect->reset(Zend_Db_Select::ORDER);
        $countSelect->reset(Zend_Db_Select::LIMIT_COUNT);
        $countSelect->reset(Zend_Db_Select::LIMIT_OFFSET);
        $countSelect->reset(Zend_Db_Select::COLUMNS);

        $countSelect->columns('COUNT(*)');

        return $countSelect;
    }

Temel olarak, sınırları, sütunları, sıralamayı vb. Düşürür ve filtreleri geride bırakır. Ardından COUNT()sütunlara bir MySQL ekler .

Sorun

Normalde, bir tabloda bu, toplam sayımla birlikte bir satır döndürür. Bu yüzden getSize()bir fetchOne()sorguya karşı yapar . Ancak, tablo birleştirmeleri, grup bayileri ve benzerleri gibi şeyler yaparken, bir satır döndürmezsiniz, birden çok satır döndürürsünüz. Bu nedenle getSize()koleksiyonunuzdaki yöntemi değiştirmeniz gerekir .

Çözüm

Yönteminiz şu şekilde görünmelidir:

public function getSize() {

        if ( is_null( $this->_totalRecords ) ) {
            $sql = $this->getSelectCountSql();
            // fetch all rows since it's a joined table and run a count against it.
            $this->_totalRecords = count( $this->getConnection()->fetchall( $sql, $this->_bindParams ) );
        }

        return intval( $this->_totalRecords );
    }

Bir yerine, bir PHP işlevine sarılmış fetchOne()koştu . Şimdi toplamlarınız uygun şekilde geri dönecektir.fetchAll()count()


2
Ben SE ile ilgili tüm cevapların böyle olmasını dilerdim. Bir çözüm VE biraz derinlik.
şampuan

4

Harika bir çözüm. Belki birileri yaşadığımız problemle aynıdır, bu yüzden başka bir olası çözüm göndereceğim. Bizim durumumuzda, koleksiyonun yüklendiği ızgaraya bağlı olarak bazen gruba göre bir grup içeren ve bazen de içermeyen bir koleksiyonumuz vardı. Yukarıdaki çözümü kullanarak iki sorun bulduk:

  1. Koleksiyon boşsa, boyut sıfır olmasına rağmen boyut 1 olarak değerlendirilir.
  2. GetSize yönteminin koleksiyondaki ifadeye göre grup olarak çağrılmadığı durumlarda, koleksiyonda kaç öğe olursa olsun boyut 1 olarak değerlendirilir.

Bir süre hata ayıkladıktan sonra öğrendik ki, bu durumda 1

$this->getConnection()->fetchall( $sql, $this->_bindParams ) 

0 değerine sahip bir girdi içeren bir dizi döndürür. Bu nedenle, count bulunmadığı halde count işlevi 1 değerini döndürür.

Durum 2'de aynı bölüm, değeri koleksiyonun gerçek boyutu olan bir girişli bir dizi döndürür. Count işlevi tekrar değeri değil 1 değerini döndürür.

Bir alternatif ararken, ürün koleksiyonunun getSelectCountSql () işlevinin yeniden yazılmasını kullandığını öğrendik. Bunu adapte ettik ve biraz değiştirdik, bu da bu çözümle sonuçlandı:

public function getSelectCountSql()
{
    $countSelect = parent::getSelectCountSql();
    $countSelect->reset(Zend_Db_Select::COLUMNS);
    $countSelect->reset(Zend_Db_Select::GROUP);
    $countSelect->columns('COUNT(DISTINCT item_id)');

    return $countSelect;
}

Daha önce bahsettiğim iki sorunu çözüyor ve görebildiğim kadarıyla diğer durumlar için de çalışıyor.


Ürün toplama modeline referans verdiğiniz için teşekkür ederiz. Bana yardımcı oldu.
Dinesh Yadav
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.