Magento product collection pagination with custom sort
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
add a comment |
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
add a comment |
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
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
php sorting magento collections
asked Nov 12 '18 at 6:46
Navalona Ramanantoanina
338
338
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
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.
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
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
add a comment |
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.
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
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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