Làm thế nào để thêm trường động trong bộ sưu tập magento?


8

Tôi đã tạo một bộ sưu tập magento như thế này để tính khoảng cách từ lat long.

$collection = Mage::getModel('module/module')->getCollection()->addFieldToFilter('status',1);
            $collection->getSelect()->columns(array('distance' => new Zend_Db_Expr("( 6371 * acos( cos( radians(23.0130648) ) * cos( radians( latitude ) ) * cos( radians( longitude) - radians(72.4909026) ) + sin( radians(23.0130648) ) * sin( radians( latitude ) ) ) )")))
            ->having('distance <10')
            ->order('distance ' . Varien_Db_Select::SQL_ASC);

Nhưng tôi đang gặp lỗi SQLSTATE [42S22]: Không tìm thấy cột: 1054 Cột không xác định 'khoảng cách' trong 'có mệnh đề'.

Khi tôi in đối tượng bộ sưu tập Tính toán khoảng cách là đúng. Vậy vấn đề là gì?

Vấn đề của tôi tương tự như câu hỏi này Vấn đề sử dụng "có" trong bộ sưu tập Magento

Tôi đang sử dụng phân trang trên bộ sưu tập, nếu tôi loại bỏ lớp phân trang thì nó hoạt động hoàn hảo. Nhưng tôi không thể giải quyết với giải pháp được cung cấp. Đây là mã phân trang của tôi.

Trong _prepareLayout()chức năng tôi đặt cái này

$pager = $this->getLayout()->createBlock('page/html_pager', 'pager');
          $pager->setAvailableLimit(array(5=>5,10=>10,20=>20,'all'=>'all'));
          $pager->setCollection($this->getCollection());
          $this->setChild('pager', $pager);
          $this->getCollection()->load();
          return $this;

thêm chức năng này trong tập tin khối

  public function getPagerHtml()
  {
    return $this->getChildHtml('pager');
  }

và gọi nó trong tập tin phtml là <?php echo $this->getPagerHtml(); ?>

Câu trả lời:


13

Tôi có thể thử sử dụng addExpressionFieldToSelect.
Bạn có thể tìm thấy phương pháp trong Mage_Core_Model_Resource_Db_Collection_Abstract.
Trong trường hợp của bạn, nó phải là một cái gì đó như thế này: (Đây chỉ là một giả định, bạn có thể gặp một số lỗi, nhưng ý tưởng là ok)

$collection = Mage::getModel('module/module')->getCollection()->addFieldToFilter('status',1);
$collection->addExpressionFieldToSelect('distance', '( 6371 * acos( cos( radians(23.0130648) ) * cos( radians( {{latitude}}) ) * cos( radians( {{longitude}}) - radians(72.4909026) ) + sin( radians(23.0130648) ) * sin( radians( {{latitude}}) ) ) )', array('latitude'=>'latitude', 'longitude'=>'longitude'));
$collection->getSelect()->having('distance > 10');

Các addExpressionFieldToSelectcông việc như thế này:
tham số đầu tiên là bí danh của biểu thức (tên trường ảo).
Tham số thứ hai là biểu thức. Thay thế tên trường bằng giữ chỗ arround {{...}}
Tham số thứ ba là sự tương ứng giữ chỗ (không có {{}}). Trong trường hợp của bạn latitidegiữ chỗ tương ứng với latitudetrường vì vậy {{latitude}}sẽ được thay thế bằng latitude. Cùng đi cho longitude.

[EDIT]
Có một vấn đề khi thêm phân trang vào $collectionnhư thế này

$collection->setCurPage(1)->setPageSize(5);  

Đây là nền tảng của vấn đề. Khi bộ sưu tập được tải, nó được gọi _renderLimit(). Phương pháp này trông như thế này

protected function _renderLimit()
{
    if($this->_pageSize){
        $this->_select->limitPage($this->getCurPage(), $this->_pageSize);
    }

    return $this;
}

Vì vậy, cuộc gọi này getCurPage()(xem Varien_Data_Collectionlớp).
getCurPagecó một xác minh bổ sung để xem nếu số trang không nằm ngoài phạm vi tối đa để nó tính tổng số trang trong đó getLastPageNumber().
Vấn đề ở đây là Magento đặt lại các cột trong phần chọn để tính kích thước bộ sưu tập. Trong Varien_Data_Collection_Db::getSelectCountSqlđó có cái này:

$countSelect->reset(Zend_Db_Select::COLUMNS);

Bằng cách đặt lại các cột, bạn kết thúc với sql này

SELECT COUNT(*) FROM `table_name_here` AS `main_table` HAVING (distance < 10)

Đây là những gì tạo ra lỗi.

Tôi thấy 2 lựa chọn ở đây.

  1. Bạn ghi đè trong lớp bộ sưu tập của mình phương thức getSelectCountSql và xóa thiết lập lại cột:

    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);//comment this line
    
        $countSelect->columns('COUNT(*)');
    
        return $countSelect;
    }
  2. Bạn ghi đè getCurPage()phương thức để bỏ qua xác thực phạm vi:

    public function getCurPage($displacement = 0){
        if (!empty($this->_curPage)){
            return $this->_curPage + $displacement;
        }
        return 1;
    }

[CHỈNH SỬA EDIT]
Để tránh ảnh hưởng đến các mô-đun còn lại, bạn có thể ghi đè getCurPagephương thức như sau:

public function getCurPage($displacement = 0){
    if (!$this->getDirectCurPage()){//if a specific flag is not set behave as default
        return parent::getCurPage($displacement);
    }
    if (!empty($this->_curPage)){
        return $this->_curPage + $displacement;
    }
    return 1;
}

Bây giờ khi bạn muốn sử dụng havingphương thức của mình, chỉ cần thêm nó vào bộ sưu tập của bạn

$collection->setDirectCurPage(1);

Phương pháp này vẫn không hoạt động lỗi tiếp tục.
Mufaddal

Điều gì xảy ra nếu bạn loại bỏ havingcâu lệnh và vòng lặp thông qua bộ sưu tập? Bạn có thấy một giá trị distancetrong dữ liệu mục không?
Marius

vâng tôi có thể thấy một giá trị của khoảng cách mục nếu tôi loại bỏ có cluase.
Mufaddal

Điều này thật lạ. Tôi đã thử nghiệm như một bằng chứng về khái niệm trên một bộ sưu tập cốt lõi và nó hoạt động rất tốt. $collection = Mage::getModel('cms/block')->getCollection() ->addExpressionFieldToSelect('some_total', 'SUM({{is_active}})', array('is_active'=>'is_active')); $collection->getSelect()->having('some_total > 1')->order('some_total ASC');Có thể là một cái gì đó sai với mô-đun của bạn.
Marius

Một điều, tôi đang sử dụng phân trang trên bộ sưu tập để nó tạo ra vấn đề nếu tôi xóa phân trang thì các phương thức của bạn hoạt động chính xác
Mufaddal

3

Hãy thử sử dụng cái này thay thế:

$collection = Mage::getModel('module/module')->getCollection()->addFieldToFilter('status',1);
            $collection->getSelect()->columns(array('distance' => new Zend_Db_Expr("( 6371 * acos( cos( radians(23.0130648) ) * cos( radians( latitude ) ) * cos( radians( longitude) - radians(72.4909026) ) + sin( radians(23.0130648) ) * sin( radians( latitude ) ) ) )")))
            ->addAttributeHaving('distance <10')
            ->addAttributeToSort('distance', Varien_Db_Select::SQL_ASC);

nó không hoạt động, nó trả về đối tượng null
Mufaddal

0

Bạn có thể thử where()thay vì having()bạn không sử dụng bất kỳ JOINtuyên bố nào :

$collection->getSelect()->where('distance > ?', 10);

Không, nó vẫn trả về lỗi cột Không xác định 'khoảng cách' trong 'mệnh đề where
Mufaddal
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.