Magento 2 product attribute filter url rewrite?
-
14-04-2021 - |
Question
I have override url-rewrite router in my custom module,and add my custom rewrite code in override router file. after filter url created like below :
But I want to create url like :
http://domainname.com/services/aruba
I am using below code for rewrite url in router file .it's not working. it's goes to 404 result page.
//custom code
if ($request->getModuleName() === 'catalog' || $request->getModuleName() === 'cms') {
return;
}
$identifier = trim($request->getPathInfo(), '/');
$urlKey_explode = explode('/', $identifier);
if($urlKey_explode[0]=='services')
{
$url_string = $urlKey_explode[1];
//get manufacture
$objectManager = \Magento\Framework\App\ObjectManager::getInstance(); // Instance of object manager
$resource = $objectManager->get('Magento\Framework\App\ResourceConnection');
$connection = $resource->getConnection();
//Select product attribute from table
$sql = "SELECT
eav_attribute_option_value.option_id , eav_attribute_option_value.value
FROM
eav_attribute_option_value
join `eav_attribute_option` on `eav_attribute_option`.option_id = eav_attribute_option_value.option_id
WHERE
eav_attribute_option.attribute_id = 83
group by
eav_attribute_option_value.option_id";
$result_has_options_attribute_option = $connection->fetchAll($sql);
foreach ($result_has_options_attribute_option as $key => $value)
{
$productattriburtname = $value['value'];
if(strpos($url_string, $productattriburtname) !== false){
$manufacturerlabel = $value['value'];
$url_string = str_replace($productattriburtname, "-", $url_string);
break;
}
}
$request->setModuleName('catalog')->setControllerName('category')->setActionName('view');
$request->setParam('manufacturer', $manufacturerlabel);
$request->setAlias(\Magento\Framework\Url::REWRITE_REQUEST_PATH_ALIAS, $identifier);
return $this->actionFactory->create(
'Magento\Framework\App\Action\Forward',
['request' => $request]
);
}
//end custom code
Please advise me.
Solution
I have to Create a Custom Module for product attribute filter URL rewrite.
registration.php
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Custom_Seo',
__DIR__
);
module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
<module name="Custom_Seo" setup_version="1.0.0">
</module>
</config>
create 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\UrlRewrite\Controller\Router" type="Custom\Seo\Controller\CustomRouter" />
</config>
Override
Magento\UrlRewrite\Controller\Router to Custom\Seo\Controller\CustomRouter
Controller/CustomRouter.php
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Custom\Seo\Controller;
use Magento\Framework\App\Request\Http as HttpRequest;
use Magento\Framework\App\Response\Http as HttpResponse;
use Magento\UrlRewrite\Controller\Adminhtml\Url\Rewrite;
use Magento\UrlRewrite\Model\OptionProvider;
use Magento\UrlRewrite\Model\UrlFinderInterface;
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
use Magento\Framework\UrlInterface;
use Magento\Framework\App\Action\Redirect;
use Magento\Framework\App\ActionInterface;
/**
* UrlRewrite Controller Router
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class CustomRouter implements \Magento\Framework\App\RouterInterface
{
/**
* @var \Magento\Framework\App\ActionFactory
*/
protected $actionFactory;
/**
* @var UrlInterface
*/
protected $url;
/**
* @var \Magento\Store\Model\StoreManagerInterface
*/
protected $storeManager;
/**
* @var \Magento\Framework\App\ResponseInterface|HttpResponse
*/
protected $response;
/**
* @var \Magento\UrlRewrite\Model\UrlFinderInterface
*/
protected $urlFinder;
/**
* @param \Magento\Framework\App\ActionFactory $actionFactory
* @param 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,
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|HttpRequest $request
* @return ActionInterface|null
*/
public function match(\Magento\Framework\App\RequestInterface $request)
{
//custom code
if ($request->getModuleName() === 'catalog' || $request->getModuleName() === 'cms') {
return;
}
$identifier = trim($request->getPathInfo(), '/');
$urlKey_explode = explode('/', $identifier);
if($urlKey_explode[0]=='services')
{
if (!isset($urlKey_explode[1])) {
$urlKey_explode[1] = null;
}
$url_string = $urlKey_explode[1];
//Instance of object manager
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$resource = $objectManager->get('Magento\Framework\App\ResourceConnection');
$connection = $resource->getConnection();
//category code
$category_id = '';
$category_flat_query = 'SELECT `entity_id`, `name` FROM `catalog_category_flat_store_1` WHERE is_active = 1 AND `parent_id` = 26 ORDER BY LENGTH(name) DESC';
$category_flat_data = $connection->fetchAll($category_flat_query);
foreach ($category_flat_data as $category_flat_data_val)
{
//format url
$category_dynUrl = $this->formatUrlKey($category_flat_data_val['name']);
if(strpos($url_string, $category_dynUrl) !== false){
$category_id .= $category_flat_data_val['entity_id'].',';
$url_string = str_replace($category_dynUrl, "-", $url_string);
break;
}
//get children
$category_child_flat_query = 'SELECT `entity_id`, `name` FROM `catalog_category_flat_store_1` WHERE is_active = 1 AND `parent_id` = '.$category_flat_data_val['entity_id'].' ORDER BY LENGTH(`name`) DESC';
$category_child_flat_data = $connection->fetchAll($category_child_flat_query);
foreach ($category_child_flat_data as $subcat){
$subcat['entity_id'];
$subcat['name'];
//format url
$category_dynUrl = $this->formatUrlKey($subcat['name']);
if(strpos($url_string, $category_dynUrl) !== false){
$category_id .= $subcat['entity_id'].',';
$url_string = str_replace($category_dynUrl, "-", $url_string);
break;
}
}
}
if (empty($category_id)) {
$category_id = 26;
}
//end category code
//manufacture code
$manufacturerid = '';
$sql = "SELECT
eav_attribute_option_value.option_id , eav_attribute_option_value.value
FROM
eav_attribute_option_value
join `eav_attribute_option` on `eav_attribute_option`.option_id = eav_attribute_option_value.option_id
WHERE
eav_attribute_option.attribute_id = 83
group by
eav_attribute_option_value.option_id";
$result_has_options_attribute_option = $connection->fetchAll($sql);
foreach ($result_has_options_attribute_option as $key => $value)
{
$manufactureattriburtname = $this->formatUrlKey($value['value']);
if(strpos($url_string, $manufactureattriburtname) !== false){
$manufacturerid = $value['option_id'];
$url_string = str_replace($manufactureattriburtname, "-", $url_string);
break;
}
}
//end manufacture code
// product code
$productid = '';
$sqlproduct = "SELECT
eav_attribute_option_value.option_id , eav_attribute_option_value.value
FROM
eav_attribute_option_value
join `eav_attribute_option` on `eav_attribute_option`.option_id = eav_attribute_option_value.option_id
WHERE
eav_attribute_option.attribute_id = 139
group by
eav_attribute_option_value.option_id";
$result_product_attribute = $connection->fetchAll($sqlproduct);
foreach ($result_product_attribute as $key1 => $value1)
{
$productattriburtname = $this->formatUrlKey($value1['value']);
if(strpos($url_string, $productattriburtname) !== false){
$productid = $value1['option_id'];
$url_string = str_replace($productattriburtname, "-", $url_string);
break;
}
}
// end product code
/*$manufacturerid = rtrim($manufacturerid,',');
$category_id = rtrim($category_id,',');
$productid = rtrim($productid,',');*/
$request->setModuleName('catalog')->
setControllerName('category')->
setActionName('view')->
setParam('manufacturer', $manufacturerid)->
setParam('product', $productid)->
setParam('id', $category_id);
$request->setAlias(\Magento\Framework\Url::REWRITE_REQUEST_PATH_ALIAS, $identifier);
return $this->actionFactory->create(
'Magento\Framework\App\Action\Forward',
['request' => $request]
);
}
//end custom code
$rewrite = $this->getRewrite(
$request->getPathInfo(),
$this->storeManager->getStore()->getId()
);
if ($rewrite === null) {
//No rewrite rule matching current URl found, continuing with
//processing of this URL.
return null;
}
if ($rewrite->getRedirectType()) {
//Rule requires the request to be redirected to another URL
//and cannot be processed further.
return $this->processRedirect($request, $rewrite);
}
//Rule provides actual URL that can be processed by a controller.
$request->setAlias(
UrlInterface::REWRITE_REQUEST_PATH_ALIAS,
$rewrite->getRequestPath()
);
$request->setPathInfo('/' . $rewrite->getTargetPath());
return $this->actionFactory->create(
\Magento\Framework\App\Action\Forward::class
);
}
protected function formatUrlKey($str)
{
$urlKey = preg_replace('#[^0-9a-z]+#i', '-', $str);
$urlKey = strtolower($urlKey);
$urlKey = trim($urlKey, '-');
return $urlKey;
}
}
?>
OTHER TIPS
You need to get the categoryId
by url_key
for your parameter and pass it to the forwarded action too. For the manufacturer you need to get the optionId
which cou can do without SQL in your code by using EAV Config.
The following code should work and give you the category page with the manufacturer filter set, so the scope of this question should be answered with that. But anyway you will have to do some more changes in the filter of the categories since removing the manufacturer filter from your custom url will not work with Magento's standard logic. Also it would be good to add some error handling.
$identifier = trim($request->getPathInfo(), '/');
$urlKey_explode = explode('/', $identifier);
if (count($urlKey_explode) > 1){
$urlKey = $urlKey_explode[0];
$optionValue = $urlKey_explode[1];
$objectManager = \Magento\Framework\App\ObjectManager::getInstance(); // Instance of object manager
//get the category id for the first given parameter
$categoryFactory = $objectManager->create('Magento\Catalog\Model\CategoryFactory');
$categories = $categoryFactory->create()
->getCollection()
->addAttributeToFilter('url_key',$urlKey)
->addAttributeToSelect(['entity_id']);
$categoryId = $categories->getFirstItem()->getEntityId();
//get the option id for the second given parameter
$eavConfig = $objectManager->get('Magento\Eav\Model\Config');
$attribute = $eavConfig->getAttribute('catalog_product', 'manufacturer');
$manufacturerOptionId = $attribute->getSource()->getOptionId($optionValue);
//create forward with the correct settings
$resultForwardFactory = $objectManager->get('Magento\Framework\Controller\Result\ForwardFactory');
$result = $resultForwardFactory->create();
$result->setModule('catalog')->setController('category');
$result->setParams(['id' => $categoryId, 'manufacturer' => $manufacturerOptionId]);
$result->forward('view');
return $result;
}
I hope that helps you. Feedback would be nice :-)