7

I am trying to redirect to custom URL by using plugin feature of Magento 2 but somehow I am not able to redirect it. For this, I tried a couple of options like,

Magento2: redirection from Observer

Magento2: Redirect Using Plugin (With Website Restrictions ON)

But couldn't succeed with this. I am able to do it If I am adding exit(); after redirect method but it is not good practice to write exit();. Do anyone have some hint on this?

I am using around plugin and before plugin

I have written a plugin on Magento\Customer\Model\AccountManagement class.

Thanks

8

5 Answers 5

2
+50

As per as, our discussion, I am sharing an idea that might help you.

  • First, pass a registry variable from initiatePasswordReset that registry variable will contain your desired URL.
  • Then at controller_action_postdispatch_customer_account_forgotPasswordPostevent catch that registry variable value, that page

Create Plugin over initiatePasswordReset call and use after, before ,around method depend on your choose.

Here, i am using around method.

<?php
/**
 * Created by Amit Bera.
 * User: Amit Kumar Bera
 * Email: [email protected]
 * Date: 19-05-2018
 * Time: 17:03
 */

namespace StackExchange\Works\Plugin;


use Magento\Framework\Registry;

class InitiatePasswordResetPlugin
{
    protected $registry;
    public function __construct(
        Registry $registry
    )
    {
        $this->registry = $registry;
    }
    public function aroundInitiatePasswordReset(
        \Magento\Checkout\Model\Session $subject,
        \Closure $proceed,
        $email,
        $template,
        $websiteId
    )
    {
        // Do business logic here
        if($this->registry->registry('my_custom_redirect')){
            $this->registry->unregister('my_custom_redirect');
        }
        $this->registry->register('my_custom_redirect','{YourUrl}');
        return $proceed($email, $template, $websiteId);

    }

}

Now, controller_action_postdispatch_customer_account_forgotPasswordPost event,

redirect that URL my_custom_redirect.

<?php

namespace StackExchange\Works\Observer\Frontend;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Registry;

class ControllerActionPostdispatchForgotPasswordPost implements ObserverInterface
{

    /**
     * @var \Magento\Framework\App\ActionFlag
     */
    protected $actionFlag;

    public function __construct(
        \Magento\Framework\App\ActionFlag $actionFlag,
         Registry $registry
    ) {
         $this->registry = $registry;
        $this->actionFlag        = $actionFlag;
    }

    public function execute(Observer $observer)
    {

        $action = $observer->getEvent()->getControllerAction();

        if($this->registry->registry('my_custom_redirect')){
            $this->actionFlag->set('', \Magento\Framework\App\ActionInterface::FLAG_NO_DISPATCH, true);
            $action->getResponse()->setRedirect($this->registry->registry('my_custom_redirect'));
            return $this;
        }
        return $this;
    }
}
7
  • Thanks Amit for your efforts ! +1 from me , but do you know direct forcefully redirect without writing extra observer? Like in observer we can forcefully redirect by setting 'FLAG_NO_DISPATCH` but in plugin?
    – Keyur Shah
    Commented May 19, 2018 at 12:51
  • FLAG_NO_DISPATCH cannot used to observer, if your does have any controller object at your observer
    – Amit Bera
    Commented May 21, 2018 at 11:45
  • I think we can use FLAG_NO_DISPATCH in observer please check github.com/magento/magento2/blob/2.2-develop/app/code/Magento/… @Amit
    – Keyur Shah
    Commented May 23, 2018 at 19:34
  • you can use FLAG_NO_DISPATCH this observer have controller object github.com/magento/magento2/blob/2.2-develop/app/code/Magento/…
    – Amit Bera
    Commented May 23, 2018 at 19:42
  • 1
    then if you will use predispatch then execute method will not work
    – Amit Bera
    Commented May 23, 2018 at 19:47
5

Below is a working example from my own code. It only requires 2 files.

Create 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">
    <type name="Magento\Backend\App\AbstractAction">
        <plugin name="Vendorname\Modulename\Plugin\Backend\App\AbstractAction" type="Vendorname\Modulename\Plugin\Backend\App\AbstractAction" />
    </type>
</config>

Create the plugin file

<?php

namespace Vendorname\Modulename\Plugin\Backend\App;

class AbstractAction
{
    /**
     * @var \Magento\Framework\Controller\ResultFactory
     */
    private $resultFactory;

    /**
     * @var \Magento\Framework\App\Response\RedirectInterface
     */
    private $redirect;

    /**
     * AbstractAction constructor.
     *
     * @param \Magento\Framework\Controller\ResultFactory       $resultFactory
     * @param \Magento\Framework\App\Response\RedirectInterface $redirect
     */
    public function __construct(
        \Magento\Framework\Controller\ResultFactory $resultFactory,
        \Magento\Framework\App\Response\RedirectInterface $redirect
    ) {
        $this->resultFactory        = $resultFactory;
        $this->redirect             = $redirect;
    }

    /**
     * @param \Magento\Backend\App\AbstractAction     $subject
     * @param \Closure                                $procede
     * @param \Magento\Framework\App\RequestInterface $request
     *
     * @return \Magento\Framework\App\RequestInterface|\Magento\Framework\Controller\ResultInterface|\Magento\Framework\Controller\Result\Json
     */
    public function aroundDispatch($subject, $procede, $request)
    {
        if ($yourCondition) {
            $resultRedirect = $this->resultFactory->create(
                \Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT
            );

            // if you want to redirect to the previous page
            $result = $resultRedirect->setUrl($this->redirect->getRefererUrl());

            // if you want to redirect to an external url
            $result = $resultRedirect->setUrl('https://www.google.com');
        } else {
            $result = $procede($request);
        }

        return $result;
    }
}
3
  • Yes, I can use this in Dispatch but what If I want to use in some custom methods?
    – Keyur Shah
    Commented May 27, 2018 at 8:04
  • What is the condition going to be? I can help you figure out the best time/place to check it and do the redirect. Commented May 27, 2018 at 13:40
  • Yes, sure, I am using around plugin in Magento\Customer\Model\AccountManagement on initiatePasswordReset() method @Shawn
    – Keyur Shah
    Commented May 28, 2018 at 7:02
4

I'm not sure exactly what you are trying to achieve here, but if you limit your problem to redirecting to a different url from a plugin, I can give you some ideas.
Since the Magento\Customer\Api\AccountManagementInterface does not act as a controller maybe you should not try to redirect from one of the methods from the implementation of this interface.
only controllers should handle the request and send the response.
The method initiatePasswordReset is called from 2 controller actions Magento\Customer\Controller\Adminhtml\Index\ResetPassword::execute and Magento\Customer\Controller\Account\ForgotPasswordPost::execute.
Maybe you should pluginize these methods using after or around.
Both methods above return an instance of \Magento\Backend\Model\View\Result\Redirect so it is pretty easy to change the return value of them via a plugin. (I suggest after, but you may need around, not sure of your requirements).

an after plugin could look like this (but you already know that):

public function afterExecute(
     \Magento\Customer\Controller\Account\ResetPassword $subject, $redirect, 
     \Magento\Backend\Model\View\Result\Redirect $redirect
) {
     //custom logic in here;
     if (your condition) {
          $redirect->setPath('custom/action/page');
     }
     return $redirect;
}

If you have a lot of custom logic, in order to avoid content duplication you can move the logic to a custom class and use that class as a dependency in both plugins you are creating.

3
  • I am agree with you! Not possible direction from AccountManagement
    – Amit Bera
    Commented May 21, 2018 at 8:16
  • Thanks for the answer :) I am using around plugin because I have some custom logic and on based on custom logic I need to forcefully redirect to another URL. Yes, I can use after plugin to change URL but It will not fulfill my all requirenment.
    – Keyur Shah
    Commented May 21, 2018 at 8:34
  • Maybe you should explain in the question what are you trying to achieve.
    – Marius
    Commented May 21, 2018 at 8:41
0

Use below code and replace setUrl with setPath

$result = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
$result->setPath('path/to/controller'); //ex. 'customer/account/login'
return $result;
1
  • 2
    Please don't post multiple answers, please answer in an answer .You can edit your post yourself
    – Amit Bera
    Commented May 18, 2018 at 12:29
-1

Inject 2 classes in Constructor like below:

public function __construct(\Magento\Framework\UrlInterface $url, Magento\Framework\Controller\ResultFactory $resultFactory)
{
    $this->resultFactory = $resultFactory;           
    $this->url = $url;
}

Code to redirect :

$result = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
$result->setUrl($this->url->getUrl('path/to/controller'));
return $result;
4
  • Did you try this answer in plugin class? I know I can use this on controller but not in plugin
    – Keyur Shah
    Commented May 18, 2018 at 12:24
  • Yes. Please try it and up vote if it works for you.
    – mighty_hk
    Commented May 18, 2018 at 12:25
  • Is it working ?
    – mighty_hk
    Commented May 18, 2018 at 12:45
  • unfortunately no :)
    – Keyur Shah
    Commented May 18, 2018 at 12:48

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.