Question

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.

Was it helpful?

Solution

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.

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