7

I would like to add a Product Prefix (Static Path) to product URLs.

Something like www.test.com/product-prefix/product1.html

So all products url of the website follows the same structure - www.test.com/product-prefix/product2.html

Where product-prefix is a static product-prefix.

I want to add it as statically , no url rewrite concept.

I have checked core ProductUrlPathGenerator.php but not getting exact solution. Can anybody help and suggest the better way ?

Magento Version - 2.2

  • Thanks for your solution I did the same way but its not working for me I am using magento 2.2.6 version. Can you please help me on it. – Anurag Rana Feb 6 at 20:30
6

After debugging of couple of hours i have resolved this issue by following below method.

I have override two files in my custom module, One is Product Url Model and Another one is Router Controller\Router

Below is the di.xml

<preference for="Magento\Catalog\Model\Product\Url" type="Vendor\ModuleName\Model\Url" />
<preference for="Magento\UrlRewrite\Controller\Router" type="Vendor\ModuleName\Controller\Router" />

Code for Url.php

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

/**
 * Product Url model
 *
 * @author     Magento Core Team <core@magentocommerce.com>
 */
namespace Vendor\ModuleName\Model;

use Magento\UrlRewrite\Model\UrlFinderInterface;
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;

class Url extends \Magento\Catalog\Model\Product\Url
{
    /**
     * URL instance
     *
     * @var \Magento\Framework\UrlFactory
     */
    protected $urlFactory;

    /**
     * @var \Magento\Framework\Filter\FilterManager
     */
    protected $filter;

    /**
     * Store manager
     *
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $storeManager;

    /**
     * @var \Magento\Framework\Session\SidResolverInterface
     */
    protected $sidResolver;

    /** @var UrlFinderInterface */
    protected $urlFinder;

    /**
     * @param \Magento\Framework\UrlFactory $urlFactory
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     * @param \Magento\Framework\Filter\FilterManager $filter
     * @param \Magento\Framework\Session\SidResolverInterface $sidResolver
     * @param UrlFinderInterface $urlFinder
     * @param array $data
     */
    public function __construct(
        \Magento\Framework\UrlFactory $urlFactory,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\Filter\FilterManager $filter,
        \Magento\Framework\Session\SidResolverInterface $sidResolver,
        UrlFinderInterface $urlFinder,
        array $data = []
    ) {
        parent::__construct($urlFactory, $storeManager, $filter, $sidResolver, $urlFinder, $data);
        $this->urlFactory = $urlFactory;
        $this->storeManager = $storeManager;
        $this->filter = $filter;
        $this->sidResolver = $sidResolver;
        $this->urlFinder = $urlFinder;
    }

    /**
     * Retrieve URL Instance
     *
     * @return \Magento\Framework\UrlInterface
     */
    private function getUrlInstance()
    {
        return $this->urlFactory->create();
    }

    /**
     * Retrieve URL in current store
     *
     * @param \Magento\Catalog\Model\Product $product
     * @param array $params the URL route params
     * @return string
     */
    public function getUrlInStore(\Magento\Catalog\Model\Product $product, $params = [])
    {
        $params['_scope_to_url'] = true;
        return $this->getUrl($product, $params);
    }

    /**
     * Retrieve Product URL
     *
     * @param  \Magento\Catalog\Model\Product $product
     * @param  bool $useSid forced SID mode
     * @return string
     */
    public function getProductUrl($product, $useSid = null)
    {
        if ($useSid === null) {
            $useSid = $this->sidResolver->getUseSessionInUrl();
        }

        $params = [];
        if (!$useSid) {
            $params['_nosid'] = true;
        }

        return $this->getUrl($product, $params);
    }

    /**
     * Format Key for URL
     *
     * @param string $str
     * @return string
     */
    public function formatUrlKey($str)
    {
        return $this->filter->translitUrl($str);
    }

    /**
     * Retrieve Product URL using UrlDataObject
     *
     * @param \Magento\Catalog\Model\Product $product
     * @param array $params
     * @return string
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     * @SuppressWarnings(PHPMD.NPathComplexity)
     */
    public function getUrl(\Magento\Catalog\Model\Product $product, $params = [])
    {
        $routePath = '';
        $routeParams = $params;

        $storeId = $product->getStoreId();

        $categoryId = null;

        if (!isset($params['_ignore_category']) && $product->getCategoryId() && !$product->getDoNotUseCategoryId()) {
            $categoryId = $product->getCategoryId();
        }

        if ($product->hasUrlDataObject()) {
            $requestPath = $product->getUrlDataObject()->getUrlRewrite();
            $routeParams['_scope'] = $product->getUrlDataObject()->getStoreId();
        } else {
            $requestPath = $product->getRequestPath();
            if (empty($requestPath) && $requestPath !== false) {
                $filterData = [
                    UrlRewrite::ENTITY_ID => $product->getId(),
                    UrlRewrite::ENTITY_TYPE => \Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator::ENTITY_TYPE,
                    UrlRewrite::STORE_ID => $storeId,
                ];
                if ($categoryId) {
                    $filterData[UrlRewrite::METADATA]['category_id'] = $categoryId;
                }
                $rewrite = $this->urlFinder->findOneByData($filterData);
                if ($rewrite) {
                    $requestPath = $rewrite->getRequestPath();
                    $product->setRequestPath($requestPath);
                } else {
                    $product->setRequestPath(false);
                }
            }
        }

        if (isset($routeParams['_scope'])) {
            $storeId = $this->storeManager->getStore($routeParams['_scope'])->getId();
        }

        if ($storeId != $this->storeManager->getStore()->getId()) {
            $routeParams['_scope_to_url'] = true;
        }

        if (!empty($requestPath)) {
            $routeParams['_direct'] = $requestPath;
        } else {
            $routePath = 'catalog/product/view';
            $routeParams['id'] = $product->getId();
            $routeParams['s'] = $product->getUrlKey();
            if ($categoryId) {
                $routeParams['category'] = $categoryId;
            }
        }

        // reset cached URL instance GET query params
        if (!isset($routeParams['_query'])) {
            $routeParams['_query'] = [];
        }
$baseUrl = $this->storeManager->getStore()->getBaseUrl();
        $productUrl = $this->getUrlInstance()->setScope($storeId)->getUrl($routePath, $routeParams);

        $remainingUrl = str_replace($baseUrl, '', $productUrl);

        $productUrl = $baseUrl."your-static-prefix/" . $remainingUrl;
        //return $this->getUrlInstance()->setScope($storeId)->getUrl($routePath, $routeParams);
        return $productUrl;
    }
}

Code for Controller Router.php

<?php
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Vendor\ModuleName\Controller;

use Magento\UrlRewrite\Controller\Adminhtml\Url\Rewrite;
use Magento\UrlRewrite\Model\OptionProvider;
use Magento\UrlRewrite\Model\UrlFinderInterface;
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;

/**
 * UrlRewrite Controller Router
 */
class Router implements \Magento\Framework\App\RouterInterface
{
    /** var \Magento\Framework\App\ActionFactory */
    protected $actionFactory;

    /** @var \Magento\Framework\UrlInterface */
    protected $url;

    /** @var \Magento\Store\Model\StoreManagerInterface */
    protected $storeManager;

    /** @var \Magento\Framework\App\ResponseInterface */
    protected $response;

    /** @var UrlFinderInterface */
    protected $urlFinder;

    /**
     * @param \Magento\Framework\App\ActionFactory $actionFactory
     * @param \Magento\Framework\UrlInterface $url
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     * @param \Magento\Framework\App\ResponseInterface $response
     * @param UrlFinderInterface $urlFinder
     */
    public function __construct(
        \Magento\Framework\App\ActionFactory $actionFactory,
        \Magento\Framework\UrlInterface $url,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\App\ResponseInterface $response,
        UrlFinderInterface $urlFinder
    ) {
        $this->actionFactory = $actionFactory;
        $this->url = $url;
        $this->storeManager = $storeManager;
        $this->response = $response;
        $this->urlFinder = $urlFinder;
    }

    /**
     * Match corresponding URL Rewrite and modify request
     *
     * @param \Magento\Framework\App\RequestInterface $request
     * @return \Magento\Framework\App\ActionInterface|null
     */
    public function match(\Magento\Framework\App\RequestInterface $request)
    {
        if ($fromStore = $request->getParam('___from_store')) {
            $oldStoreId = $this->storeManager->getStore($fromStore)->getId();
            $oldRewrite = $this->getRewrite($request->getPathInfo(), $oldStoreId);
            if ($oldRewrite) {
                $rewrite = $this->urlFinder->findOneByData(
                    [
                        UrlRewrite::ENTITY_TYPE => $oldRewrite->getEntityType(),
                        UrlRewrite::ENTITY_ID => $oldRewrite->getEntityId(),
                        UrlRewrite::STORE_ID => $this->storeManager->getStore()->getId(),
                        UrlRewrite::IS_AUTOGENERATED => 1,
                    ]
                );
                if ($rewrite && $rewrite->getRequestPath() !== $oldRewrite->getRequestPath()) {
                    return $this->redirect($request, $rewrite->getRequestPath(), OptionProvider::TEMPORARY);
                }
            }
        }
        //Below i have replaced static prefix

        $replaceUrl = str_replace("your-static-prefix/", "", $request->getPathInfo());
        $rewrite = $this->getRewrite($replaceUrl, $this->storeManager->getStore()->getId());

        //$rewrite = $this->getRewrite($request->getPathInfo(), $this->storeManager->getStore()->getId());

        // CODE FOR CATEGORY REWRITE
        if ($rewrite === null) 
        {
            $pathInfo = $request->getPathInfo();
            $pathInfoArray = explode("/", $pathInfo);

            $key = "";
            if(!empty(trim($pathInfoArray[count($pathInfoArray) - 1])))
                $key = trim($pathInfoArray[count($pathInfoArray) - 1]);
            elseif(!empty(trim($pathInfoArray[count($pathInfoArray) - 2])))
                $key = trim($pathInfoArray[count($pathInfoArray) - 2]);

            if($key != "")
            {
                $objectManaer = \Magento\Framework\App\ObjectManager::getInstance();
                $category = $objectManaer->create('Magento\Catalog\Model\Category');
                $collection = $category->getCollection()->addAttributeToFilter('url_key', ['like' => '%' . $key . '%']);

                if($collection->count())
                {
                    $category = $collection->getFirstItem();
                    $path = $category->getPath();
                    $pathArray = explode("/", $category->getPath());

                    foreach(['1', '2', $category->getId()] as $del_val)
                    {
                        if (($categoryId = array_search($del_val, $pathArray)) !== false) {
                            unset($pathArray[$categoryId]);
                        }
                    }

                    $keyArray = [];
                    if(count($pathArray))
                    {
                        foreach($pathArray as $pathId)
                        {
                            $pathCategory = $objectManaer->create('Magento\Catalog\Model\Category')->load($pathId);
                            $keyArray[] = $pathCategory->getUrlKey();
                        }
                    }

                    $keyArray[] = $category->getUrlKey();
                    $key = implode("/", $keyArray);
                    $key = '/' . $key;
                    $rewrite = $this->getRewrite($key, $this->storeManager->getStore()->getId());
                }
            }
        }

        if ($rewrite === null) {
            return null;
        }

        if ($rewrite->getRedirectType()) {
            return $this->processRedirect($request, $rewrite);
        }

        $request->setAlias(\Magento\Framework\UrlInterface::REWRITE_REQUEST_PATH_ALIAS, $rewrite->getRequestPath());
        $request->setPathInfo('/' . $rewrite->getTargetPath());
        return $this->actionFactory->create('Magento\Framework\App\Action\Forward');
    }

    /**
     * @param \Magento\Framework\App\RequestInterface $request
     * @param UrlRewrite $rewrite
     * @return \Magento\Framework\App\ActionInterface|null
     */
    protected function processRedirect($request, $rewrite)
    {
        $target = $rewrite->getTargetPath();
        if ($rewrite->getEntityType() !== Rewrite::ENTITY_TYPE_CUSTOM
            || ($prefix = substr($target, 0, 6)) !== 'http:/' && $prefix !== 'https:'
        ) {
            $target = $this->url->getUrl('', ['_direct' => $target]);
        }
        return $this->redirect($request, $target, $rewrite->getRedirectType());
    }

    /**
     * @param \Magento\Framework\App\RequestInterface $request
     * @param string $url
     * @param int $code
     * @return \Magento\Framework\App\ActionInterface
     */
    protected function redirect($request, $url, $code)
    {
        $this->response->setRedirect($url, $code);
        $request->setDispatched(true);
        return $this->actionFactory->create('Magento\Framework\App\Action\Redirect');
    }

    /**
     * @param string $requestPath
     * @param int $storeId
     * @return UrlRewrite|null
     */
    protected function getRewrite($requestPath, $storeId)
    {
        return $this->urlFinder->findOneByData([
            UrlRewrite::REQUEST_PATH => trim($requestPath, '/'),
            UrlRewrite::STORE_ID => $storeId,
        ]);
    }
}
  • This is very good. – Purushotam Sangroula Dec 25 '17 at 7:25
  • @Manthan - will your solution work, if i want to add a custom attribute value (let's say, "brand") as prefix to product url ? – Manashvi Birla Feb 11 at 10:11
  • @ManashviBirla - Yes , it might work - have you tried the same – Manthan Dave Feb 19 at 11:00

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.