0

I need to specify a prefix static string for all URLs of my Products and Categories. Just like Wordpress Woocommerce permalinks.

For example all of Categories should have product-category prefix in their URL:

  • Cat One: domain.com/product-category/cat-one
  • Cat Two (child of 'Cat One'): domain.com/product-category/cat-one/cat-two

and all of Products should have product URL prefix, no matter what their Category is:

  • Product One: domain.com/product/product-one
  • Product Two: domain.com/product/product-two

I tried to do this solution, but It's for 3 years ago and not working in Magento 2.

Also this extension is for Magento 1.x as you see.

By the way, I'm using Magento 2.1.9 with PHP 7.0.22 and XAMPP 3.2.2.

Thanks.

1

I found a good solution for this situation!

We need to make our custom module for extending Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator class with plugin methods and Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator class with preference class (because we need to change inside of its methods, not change after or before them).

Assume that our custom module created by this documentation, has <Vendor> and <Module> names.

1) So, at first we need to define our plugin and preference class in our etc/di.xml file:

<?xml version="1.0"?>   
  <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">

    <preference for="Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator" type="<Vendor>\<Module>\Model\CatalogUrlRewrite\ProductUrlPathGenerator"/>

    <type name="Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator">
      <plugin name="my_category_url_path_generator" type="<Vendor>\<Module>\Plugin\Model\CategoryUrlPathGenerator" sortOrder="15"/>
    </type>

  </config>

2) Add these classes in proper addresses:

a) Our preference class in <Vendor>\<Module>\Model\CatalogUrlRewrite\ProductUrlPathGenerator.php :

--> Change this two constant in this class for your own custom static route: <--

<?php
    namespace <Vendor>\<Module>\Model\CatalogUrlRewrite;

    class ProductUrlPathGenerator extends \Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator
    {

        // CHANGE THESE FOR CUSTOM STATIC PREFIX ROUTE of PRODUCT and PRODUCT CATEGORY
        const PRODUCT_PREFIX_ROUTE = 'product';
        const CATEGORY_PREFIX_ROUTE = 'product-category';

        /**
         * @param \Magento\Store\Model\StoreManagerInterface $storeManager
         * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
         * @param \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $categoryUrlPathGenerator
         * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
         */
        public function __construct(
            \Magento\Store\Model\StoreManagerInterface $storeManager,
            \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
            \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $categoryUrlPathGenerator,
            \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
        ) {
            parent::__construct($storeManager, $scopeConfig, $categoryUrlPathGenerator, $productRepository);
        }

        /**
         * Retrieve Product Url path (with category if exists)
         *
         * @param \Magento\Catalog\Model\Product $product
         * @param \Magento\Catalog\Model\Category $category
         *
         * @return string
         */
        public function getUrlPath($product, $category = null)
        {
            $path = $product->getData('url_path');
            if ($path === null) {
                $path = $product->getUrlKey()
                    ? $this->prepareProductUrlKey($product)
                    : $this->prepareProductDefaultUrlKey($product);
            }

            if ($category !== null) {
                $categoryUrl = str_replace(self::CATEGORY_PREFIX_ROUTE .'/','',$this->categoryUrlPathGenerator->getUrlPath($category));
                $path = $categoryUrl . '/' . $path;
            }

            return self::PRODUCT_PREFIX_ROUTE . '/' . $path;
        }
    }

b ) Our plugin class in <Vendor>\<Module>\Plugin\Model\CategoryUrlPathGenerator.php :

<?php
namespace <Vendor>\<Module>\Plugin\Model;


class CategoryUrlPathGenerator
{
    /**
    * Add a static prefix to category URL path
    *
    * @param \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $subject
    * @param $path
    * @return string
    */
    public function afterGetUrlPath(\Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $subject, $path)
    {
        if (strpos($path, \<Vendor>\<Module>\Model\CatalogUrlRewrite\ProductUrlPathGenerator::CATEGORY_PREFIX_ROUTE) === false)
            $path = \<Vendor>\<Module>\Model\CatalogUrlRewrite\ProductUrlPathGenerator::CATEGORY_PREFIX_ROUTE . $path;

        return $path;
    }
}

3) Run this command:

php bin/magento setup:upgrade

And its DONE!, now you can create products and their categories and you'll see the url rewrites that created with these static url prefixes.

DO NOT forget to change <Vendor>,<Module> with your own custom module names and change the constants of ProductUrlPathGenerator class for change to your custom static prefixes.

Good luck.

  • Hello @Mehran. Can you please let me know why you have used strpos with prefix and path in CategoryUrlPathGenerator plugin? I am not getting it. Otherwise, this solution works fine. – Patrick W Sep 27 '18 at 9:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.