/ #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>
  1. Додаємо до адмінки опцію для додавання/вилучення списку батьківських категорій в 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>
  1. Робимо хелпер для можливості отримати значення налаштування з адмін-панелі

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;
    }
}
  1. Створюємо 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

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

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