Magento koleksiyonunda “sahip olmak” sorunu


20

Magento yönetici modülünde bir ızgara için özel bir koleksiyon oluşturmaya çalışıyorum. Ben sadece aşağıdakileri yapar "addAttributeHaving" adlı yeni bir toplama yöntemi oluşturduk:

public function addAttributeHaving($value)
{
    $this->getSelect()->having($value);
    return $this;
}

Koleksiyon koduna bakın:

$collection->addFieldToSelect(
    array(
        'entity_id',
        'created_at',
        'increment_id',
        'customer_email',
        'customer_firstname',
        'customer_lastname',
        'grand_total',
        'status'
    )
);

$collection->getSelect()->joinLeft(array('sfop' => 'sales_flat_order_payment'), 'main_table.entity_id = sfop.parent_id', 'sfop.amount_authorized');
$collection->getSelect()->columns('sum(sfop.amount_authorized) AS AUTHD');
$collection->getSelect()->columns('grand_total - sum(sfop.amount_authorized) AS DIF_AU');
$collection->addFieldToFilter('main_table.state', array('in' => array('new','payment_review')));
$collection->addFieldToFilter('main_table.sd_order_type', array('neq' => 7));
$collection->addFieldToFilter('sfop.method', array('neq' => 'giftcard'));
$collection->addFieldToFilter('main_table.created_at', array('gt' => $this->getFilterDate()));
$collection->getSelect()->group(array('main_table.entity_id'));
$collection->addAttributeHaving('DIF_AU <> 0');
$collection->load(true,true);

$this->setCollection($collection);

Bu, Magento'nun dışında çalıştırıldığında mükemmel bir şekilde çalışan ve beklenen sonuçları üreten aşağıdaki SQL'i üretir.

[METHOD=Varien_Data_Collection_Db->printLogQuery] SELECT `main_table`.`entity_id`, `main_table`.`entity_id`, `main_table`.`created_at`, `main_table`.`increment_id`, `main_table`.`customer_email`, `main_table`.`customer_firstname`, `main_table`.`customer_lastname`, `main_table`.`grand_total`, `main_table`.`status`, `sfop`.`amount_authorized`, sum(sfop.amount_authorized) AS `AUTHD`, grand_total - sum(sfop.amount_authorized) AS `DIF_AU` FROM `sales_flat_order` AS `main_table` LEFT JOIN `sales_flat_order_payment` AS `sfop` ON main_table.entity_id = sfop.parent_id WHERE (main_table.state in ('new', 'payment_review')) AND (main_table.sd_order_type != 7) AND (sfop.method != 'giftcard') AND (main_table.created_at > '2013-04-07') GROUP BY `main_table`.`entity_id` HAVING (DIF_AU <> 0)

Ancak, Magento içindeki ızgarayı yüklemeye çalıştığımda aşağıdaki hatayı alıyorum:

SQLSTATE [42S22]: Sütun bulunamadı: 1054 'sahiplik maddesi' içinde bilinmeyen 'DIF_AU' sütunu

Ayrıca, sahip olan yan tümceyi kaldırırsam (ki bu da sonuçlarımı bozar), ızgarada bir veri kaynağı için DIF_AU sütununu kullanabilirsiniz.


1
GÜNCELLEME: Sorunu üst getSelectCountSql () yöntemine kadar takip edebildim. Aslında bu, toplama sayısını almaya çalışırken sorunun meydana geldiği yerdir.
Anthony Leach Jr

1
Bir cevap gönderin! WTH sd_order_typenereden geliyor?
Benmarks

1
Düz tablolara eklenen çok gizli özel sipariş türü şeyler. Hala cevabı üzerinde çalışıyorum.
Anthony Leach Jr7

1
"10'dan az üne sahip kullanıcılar, sorduktan sonra 8 saat boyunca kendi sorularını cevaplayamazlar. 7 saat içinde cevap verebilirsiniz. O zamana kadar lütfen yorumları kullanın veya bunun yerine sorunuzu düzenleyin." (çözelti 7 saat içinde gelir).
Anthony Leach Jr7

1
Birisi bu adama bir oy verin
benmarks

Yanıtlar:


12

Aslında burada kendi soruma cevap vereceğim. Biliyorum, yapışkan, ama gerçek yığın izine çok daha yakından bakarken cevabın üzerine tökezledim. Koleksiyon iyi yükleniyor, ancak Varien_Data_Collection_Db :: getSelectCountSql () ' de toplama sayısını almaya çalıştığınızda hata biraz sonra yürütme geliyor . Bundan üretilen SQL:

SELECT COUNT(*) FROM sales_flat_order AS main_table LEFT JOIN sales_flat_order_payment AS sfop ON main_table.entity_id = sfop.parent_id WHERE (main_table.state in ('payment_review')) AND (main_table.sd_order_type != 7) AND (sfop.method != 'giftcard') AND (main_table.created_at > '2013-04-07') GROUP BY main_table.entity_id HAVING (DIF_AU <> 0)

HAVING ifadesinin eklendiğini göreceksiniz, ancak DIF_AU sütunu için artık tanımımız yok. Sanırım doğru kayıt sayısını elde etmek için koleksiyon sınıfımda özel bir getSelectCountSql () genişletmek gerekecek gibi görünüyor.

I have having deyimi için gerekli eksik sütunda geri ekler özel toplama sınıfında genişletilmiş getSelectCountSql () oluşturduk.


public function getSelectCountSql()
  {
    $countSelect = parent::getSelectCountSql();
    $countSelect->columns('grand_total - sum(sfop.amount_authorized) AS DIF_AU');
    $countSelect->reset(Zend_Db_Select::GROUP);
    return $countSelect;
  }

1
Hiç yapışkan değil… İlk önce çözümü bulursanız, teşvik edilir. Diğerleri potansiyel olarak yol boyunca yararlı bulacaktır. +1 :)
davidalger

Bir hata raporu sunmalısınız! magentocommerce.com/bug-tracking
benmarks

Bu da benim de gördüğüm ve cevap bulmakta başarılı olduğum bir konudur. Ancak, çözümünüzün doğru olduğunu düşünmüyorum - group by kullandığınız için, SelectCountSql grubunuzun grup sayısını döndürmesi gerekiyor. Yani bir sayıya ihtiyacınız var (fetchAll ()) veya sorgunuzu count(distinct main_table.entity_id)yerine yeniden yazmak içincount(*)
Benubird

Bence çok haklısın. Bu proje, bu görevden bu yana arka brülörde ve şimdi geri dönüyor. Geçen hafta bir demoda, şebekede yanlış kayıt sayısının bildirildiğini fark ettim. Çözdüğümde bulgularımı rapor edeceğim.
Anthony Leach Jr

Bulgularınızla ilgili herhangi bir haber var mı?
Simon

0

Her şeyden önce koleksiyonunuzdan $countSelect->reset(Zend_Db_Select::HAVING);sıfırlanacak demektir HAVING. Bu, sahip olması gereken maddeyi kaldıracağı anlamına gelir. Ve istediğin bu değil. Koleksiyona eklemek isteyebilirsiniz ( app/code/core/Mage/Catalog/Model/Resource/Product/Collection.php->_getSelectCountSql()burada.)

Ama asıl suçlu dosyada getSize()var olan yöntem lib/Varien/Data/Collection/Db.php.

@Anthony tarafından belirtilen yukarıdaki çözümü denedim ama işe yaramadı.

Şimdi aşağıdakileri yaptım.

public function getSize()
{
    if (is_null($this->_totalRecords)) {
        //$sql = $this->getSelectCountSql();
        $sql = $this->getSelect();
        $this->_totalRecords = count($this->getConnection()->fetchAll($sql, $this->_bindParams));
    }
    return intval($this->_totalRecords);
}

Ben bile kullanmıyorum kontrol edin getSelectCountSql(). Ben sadece tüm SQL QUERY okuyorum ve tüm veri getiriliyor ve sayısını döndürüyorum . Bu kadar.


0

Bu sorunu burada çözdüm: app / code / core / Mage / Katalog / Model / Kaynak / Ürün / Koleksiyon.php: 943 bunu ekleyin: $ select-> reset (Zend_Db_Select :: HAVING);

Sadece app / code / core / Mage / Katalog / Model / Kaynak / Ürün / Collection.php dosyasını app / code / local / Mage / Katalog / Model / Resource / Product / Collection.php dosyasına kopyalayın

Kodum şimdi şöyle görünüyor:

/**
 * Build clear select
 *
 * @param Varien_Db_Select $select
 * @return Varien_Db_Select
 */
protected function _buildClearSelect($select = null)
{
    if (is_null($select)) {
        $select = clone $this->getSelect();
    }
    $select->reset(Zend_Db_Select::ORDER);
    $select->reset(Zend_Db_Select::LIMIT_COUNT);
    $select->reset(Zend_Db_Select::LIMIT_OFFSET);
    $select->reset(Zend_Db_Select::COLUMNS);
    $select->reset(Zend_Db_Select::HAVING);

0

Alt sorgu seçme listesindeki sütunların benzersiz adları olması gerektiğinden, bu çözüm seçiminizin benzersiz sütun adları varsa çalışır

Alt sorgu: tablo alt sorgusu yinelenen sütun adlarına izin verir

public function getSelectCountSql()
{
    $this->_renderFilters();
    $select = clone $this->getSelect();
    $select->reset(Zend_Db_Select::ORDER);
    $select->reset(Zend_Db_Select::LIMIT_COUNT);
    $select->reset(Zend_Db_Select::LIMIT_OFFSET);        

    $countSelect = clone $this->getSelect();
    $countSelect->reset();
    $countSelect->from(array('a' => $select), 'COUNT(*)');
    return $countSelect;
}

Not: Bu cevap genel magento koleksiyonları içindir. sadece ürün koleksiyonu ile ilgili değildir.


0

Bu çalışıyor

public function getSize () {if (is_null ($ this -> _ totalRecords)) {// $ sql = $ this-> getSelectCountSql (); $ sql = $ this-> getSelect (); $ this -> _ totalRecords = count ($ this-> getConnection () -> fetchAll ($ sql, $ this -> _ bindParams)); } dönüş aralığı ($ this -> _ totalRecords); }

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.