Question

I want to sort the categories in a Magento 2.3.1 install in alphabetical order (on the frontend!). I'm aware of the fact that you can sort it by dragging it in the Magento admin panel. But since the store I'm working on has more than 3000 categories, that's not an option. The categories also update from time to time, so it has to be a "future proof" solution.

Does anyone have an idea how to solve this? The only things I can find are for M1.

Was it helpful?

Solution

In your module di.xml (app\code\vender\module\etc\di.xml) place this line

<preference for="Magento\Catalog\Model\ResourceModel\Category" type="Vendor\Module\Model\Category"/>    

Create the file Vendor\Module\Model\Category.php and place this code in it:

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

/**
 * Catalog category model
 *
 * @author      Magento Core Team <core@magentocommerce.com>
 */
declare(strict_types=1);

namespace elastron\elcustom\Model;

/**
 * Resource model for category entity
 *
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class Category extends \Magento\Catalog\Model\ResourceModel\Category
{

    /**
     * Return child categories
     *
     * @param \Magento\Catalog\Model\Category $category
     * @return \Magento\Catalog\Model\ResourceModel\Category\Collection
     */
    public function getChildrenCategories($category)
    {
        $collection = $category->getCollection();
        /* @var $collection \Magento\Catalog\Model\ResourceModel\Category\Collection */
        $collection->addAttributeToSelect(
            'url_key'
        )->addAttributeToSelect(
            'name'
        )->addAttributeToSelect(
            'all_children'
        )->addAttributeToSelect(
            'is_anchor'
        )->addAttributeToFilter(
            'is_active',
            1
        )->addIdFilter(
            $category->getChildren()
        )->setOrder(
            'name',
            \Magento\Framework\DB\Select::SQL_ASC
        )->joinUrlRewrite();

        return $collection;
    }
}
?>

let me know if you need any assistance !

Don't forget to run upgrade, compile an clean/flush cache

OTHER TIPS

There are many solutions to this problem, Joao71's solution is simple to write and should do the trick.

In terms of best practice, preference are to be used if plugin is not possible. The reason is because if 2 modules do use the same preference, only one in the system will be eventually be used (we call this a conflict) and that is what plugin resolves.

plugin will allow you to take over any public function and yet, any further plugin on the same function will not be compromised. In your case, getChildrenCategories is a public function and that is therefore working

Finally, the solution I would offer in this instance would be to write a script / command-line that reorders the categories. This way solves the problem to do it manually but more importantly does not touch an inch on the integrity of the Magento system

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top