/ #magento 

Вилучення ієрархії категорій з URL в Magento 2

В Magento 2 є налаштування, яке дозволяє не показувати категорії для адрес товарів: Stores > Configuration > General > Catalog > Catalog > Search Engine Optimization > Use Categories Path for Product URLs howto-remove-parent-category-from-url-magento-2-1-1

Результатом буде отримання URL виду https://mysite.com/product1.html замість https://mysite.com/category1/category2/product1.html. На жаль для категорій такої можливості не передбачено і не можна отримати https://mysite.com/category2.

За генерацію URL категорій відповідає клас Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator.

public function getUrlPath($category, $parentCategory = null)
{
...
    if ($this->isNeedToGenerateUrlPathForParent($category)) {
        $parentCategory = $parentCategory === null ?
            $this->categoryRepository->get($category->getParentId(), $category->getStoreId()) : $parentCategory;
        $parentPath = $this->getUrlPath($parentCategory);
        $path = $parentPath === '' ? $path : $parentPath . '/' . $path;
    }
...
}

Створимо around-плагін для вимкнення та увімкнення ціїє умови в залежності від налаштувань в адмінці Magento.

  1. Створюємо заготовку для модуля в директорії Noon/CategoryUrlPathGenerator

    registration.php

    <?php
    \Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
        'Noon_CategoryUrlPathGenerator',
        __DIR__
    );
    

    etc/module.xml

    <?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
        <module name="Noon_CategoryUrlPathGenerator" setup_version="0.1.0" />
    </config>
    
  2. Додаємо до адмінки опцію для додавання/вилучення списку батьківських категорій в URL

    etc/adminhtml/system.xml

    <?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
        <system>
            <section id="catalog">
                <group id="seo">
                    <field id="category_use_parent_categories" translate="label" type="select" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
                        <label>Use Parent Category Path for Category URLs</label>
                        <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                    </field>
                </group>
            </section>
        </system>
    </config>
    

    Результатом буде такий вигляд адмінки howto-remove-parent-category-from-url-magento-2-2

    Задаємо значення No на замовчання

    etc/config.xml

    <?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
        <default>
            <catalog>
                <seo>
                    <category_use_parent_categories>0</category_use_parent_categories>
                </seo>
            </catalog>
        </default>
    </config>
    
  3. Робимо хелпер для можливості отримати значення налаштування з адмін-панелі

    Helper/Data.php

    <?php
    namespace Noon\CategoryUrlPathGenerator\Helper;
    
    class Data extends \Magento\Framework\App\Helper\AbstractHelper
    {
        const XML_PATH_CATEGORY_USE_PARENT_CATEGORIES = 'catalog/seo/category_use_parent_categories';
    
        /**
        *
        * @var \Magento\Framework\App\Config\ScopeConfigInterface
        */
        protected $scopeConfig;
    
        /**
        *
        * @param \Magento\Framework\App\Helper\Context $context
        * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
        */
        public function __construct(
            \Magento\Framework\App\Helper\Context $context,
            \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
        ) {
            parent::__construct($context);
            $this->scopeConfig = $scopeConfig;
        }
    
        /**
        *
        * @return boolean
        */
        public function useParentCategoties()
        {
            if ($this->scopeConfig->getValue(self::XML_PATH_CATEGORY_USE_PARENT_CATEGORIES, \Magento\Store\Model\ScopeInterface::SCOPE_STORE)) {
                return true;
            }
            return false;
        }
    }
    
  4. Створюємо around-плагін

    etc/di.xml

    <?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
        <type name="Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator">
            <plugin name="noon_category_url_path_generator" type="\Noon\CategoryUrlPathGenerator\Plugin\Model\CategoryUrlPathGenerator" sortOrder="0" />
        </type>
    </config>
    

    Plugin/Model/CategoryUrlPathGenerator.php

    <?php
    
    namespace Noon\CategoryUrlPathGenerator\Plugin\Model;
    
    use Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator;
    use Magento\Catalog\Api\CategoryRepositoryInterface;
    use Magento\Catalog\Model\Category;
    
    class CategoryUrlPathGenerator
    {
        protected $helper;
    
        public function __construct(
            \Noon\CategoryUrlPathGenerator\Helper\Data $helper
        ){
            $this->helper = $helper;
        }
    
        /**
        *
        * @param \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $subject
        * @param $path
        * @return string
        */
        public function aroundGetUrlPath(\Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $subject, $proceed, $category)
        {
    
            if (in_array($category->getParentId(), [Category::ROOT_CATEGORY_ID, Category::TREE_ROOT_ID])) {
                return '';
            }
            $path = $category->getUrlPath();
            if ($path !== null && !$category->dataHasChangedFor('url_key') && !$category->dataHasChangedFor('parent_id')) {
                return $path;
            }
            $path = $category->getUrlKey();
            if ($path === false) {
                return $category->getUrlPath();
            }
            if ($this->helper->useParentCategoties() && $this->isNeedToGenerateUrlPathForParent($category)) {
                $parentPath = $this->getUrlPath(
                    $this->categoryRepository->get($category->getParentId(), $category->getStoreId())
                );
                $path = $parentPath === '' ? $path : $parentPath . '/' . $path;
            }
            return $path;
    
        }
    
    }
    

Даний плагін дозволить генерувати потрібні URL для всіх новостворених категорій.

Репозиторій плагіна - https://github.com/alex-79/magento2-category-url-path-generator.

Що робити якщо дерево категорій вже створено? Тут я рекомендую скористатись модулем https://github.com/elgentos/regenerate-catalog-urls і перегенерувати path та url.

php bin/magento regenerate:category:path
php bin/magento regenerate:category:url

Посилання

Author

Олександр Бобилєв

Залишаю собі право використовувати ненормативну (але інформативну) лексику там, де звичайні слова втрачають сенс і не відображають всієї палітри почуттів, від споглядання навколишньої дійсності.