3

I've been trying to set the meta title of a product listing page when an action is executed. I found this post on Magento2 StackExchange and tried to replicate in my Controller:

<?php
    namespace TreyBake\Garage\Controller\Index;

    use Magento\Framework\App\Action\Context;

    class Search extends \Magento\Framework\App\Action\Action
    {        
        protected $resultPageFactory;
        protected $_pageConfig;

        public function __construct(
            Context $context,
            \Magento\Framework\View\Result\PageFactory $resultPageFactory,
            \Magento\Framework\View\Page\Config $pageConfig
        )
        {
            $this->resultPageFactory = $resultPageFactory;
            $this->_pageConfig = $pageConfig;

            parent::__construct($context);
        }

        protected function _prepareLayout()
        {
            $this->_pageConfig->getTitle()->set('foo');
            $pmt = $this->getLayout()->getBlock('page.main.title');
            $pmt->setPageTitle('bar');

            return parent::_prepareLayout();
        }

        public function execute()
        {
            # my controller exec code

            $rpf = $this->resultPageFactory->create();
            $pmt = $rpf->getLayout()->getBlock('page.main.title');
            $pmt->setPageTitle('foobar');

            # etc.
        }
    }

Disabling one at a time makes no change, and both uncommented has no affect. What am I doing wrong and how can I override the meta title (<title>) for product listing pages using $_GET params (though, really, if I know how to set the meta title correctly, I can fill in the blanks with $_GET)?

Update:

I think I know why this is so troublesome, the last line in the execute() method is this:

$this->getResponse()->setRedirect($backUrl);

doing a log of this shows the $backUrl to equate to:

http://site.development/wheel-tyres/tyres.html?find=aprilia-af-1-futura-1990-4730&sid=cbFktM0OTy

So I don't think I can return $resultPageFactory as, it's redirected before it's returned.

My Edited Question: How do I set the meta title with redirect?

Another Update

I tried using getResponse() to set the data, as I did some logging and it doesn't seem I can use it:

$writer = new \Zend\Log\Writer\Stream(BP. '/var/log/dev.log');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);
$logger->info(
    print_r(
        get_class_methods($this->getResponse),
        true
    )
);

This led me to three functions of interest:

  • getHeaders()
  • getMetaData()
  • setMetaData()

I then logged the get* functions and getMetaData() was empty, getHeaders had data, but I overlooked what it might mean, headers are the HTTP headers (duh).

I then used setMetaData('title', 'foo') and logged getMetaData after that and huzzah, my data is there - however, the title for the page remains the same.. again, I'm guessing because of the redirect.

7
  • Is this issue been resolved already?
    – fmsthird
    Jan 28, 2019 at 8:22
  • @magefms not yet - though haven't tried any of the below solutions - going to try implementing now :)
    – treyBake
    Jan 28, 2019 at 9:02
  • can you update your code also ? you're right that getresponse could be the reason why your code is not working.
    – fmsthird
    Jan 28, 2019 at 10:25
  • @magefms I've added the line I think crucial - everything else works, but I think the redirect is probably stopping the setting of meta title
    – treyBake
    Jan 28, 2019 at 10:26
  • yeah , possibly
    – fmsthird
    Jan 28, 2019 at 10:28

6 Answers 6

1

Try with the below code:

 public function execute()
        {
            # my controller exec code

            $rpf = $this->resultPageFactory->create();
            $pmt = $rpf->getLayout()->getBlock('head')->setTitle($this->__('foobar'));;
        }
1
  • returned error of: Uncaught Error: Call to a member function setTitle() on boolean :s
    – treyBake
    Jan 28, 2019 at 9:37
1

This code is working for me, in your execute() function you have to use this code

/**
     * Execute view action
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        $resultPage = $this->resultPageFactory->create();
        $resultPage->getConfig()->getTitle()->set('foobar');
        return $resultPage;
    }

I hope it will work for you

1
  • see edit about use of return :)
    – treyBake
    Jan 28, 2019 at 10:03
1

Try prepend(__("Title"));

public function execute()
    {
        $rpf = $this->resultFactory->create(ResultFactory::TYPE_PAGE);
        $rpf->getConfig()->getTitle()->prepend(__(" foobar"));
        return $rpf;
    }  

or

public function execute()
{
    $rpf = $this->resultFactory->create(ResultFactory::TYPE_PAGE);
    $rpf->getLayout()->getBlock('page.main.title');
    $rpf->getConfig()->getTitle()->prepend(__(" foobar"));
    return $rpf;
}

or

public function execute()
{
    $rpf = $this->resultPageFactory->create(ResultFactory::TYPE_PAGE);
    $rpf->getLayout()->getBlock('page.main.title');
    $rpf->getConfig()->getTitle()->prepend(__(" foobar"));
    return $rpf;
}  

To make sure the given solution above will work, don't forget to add this before your class :

use Magento\Framework\Controller\ResultFactory;

2
  • I should note: the last line in my current controller is: $this->getResponse()->setRedirect($backUrl); so I don't think I can use return here
    – treyBake
    Jan 28, 2019 at 9:44
  • lemme update question
    – treyBake
    Jan 28, 2019 at 9:44
1

If you want to change your category page title to something comes from $_GET like this:

enter image description here

You should create a plugin for Magento\Catalog\Controller\Category\View

Detail steps are below:

  1. app/code/Vendor/Module/etc/frontend/di.xml
<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <type name="Magento\Catalog\Controller\Category\View">
        <plugin name="training_catalog_product_list" type="Vendor\Module\Plugin\Catalog\Controller\Category\View"/>
    </type>
</config>
  1. app/code/Vendor/Module/Plugin/Catalog/Controller/Category/View.php
namespace Vendor\Module\Plugin\Catalog\Controller\Category;


class View
{
    /**
     * @param \Magento\Catalog\Controller\Category\View $subject
     * @param $result
     * @return mixed
     */
    public function afterExecute(\Magento\Catalog\Controller\Category\View $subject, $result)
    {
        if ($result instanceof \Magento\Framework\View\Result\Page) {

            $title = $subject->getRequest()->getParam('test', false);
            if ($title) {
                $result->getConfig()->getTitle()->set($title);
            }
        }
        return $result;
    }
}

Hope this will solve your issue. Let me know if you have any question

1
+50

You can create custom event to set product title dynamic or by $_GET url Please check below steps for more information.

In your custom module please create event.xml file

/app/code/Vendor/Module/etc/frontend/events.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="catalog_product_load_after">
        <observer name="dynamic_title_generator" instance="Vendor\Module\Observer\AfterProductLoad" />
    </event> 
</config>

Add below code in your Observer

/app/code/Vendor/Module/Observer/AfterProductLoad.php

<?php
namespace Vendor\Module\Observer;

use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Event\Observer as EventObserver;
use Magento\Store\Model\StoreManagerInterface;

class AfterProductLoad implements ObserverInterface
{
    /**
     * @var StoreManagerInterface
     */
    private $storeManager;

    /**
     * @param StoreManagerInterface $storeManager
     */
    public function __construct(
        StoreManagerInterface $storeManager
    ){
        $this->storeManager = $storeManager;
    }

    public function execute(EventObserver $observer)
    {
        $product = $observer->getProduct();
        $metaTitle = $observer->getRequest()->getParam('test', false);

        //You can set any dynamic title from here as well.
        if ($metaTitle) {
            $product->setMetaTitle($metaTitle);
            $product->setIsMetaApplied(true);
        }
    }
}
0

I would suggest to store the title you need in the session before calling the redirect and reuse it in a plugin hooked in before the set() method in Magento\Framework\View\Page\Title I assume you wan't to change the page title everywhere - otherwise another appropriate pluggable method should be used. For example if you want to overwrite only the HTML title, you might better plug in in Magento\Framework\View\Page\Config\Renderer after the method renderTitle(), that should also work. Where to plug in depends on your specific requierements.

Example code:

1. add session object in your controller and store title

 [...]
protected $_catalogSession;
public function __construct(
    Context $context,
    \Magento\Framework\View\Result\PageFactory $resultPageFactory,
    \Magento\Framework\View\Page\Config $pageConfig,
    \Magento\Catalog\Model\Session $catalogSession
)
[...]
public function execute()
{
    [...]
    $this->_catalogSession->setMyTitle("My Title");
    $this->getResponse()->setRedirect($backUrl);
}

2. add plugin in di.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\View\Page\Title">
        <plugin name="YourModule_Page_Plugin" type="YourNamespace\YourModule\Plugin\TitlePlugin" sortOrder="10" disabled="false"  />
    </type>
</config>

3. create plugin TitlePlugin.php

class TitlePlugin{

    protected $_catalogSession;

    public function __construct( 
        \Magento\Catalog\Model\Session $catalogSession
        ){
            $this->_catalogSession = $catalogSession;
    }

    public function beforeSet(\Magento\Framework\View\Page\Title $titleObject, string $title)
    {
        //set the parameter to true, to use the title only once (i.e. the call from the redirect in previous controller)
        //this could be a problem if setTitle() is called more than once in your target page (for whatever reason)
        $mytitle = $this->_catalogSession->getMyTitle(true);
        if (!empty($mytitle)){
            $title = $mytitle;
        }

        return $title;
    }
}
1
  • Please let me know if this helps you or if you need further support.
    – HelgeB
    Feb 1, 2019 at 19:37

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.