2

I am using Magento ver. 2.2.3 . I need to add a custom attribute's (brand) value to the product url, like :

http://domain.com/smeg/smeg-cooker-90cm-with-gas-hob-cream.html

For that i have overridden the frontend product model & router, but nothing works. Can anyone suggest the solution. ?

etc/frontend/di.xml

<preference for="Magento\Catalog\Model\Product\Url"  type="Company\Module\Model\Url" />

<preference for="Magento\UrlRewrite\Controller\Router"  type="Company\Module\Controller\Router" />

Company\Module\Model\Url.php

<?php

namespace Company\Module\Model;

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

class Url extends \Magento\Catalog\Model\Product\Url
{
    protected $urlFactory;
    protected $storeManager;

    public function __construct(
        \Magento\Framework\UrlFactory $urlFactory,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\Filter\FilterManager $filter,
        \Magento\Framework\Session\SidResolverInterface $sidResolver,
        UrlFinderInterface $urlFinder
    ) {
        parent::__construct($urlFactory, $storeManager, $filter, $sidResolver, $urlFinder);
        $this->urlFactory = $urlFactory;
        $this->storeManager = $storeManager;
    }
    public function getUrl(\Magento\Catalog\Model\Product $product, $params = [])
    {
        $requestPath = $product->getRequestPath();  
        if (!empty($requestPath))
        {
             $params['_direct'] = $requestPath;
        }
        $baseUrl = $this->storeManager->getStore()->getBaseUrl();
        $productUrl = $this->getUrlInstance()->setScope($product->getStoreId())->getUrl(' ',$params);
        $_attributeValue = $product->getResource()->getAttribute('manufacturer')->getFrontend()->getValue($product);
        $remainingUrl = str_replace($baseUrl, '', $productUrl);

        $productUrl = $baseUrl. $_attributeValue . "/" . $remainingUrl;
        return $productUrl;
    }
    private function getUrlInstance()
    {
        return $this->urlFactory->create();
    }
}

Company\Module\Controller\Router.php

<?php

namespace Company\Module\Controller;

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

class Router implements \Magento\Framework\App\RouterInterface
{
    protected $actionFactory;
    protected $storeManager;
    protected $urlFinder;
    public function __construct(
        \Magento\Framework\App\ActionFactory $actionFactory,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        UrlFinderInterface $urlFinder
    ) {
        $this->actionFactory = $actionFactory;
        $this->storeManager = $storeManager;
        $this->urlFinder = $urlFinder;
    } 
    public function match(\Magento\Framework\App\RequestInterface $request)
    {
        $identifier = trim($request->getPathInfo(), '/');
        $identifier = explode("/", $identifier);

        if(isset($identifier[0]) && !empty($identifier[0])) {
            $urlKey = str_replace('.html', '', $identifier[0]);

            if($urlKey) {   
                $objectManager     = \Magento\Framework\App\ObjectManager::getInstance();

                $collection        = $objectManager->create('Magento\Catalog\Model\ResourceModel\Product\Collection');

                $productcollection = $collection->addAttributeToSelect('*')
                    ->addAttributeToFilter(
                    [
                        ['attribute' => 'url_key', 'eq' => $urlKey], 
                    ]
                );
                $productInfo = $productcollection->getData();
                if(isset($productInfo) && !empty($productInfo)) {
                    $productId = $productInfo[0]['entity_id'];
                    $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
                    $product = $objectManager->create('Magento\Catalog\Model\Product')->load($productId);
                    $brand = $product->getResource()->getAttribute('manufacturer')->getFrontend()->getValue($product);
                    $brandUrl = $brand . "/";

                    $replaceUrl = str_replace($brandUrl, "", $request->getPathInfo());
                    $rewrite = $this->getRewrite($replaceUrl, $this->storeManager->getStore()->getId());    
                    if ($rewrite == null)
                    {
                        return null;
                    }
                    $request->setAlias(\Magento\Framework\UrlInterface::REWRITE_REQUEST_PATH_ALIAS, $rewrite->getRequestPath());
                    $request->setPathInfo('/' . $rewrite->getTargetPath());
                    return $this->actionFactory->create('Magento\Framework\App\Action\Forward');
                }
            }
        }
    }
    protected function getRewrite($requestPath, $storeId)
    {
        return $this->urlFinder->findOneByData([
            UrlRewrite::REQUEST_PATH => trim($requestPath, '/'),
            UrlRewrite::STORE_ID => $storeId,
        ]);
    }
}
6
  • Just to get sure what your situation is: You have a rewrite for your product with request_path "smeg-cooker-90cm-with-gas-hob-cream.html" in the database. That product has the urlkey "smeg-cooker-90cm-with-gas-hob-cream" and you want that domain.com/smeg/smeg-cooker-90cm-with-gas-hob-cream.html route to that product page. Right? If not, please correct me.
    – HelgeB
    Commented Feb 11, 2019 at 12:57
  • I want that the request path 'catalog/product/view/id/2417/' should redirect to target path 'smeg/smeg-cooker-90cm-with-gas-hob-cream' Commented Feb 11, 2019 at 13:13
  • you mean request_path = 'smeg/smeg-cooker-90cm-with-gas-hob-cream' and target_path='catalog/product/view/id/2417/' since catalog/product/view/id/2417 is handled by the Magento\Catalog\Controller\Product\View controller? OK, and what are your actual entries in your url_rewrite table for this product?
    – HelgeB
    Commented Feb 11, 2019 at 13:21
  • I do not have any entry for url rewrite for this product, i was using custom frontend url router to redirect to another url, without changing the url rewrites Commented Feb 11, 2019 at 13:33
  • Also, you had got it correct. I have a product with url key "smeg-cooker-90cm-with-gas-hob-cream" and i want to redirect it to "smeg/smeg-cooker-90cm-with-gas-hob-cream" Commented Feb 11, 2019 at 13:34

1 Answer 1

0

First, we need to create ‘di.xml’ at the following location and add below code. app\code\Vendor\Extension\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">
<preference for="Magento\Catalog\Model\Product\Url"  type=" Vendor\Extension\Model\Url" /><preference for="Magento\UrlRewrite\Controller\Router"  type="Vendor\Extension\Controller\Router" /></config>

After that you need to create one more file that will fetch default Magento URLs so you can override those urls easily. For that purpose you need to create ‘Url.php’ inside your custom extension folder path. app\code\Vendor\Extension\Model\Url.php

<?php
namespace Vendor\Extension\Model;
use Magento\UrlRewrite\Model\UrlFinderInterface;
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
class Url extends \Magento\Catalog\Model\Product\Url
{
    protected $urlFactory;
    protected $storeManager;
 
    public function __construct(
        \Magento\Framework\UrlFactory $urlFactory,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\Filter\FilterManager $filter,
        \Magento\Framework\Session\SidResolverInterface $sidResolver,
        UrlFinderInterface $urlFinder
    ) {
        parent::__construct($urlFactory, $storeManager, $filter, $sidResolver, $urlFinder);
        $this->urlFactory = $urlFactory;
        $this->storeManager = $storeManager;
    }
    public function getUrl(\Magento\Catalog\Model\Product $product, $params = [])
    {
        $requestPath = $product->getRequestPath();  
        if (!empty($requestPath))
        {
                         $params['_direct'] = $requestPath;
        }
        $baseUrl = $this->storeManager->getStore()->getBaseUrl();
        $productUrl = $this->getUrlInstance()->setScope($product->getStoreId())->getUrl(' ',$params);
        $remainingUrl = str_replace($baseUrl, '', $productUrl);
        $productUrl = $baseUrl."custom-prefix/" . $remainingUrl;
        return $productUrl;
    }
    private function getUrlInstance()
    {
        return $this->urlFactory->create();
    }
}

At last step, we need to create ‘Router.php’ file at below location app\code\Vendor\Extension\Controller\Router.php

<?php
namespace Vendor\Extension\Controller;
use Magento\UrlRewrite\Model\UrlFinderInterface;
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
class Router implements \Magento\Framework\App\RouterInterface
{
    protected $actionFactory;
    protected $storeManager;
    protected $urlFinder;
    public function __construct(
        \Magento\Framework\App\ActionFactory $actionFactory,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        UrlFinderInterface $urlFinder
    ) {
        $this->actionFactory = $actionFactory;
        $this->storeManager = $storeManager;
        $this->urlFinder = $urlFinder;
    } 
    public function match(\Magento\Framework\App\RequestInterface $request)
    {
        $replaceUrl = str_replace("custom-prefix/", "", $request->getPathInfo());
        $rewrite = $this->getRewrite($replaceUrl, $this->storeManager->getStore()->getId());    
        if ($rewrite == null)
    {
            return null;
        }
        $request->setAlias(\Magento\Framework\UrlInterface::REWRITE_REQUEST_PATH_ALIAS, $rewrite->getRequestPath());
        $request->setPathInfo('/' . $rewrite->getTargetPath());
        return $this->actionFactory->create('Magento\Framework\App\Action\Forward');
}
protected function getRewrite($requestPath, $storeId)
   {
        return $this->urlFinder->findOneByData([
            UrlRewrite::REQUEST_PATH => trim($requestPath, '/'),
            UrlRewrite::STORE_ID => $storeId,
        ]);
   }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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