We have already know that How to redirect from an Observer for magento 1.x version.
but for magento 2,we does not know How to forcefully do redirection from an observer.
I have done google ,but does not get any answer.
We have already know that How to redirect from an Observer for magento 1.x version.
but for magento 2,we does not know How to forcefully do redirection from an observer.
I have done google ,but does not get any answer.
Yup, i have find a solution by myself by doing a research
If you want to do that then on __construct()
function of your class observer
,you must inject two classes.
\Magento\Framework\App\ResponseFactory
which responsible for
redirection,\Magento\Framework\UrlInterface
which will make url
for that redirection.ResponseFactory
,and using
setRedirect($YourUrl)->sendResponse();
redirect to your wished url.<?php
namespace [Vendor]\[modulename]\Observer;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
class [YourClass] implements ObserverInterface
{
/**
* @var \Magento\Framework\App\ResponseFactory
*/
private $responseFactory;
/**
* @var \Magento\Framework\UrlInterface
*/
private $url;
public function __construct(
......
\Magento\Framework\App\ResponseFactory $responseFactory,
\Magento\Framework\UrlInterface $url,
......
) {
$this->responseFactory = $responseFactory;
$this->url = $url;
}
public function execute(Observer $observer)
{
$redirectionUrl = $this->url->getUrl('[ModuleName]/[ModuleName]/[[Action]');
$this->responseFactory->create()->setRedirect($redirectionUrl)->sendResponse();
return $this;
}
}
Here i am write an example of that redirection.
Basically sales_quote_collect_totals_after
event,i was try to forcefully redirect to contact us.
Here the observer code:
<?php namespace Devamit\Mgoto\Observer; use \Magento\Framework\Event\Observer; use \Magento\Framework\Event\ObserverInterface; class Challo implements ObserverInterface { protected $_responseFactory; protected $_url; public function __construct( \Magento\Framework\App\ResponseFactory $responseFactory, \Magento\Framework\UrlInterface $url ) { $this->_responseFactory = $responseFactory; $this->_url = $url; } public function execute(Observer $observer) { $event = $observer->getEvent(); $myfile = fopen("var/log/debug.log", "a+") or die("Unable to open file!"); fwrite($myfile, 'Amitber',true); fclose($myfile); // $this->_responseFactory->create()->setRedirect('www.google.com')->sendResponse(); $customerBeforeAuthUrl = $this->_url->getUrl('contact/index/index'); $this->_responseFactory->create()->setRedirect($customerBeforeAuthUrl)->sendResponse(); return $this; } }
\Magento\Framework\App\Response\Http
as a constructor argument instead. It won't work when using the factory class.
Commented
Jan 19, 2018 at 2:29
injecting the \Magento\Framework\App\ActionFlag $actionFlag
and $this->_actionFlag->set('', \Magento\Framework\App\Action\Action::FLAG_NO_DISPATCH, true);
is the way of forcing Magento to stop processing further events and redirect from an observer specially in the case of using predispatch event.
Here is the sample code
public function execute(\Magento\Framework\Event\Observer $observer)
{
/** @var \Magento\Customer\Controller\Account\LoginPost\Interceptor $controller_action */
$controller_action = $observer->getData( 'controller_action' );
$parameters = $controller_action->getRequest()->getParams();
$session = $this->customerSession;
if({yourcondition}){
// setting an action flag to stop processing further hierarchy
$this->_actionFlag->set('', \Magento\Framework\App\Action\Action::FLAG_NO_DISPATCH, true);
/// redirecting back to its referred url
$observer->getControllerAction()->getResponse()->setRedirect($this->_redirectInterface->getRefererUrl());
$session->setCustomerFormData($parameters);
}
return $this;
}
Above answer is not working for me I have updated my observer code
public function execute(\Magento\Framework\Event\Observer $observer)
{
$params = [];
// If you want to redirect with data
// $url = $this->_urlInterface->getUrl('checkout/cart/index',$params);
$url = $this->_urlInterface->getUrl('checkout/cart/index');
$observer->getControllerAction()
->getResponse()
->setRedirect($url);
}
namespace Adnan\Redirect\Observer;
use Magento\Framework\Event\ObserverInterface;
/**
* Class Example
*
* phpcs:disable Generic.Files.LineLength
*
* @package Adnan\Example\Redirect
*/
class Example implements ObserverInterface
{
/**
* @var \Magento\Framework\App\ActionFlag
*/
private $actionFlag;
/**
* @var \Magento\Framework\UrlInterface
*/
private $url;
/**
* Data constructor.
*
* @param \Magento\Framework\App\ActionFlag $actionFlag
* @param \Magento\Framework\UrlInterface $url
*/
public function __construct(
\Magento\Framework\App\ActionFlag $actionFlag,
\Magento\Framework\UrlInterface $url
) {
$this->actionFlag = $actionFlag;
$this->url = $url;
}
public function execute(\Magento\Framework\Event\Observer $observer)
{
// Stop further processing if your condition is met
$this->actionFlag->set('', \Magento\Framework\App\Action\Action::FLAG_NO_DISPATCH, true);
// then in last redirect
$observer->getControllerAction()->getResponse()->setRedirect($this->url->getUrl("[FrontName]/[Controller]/[Action]"));
return $this;
}
}
Remember to use \Magento\Framework\UrlInterface
to generate URL otherwise, you will not be redirected to a top-level structure, e.g. if you are not using UrlInterface
and want to redirect from "checkout" with "a/b/c" then it will process "checkout/a/b/c".
You have an option to use \Magento\Framework\App\ActionFlag
, it will stop further processing of observers.
I am also working on a form that use Ajax for request processing. I send the response in the form of json and based on Ajax request success/failure, I use window.location.href to redirect on a page.
You can pass the required URL in the json and can access it in the response using dot (.) operator.
$.ajax({
url:url,
data:$("#form-id").serialize(),
type:'POST',
dataType:'json',
showLoader: true,
success:function(result) {
if(result.status == true) {
if (result.product_url) {
window.location.href = result.product_url;
}
}
},
error:function(xhr,textStatus,thrownError){
alert(thrownError);
}
});
This works fine for me.
Depending on the use case, most of proposed solutions have problem: Redirects might be cached, due to other places where the response is set.
Scenario: You do a redirect based on login status -> even after the logs in, the protected page they tried to access before the login still redirects, because the 302 response is cached for one day.
I ended up in doing this:
if (!$isCustomerLoggedIn && !in_array($actionFullName, self::ALLOWED_ROUTES)) {
$response = $observer->getEvent()->getControllerAction()->getResponse();
$response->clearHeaders();
$this->redirect->redirect($response, 'customer/account/login');
}
EDIT Does not work --> clearHeaders kills the FPC - working on an alternative solution
EDIT2 Better solution:
/**
* @var $action Action
*/
$action = $observer->getEvent()->getControllerAction();
/**
* @var $response \Magento\Framework\App\Response\Http
*/
$response = $action->getResponse();
$response->clearHeaders()->setNoCacheHeaders();
$this->redirect->redirect($response, 'customer/account/login');
After many solutions tried I found one working code. Here I used the controller_action_predispatch_cms_page_save event which is working fine.
<?php
namespace VendorName\ModuleName\Observer;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\UrlInterface;
use Magento\Framework\App\ActionFlag;
class ObserverClassName implements ObserverInterface
{
protected $_urlInterface;
protected $actionFlag;
public function __construct(
UrlInterface $urlInterface,
ActionFlag $actionFlag
) {
$this->_urlInterface = $urlInterface;
$this->actionFlag = $actionFlag;
}
public function execute(Observer $observer)
{
$customRedirectionUrl = $this->_urlInterface->getUrl('cms/page/index');
$this->actionFlag->set('', \Magento\Framework\App\Action\Action::FLAG_NO_DISPATCH, true);
$controller = $observer->getControllerAction();
$response = $controller->getResponse();
return $response->setRedirect($customRedirectionUrl);
}
}
Adnan Answer worked for me.
In event.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xs d">
<event name="controller_action_predispatch_checkout_cart_add">
<observer name="Name-Your-Observer" instance="[Vendor]\[Module]\Observer\[YourClassName]" />
</event>
</config>
After that in Observer Folder Create YourClassName.php
<?php
namespace [Vendor]\[Module]\Observer;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
class [YourClassName] implements ObserverInterface
{
/**
* @var \Magento\Framework\App\ActionFlag
*/
private $actionFlag;
/**
* @var \Magento\Framework\UrlInterface
*/
private $url;
/**
* Data constructor.
*
* @param \Magento\Framework\App\ActionFlag $actionFlag
* @param \Magento\Framework\UrlInterface $url
*/
public function __construct(
\Magento\Framework\App\ActionFlag $actionFlag,
\Magento\Framework\UrlInterface $url
) {
$this->actionFlag = $actionFlag;
$this->url = $url;
}
public function execute(\Magento\Framework\Event\Observer $observer)
{
// Stop further processing if your condition is met
$this->actionFlag->set('', \Magento\Framework\App\Action\Action::FLAG_NO_DISPATCH, true);
// then in last redirect
$observer->getControllerAction()->getResponse()->setRedirect($this->url->getUrl("[route]/[controller]/[action]"));
return $this;
}
}
Let me know if this helps and need all of the files.
You can simply use header("Location: ".$storeUrl."/register-success"); in your observer