Magento product collection pagination with custom sort












0














I'm overriding Mage_Catalog_Block_Product_List 's _getProductCollection by adding:



foreach ($this->_productCollection as $product) {
$product->setDistance(Mage::helper('myhelper')->getDistance($product));
}


Now I want the collection to be sorted by distance, I tried the following:



 $this->_productCollection = Mage::helper('myhelper')->sortProductByDist($this->_productCollection);


The helper for sorting is like following (stolen from SO):



public function sortProductByDist($products) {

$sortedCollection = Mage::getSingleton('catalog/layer')
->getProductCollection()->addFieldToFilter('entity_id', 0);

$sortedCollection = $sortedCollection->clear();
$collectionItems = $products->getItems();
usort($collectionItems, array($this,'_sortItems'));

foreach ($collectionItems as $item) {
$sortedCollection->addItem($item);
}
return $sortedCollection;
}

protected function _sortItems($a, $b) {
$order = 'asc';
$al = strtolower($a->getDistance());
$bl = strtolower($b->getDistance());

if ($al == $bl) {
return 0;
}

if ($order == 'asc') {
return ($al < $bl) ? -1 : 1;
} else {
return ($al > $bl) ? -1 : 1;
}
}


The problem is the product collection is no longer paginated when this additional sort is applied.



Anyone knows how to fix this?










share|improve this question



























    0














    I'm overriding Mage_Catalog_Block_Product_List 's _getProductCollection by adding:



    foreach ($this->_productCollection as $product) {
    $product->setDistance(Mage::helper('myhelper')->getDistance($product));
    }


    Now I want the collection to be sorted by distance, I tried the following:



     $this->_productCollection = Mage::helper('myhelper')->sortProductByDist($this->_productCollection);


    The helper for sorting is like following (stolen from SO):



    public function sortProductByDist($products) {

    $sortedCollection = Mage::getSingleton('catalog/layer')
    ->getProductCollection()->addFieldToFilter('entity_id', 0);

    $sortedCollection = $sortedCollection->clear();
    $collectionItems = $products->getItems();
    usort($collectionItems, array($this,'_sortItems'));

    foreach ($collectionItems as $item) {
    $sortedCollection->addItem($item);
    }
    return $sortedCollection;
    }

    protected function _sortItems($a, $b) {
    $order = 'asc';
    $al = strtolower($a->getDistance());
    $bl = strtolower($b->getDistance());

    if ($al == $bl) {
    return 0;
    }

    if ($order == 'asc') {
    return ($al < $bl) ? -1 : 1;
    } else {
    return ($al > $bl) ? -1 : 1;
    }
    }


    The problem is the product collection is no longer paginated when this additional sort is applied.



    Anyone knows how to fix this?










    share|improve this question

























      0












      0








      0







      I'm overriding Mage_Catalog_Block_Product_List 's _getProductCollection by adding:



      foreach ($this->_productCollection as $product) {
      $product->setDistance(Mage::helper('myhelper')->getDistance($product));
      }


      Now I want the collection to be sorted by distance, I tried the following:



       $this->_productCollection = Mage::helper('myhelper')->sortProductByDist($this->_productCollection);


      The helper for sorting is like following (stolen from SO):



      public function sortProductByDist($products) {

      $sortedCollection = Mage::getSingleton('catalog/layer')
      ->getProductCollection()->addFieldToFilter('entity_id', 0);

      $sortedCollection = $sortedCollection->clear();
      $collectionItems = $products->getItems();
      usort($collectionItems, array($this,'_sortItems'));

      foreach ($collectionItems as $item) {
      $sortedCollection->addItem($item);
      }
      return $sortedCollection;
      }

      protected function _sortItems($a, $b) {
      $order = 'asc';
      $al = strtolower($a->getDistance());
      $bl = strtolower($b->getDistance());

      if ($al == $bl) {
      return 0;
      }

      if ($order == 'asc') {
      return ($al < $bl) ? -1 : 1;
      } else {
      return ($al > $bl) ? -1 : 1;
      }
      }


      The problem is the product collection is no longer paginated when this additional sort is applied.



      Anyone knows how to fix this?










      share|improve this question













      I'm overriding Mage_Catalog_Block_Product_List 's _getProductCollection by adding:



      foreach ($this->_productCollection as $product) {
      $product->setDistance(Mage::helper('myhelper')->getDistance($product));
      }


      Now I want the collection to be sorted by distance, I tried the following:



       $this->_productCollection = Mage::helper('myhelper')->sortProductByDist($this->_productCollection);


      The helper for sorting is like following (stolen from SO):



      public function sortProductByDist($products) {

      $sortedCollection = Mage::getSingleton('catalog/layer')
      ->getProductCollection()->addFieldToFilter('entity_id', 0);

      $sortedCollection = $sortedCollection->clear();
      $collectionItems = $products->getItems();
      usort($collectionItems, array($this,'_sortItems'));

      foreach ($collectionItems as $item) {
      $sortedCollection->addItem($item);
      }
      return $sortedCollection;
      }

      protected function _sortItems($a, $b) {
      $order = 'asc';
      $al = strtolower($a->getDistance());
      $bl = strtolower($b->getDistance());

      if ($al == $bl) {
      return 0;
      }

      if ($order == 'asc') {
      return ($al < $bl) ? -1 : 1;
      } else {
      return ($al > $bl) ? -1 : 1;
      }
      }


      The problem is the product collection is no longer paginated when this additional sort is applied.



      Anyone knows how to fix this?







      php sorting magento collections






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 12 '18 at 6:46









      Navalona Ramanantoanina

      338




      338
























          1 Answer
          1






          active

          oldest

          votes


















          0














          You are not doing it the right way, and there are no easy solutions. You need to use the database to do the sorting.



          The _productCollection is not an array, it's an object that has references, the query at this point can still be updated, the pagination will be handled by the query to the database.



          if you do a



          Mage::log((string) $this->_productCollection->getSelect()); 


          you will see the query in the logs



          What you do is to load the products of the current page, add the distance on all products of the page, and create a new collection where you force your items in. So that collection's data is not coming from the database and only contains the elements of the current page.



          Sorting using php is a bad idea, because if you have a lot of products it means you need to load them all from the database. That will be slow.



          The solution



          Calculate distance in the database directly by modifying the query.



          You can edit the select query and do the distance calculation in the database



          $this->_productCollection
          ->getSelect()
          ->columns("main.distance as distance")


          Now you can add a sort on the product collection



          $this->_productCollection->setOrder('distance');


          The complicated part will be to write the equivalent of your getDistance method in mysql. In my example I assumed distance was in the database already.



          Don't hesitate to print the query at various steps to understand what is going on.






          share|improve this answer





















          • Thanks for answering. Yes, I am aware that the method setOrder only works using a database query. Unfortunately, the method getDistance is way too complicated to be written in sql (or maybe I should dig further on this)
            – Navalona Ramanantoanina
            Nov 14 '18 at 11:02











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53257096%2fmagento-product-collection-pagination-with-custom-sort%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          0














          You are not doing it the right way, and there are no easy solutions. You need to use the database to do the sorting.



          The _productCollection is not an array, it's an object that has references, the query at this point can still be updated, the pagination will be handled by the query to the database.



          if you do a



          Mage::log((string) $this->_productCollection->getSelect()); 


          you will see the query in the logs



          What you do is to load the products of the current page, add the distance on all products of the page, and create a new collection where you force your items in. So that collection's data is not coming from the database and only contains the elements of the current page.



          Sorting using php is a bad idea, because if you have a lot of products it means you need to load them all from the database. That will be slow.



          The solution



          Calculate distance in the database directly by modifying the query.



          You can edit the select query and do the distance calculation in the database



          $this->_productCollection
          ->getSelect()
          ->columns("main.distance as distance")


          Now you can add a sort on the product collection



          $this->_productCollection->setOrder('distance');


          The complicated part will be to write the equivalent of your getDistance method in mysql. In my example I assumed distance was in the database already.



          Don't hesitate to print the query at various steps to understand what is going on.






          share|improve this answer





















          • Thanks for answering. Yes, I am aware that the method setOrder only works using a database query. Unfortunately, the method getDistance is way too complicated to be written in sql (or maybe I should dig further on this)
            – Navalona Ramanantoanina
            Nov 14 '18 at 11:02
















          0














          You are not doing it the right way, and there are no easy solutions. You need to use the database to do the sorting.



          The _productCollection is not an array, it's an object that has references, the query at this point can still be updated, the pagination will be handled by the query to the database.



          if you do a



          Mage::log((string) $this->_productCollection->getSelect()); 


          you will see the query in the logs



          What you do is to load the products of the current page, add the distance on all products of the page, and create a new collection where you force your items in. So that collection's data is not coming from the database and only contains the elements of the current page.



          Sorting using php is a bad idea, because if you have a lot of products it means you need to load them all from the database. That will be slow.



          The solution



          Calculate distance in the database directly by modifying the query.



          You can edit the select query and do the distance calculation in the database



          $this->_productCollection
          ->getSelect()
          ->columns("main.distance as distance")


          Now you can add a sort on the product collection



          $this->_productCollection->setOrder('distance');


          The complicated part will be to write the equivalent of your getDistance method in mysql. In my example I assumed distance was in the database already.



          Don't hesitate to print the query at various steps to understand what is going on.






          share|improve this answer





















          • Thanks for answering. Yes, I am aware that the method setOrder only works using a database query. Unfortunately, the method getDistance is way too complicated to be written in sql (or maybe I should dig further on this)
            – Navalona Ramanantoanina
            Nov 14 '18 at 11:02














          0












          0








          0






          You are not doing it the right way, and there are no easy solutions. You need to use the database to do the sorting.



          The _productCollection is not an array, it's an object that has references, the query at this point can still be updated, the pagination will be handled by the query to the database.



          if you do a



          Mage::log((string) $this->_productCollection->getSelect()); 


          you will see the query in the logs



          What you do is to load the products of the current page, add the distance on all products of the page, and create a new collection where you force your items in. So that collection's data is not coming from the database and only contains the elements of the current page.



          Sorting using php is a bad idea, because if you have a lot of products it means you need to load them all from the database. That will be slow.



          The solution



          Calculate distance in the database directly by modifying the query.



          You can edit the select query and do the distance calculation in the database



          $this->_productCollection
          ->getSelect()
          ->columns("main.distance as distance")


          Now you can add a sort on the product collection



          $this->_productCollection->setOrder('distance');


          The complicated part will be to write the equivalent of your getDistance method in mysql. In my example I assumed distance was in the database already.



          Don't hesitate to print the query at various steps to understand what is going on.






          share|improve this answer












          You are not doing it the right way, and there are no easy solutions. You need to use the database to do the sorting.



          The _productCollection is not an array, it's an object that has references, the query at this point can still be updated, the pagination will be handled by the query to the database.



          if you do a



          Mage::log((string) $this->_productCollection->getSelect()); 


          you will see the query in the logs



          What you do is to load the products of the current page, add the distance on all products of the page, and create a new collection where you force your items in. So that collection's data is not coming from the database and only contains the elements of the current page.



          Sorting using php is a bad idea, because if you have a lot of products it means you need to load them all from the database. That will be slow.



          The solution



          Calculate distance in the database directly by modifying the query.



          You can edit the select query and do the distance calculation in the database



          $this->_productCollection
          ->getSelect()
          ->columns("main.distance as distance")


          Now you can add a sort on the product collection



          $this->_productCollection->setOrder('distance');


          The complicated part will be to write the equivalent of your getDistance method in mysql. In my example I assumed distance was in the database already.



          Don't hesitate to print the query at various steps to understand what is going on.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 14 '18 at 10:24









          oliver de Cramer

          1865




          1865












          • Thanks for answering. Yes, I am aware that the method setOrder only works using a database query. Unfortunately, the method getDistance is way too complicated to be written in sql (or maybe I should dig further on this)
            – Navalona Ramanantoanina
            Nov 14 '18 at 11:02


















          • Thanks for answering. Yes, I am aware that the method setOrder only works using a database query. Unfortunately, the method getDistance is way too complicated to be written in sql (or maybe I should dig further on this)
            – Navalona Ramanantoanina
            Nov 14 '18 at 11:02
















          Thanks for answering. Yes, I am aware that the method setOrder only works using a database query. Unfortunately, the method getDistance is way too complicated to be written in sql (or maybe I should dig further on this)
          – Navalona Ramanantoanina
          Nov 14 '18 at 11:02




          Thanks for answering. Yes, I am aware that the method setOrder only works using a database query. Unfortunately, the method getDistance is way too complicated to be written in sql (or maybe I should dig further on this)
          – Navalona Ramanantoanina
          Nov 14 '18 at 11:02


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53257096%2fmagento-product-collection-pagination-with-custom-sort%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Full-time equivalent

          さくらももこ

          13 indicted, 8 arrested in Calif. drug cartel investigation