Asked  7 Months ago    Answers:  5   Viewed   35 times

In this event checkout_cart_add_product_complete, I want the customer to be redirected to an external web page http://www.example.com/. For this I am using this code, which is not working at all:-

public function moduleMethod() {
    /* @var $response1 Mage_Core_Controller_Response_Http */
    $response1 = $observer->getEvent()->getResponse();

    /* @var $response2 Mage_Core_Controller_Response_Http */
    $response2 = Mage::app()->getResponse();

    $url = 'http://www.example.com/';
    $response1->setRedirect($url);

    return;
}

I have used the "setRedirect()" method on both these variables "$response1" and "$response2", but both of them show me the Shopping Cart page, whereas I want to see this page http://www.example.com/ instead.

What I want:

  • I don't want to override the Controller Class, just to redirect the Customer, when I can effectively use the Event Observer process.
  • I don't want to use the PHP in-built function "header()", when Magento framework provides this functionality in an efficient way.

 Answers

74

tl;dr: Correct observer code at the bottom.

A note before I answer: Make sure that the observer is being triggered; step through your code or use die('here');. As written, your example method does not have the correct prototype to receive event observer data (missing an argument).

Using an event observer for redirect logic is totally appropriate in this context, as evinced by the core team explicitly passing the request and response objects in to the observer. Your attempt is good, but I think that you have conditions and configuration which cause execution to flow to Mage_Checkout_CartController::_goBack(), specifically to the line

$this->_redirect('checkout/cart');

So we need to revise our approach. Now, you could prevent any request/response logic from processing after your event observer by manipulating the response and calling the Front Controller's sendResponse() method as demonstrated below (nb: don't do this!):

public function moduleMethod($observer) //note I added a param
{
    /* @var $response1 Mage_Core_Controller_Response_Http */
    $response1 = $observer->getResponse(); // observers have event args

    $url = 'http://www.example.com/';
    $response1->setRedirect($url);

    /* SHOULDN'T DO THIS */
    Mage::app()->getFrontController()->sendResponse();
}

This should work, but I think it mixes up areas of concern by triggering output from an ethereal system component (EDA). Let's see if there's something in the command-control structure which we can use...

Just after the checkout_cart_add_product_complete event execution comes to the cart controller's _goBack() method. The problem with this method name is that it does more than its name implies:

/**
 * Set back redirect url to response
 *
 * @return Mage_Checkout_CartController
 */
protected function _goBack()
{
    $returnUrl = $this->getRequest()->getParam('return_url');
    if ($returnUrl) {
        // clear layout messages in case of external url redirect
        if ($this->_isUrlInternal($returnUrl)) {
            $this->_getSession()->getMessages(true);
        }
        $this->getResponse()->setRedirect($returnUrl);
    }
    //...
}

It looks like we can just set a return_url param on the request object and accomplish what we need.

public function moduleMethod(Varien_Event_Observer $observer)
{
    $observer->getRequest()->setParam('return_url','http://www.google.com/');
}

I've tested this, and it should do the trick!

Wednesday, March 31, 2021
 
PedroKTFC
answered 7 Months ago
79

Here is what is happening. Your configuration of the admin controller is wrong. The proper way to include your controller in the admin section is this (you'll need to change out the module name, to match yours):

<?xml version="1.0" ?>

<config>
    <modules>
        <Video_Awesome>
            <version>0.0.1</version>
        </Video_Awesome>
    </modules>
    <global>
        <models>
            <Video_Awesome>
                <class>Video_Awesome_Model</class>
                <!-- No resource model used currently -->
            </Video_Awesome>
        </models>
        <events>
            <controller_action_predispatch>
                <observers>
                    <controller_action_before>
                        <type>singleton</type>
                        <class>Video_Awesome/Observer</class>
                        <method>controllerActionPredispatch</method>
                    </controller_action_before>
                </observers>
            </controller_action_predispatch>
            <upload_video_before>
                <observers>
                    <Video_Awesome>
                        <type>singleton</type>
                        <class>Video_Awesome/Observer</class>
                        <method>uploadVideoBefore</method>
                    </Video_Awesome>
                </observers>
            </upload_video_before>
        </events>
    </global>

    <admin>
        <routers>
            <adminhtml>
            <!-- we are not creating our own router, but tapping into the adminhtml router -->
                <args>
                    <modules>
                        <!-- Your module name, and then
                        the path to the controller (minus
                        the controllers folder name). So,
                        in this instance, I put the router
                        in a "Adminhtml" folder inside of
                        the controllers folder, like thus:
        Video/Awesome/controllers/Adminhtml/videotestimonialsController.php -->
                        <Video_Awesome before="Mage_Adminhtml">Video_Awesome_Adminhtml</Video_Awesome>
                    </modules>
                </args>
            </adminhtml>
        </routers>
    </admin>
</config>

And, then, in your router (you don't need to call getEvent before getting the controller action):

public function controllerActionPredispatch ($observer)
{
    if($observer->getControllerAction()->getFullActionName() == 'adminhtml_videotestimonials_post') {
        // dispatching our own event before action upload video is run and sending parameters we need
    Mage::dispatchEvent("upload_video_before", array('request' => $observer->getControllerAction()->getRequest()));
    }
}

And finally, it doesn't sound as if you have a debugging setup for your Magento development. I would highly recommend one. I use PHPStorm (I don't have any stake in the company - this is not an advertisement :), and it works awesome. Set a breakpoint there to see if what the variables are.

I would also recommend using adminhtml_controller_action_predispatch_start, instead of the global controller_action_predispatch, as it will only trigger in the backend (a very, very small performance difference).

Also, as a small sidenote, I saw in your config.xml, that you were specifying menu items/acl there. You probably didn't know, but that is deprecated functionality, and those items should be put it adminhtml.xml.

Saturday, May 29, 2021
 
Angolao
answered 5 Months ago
88

Use THE_REQUEST instead of REQUEST_URI which might change due to other modules or rules:

RewriteEngine On

RewriteCond %{HTTPS} off
RewriteCond %{THE_REQUEST} !s/+preview [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [NE,L,R=301]

RewriteCond %{HTTPS} on
RewriteCond %{THE_REQUEST} s/+preview [NC]
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [NE,L,R=301]

# other rules go here

Also make sure to clear your browser cache.

Saturday, May 29, 2021
 
RenegadeAndy
answered 5 Months ago
79

First off there is no best practice for this. So I leave that decision of selecting one of these options to you whichever suits you according to your needs.

OPTION 1:

You have to implement an EventListener in this case.

STEP 1)

Register a service
<service id="acme_demo.listener.login" class="AcmeDemoBundleEventListenerLoginListener" scope="request">
    <tag name="kernel.event_listener" event="security.interactive_login" method="onSecurityInteractiveLogin"/>
    <argument type="service" id="router"/>
    <argument type="service" id="security.context"/>
    <argument type="service" id="event_dispatcher"/>
</service>

STEP 2)

Your EventListener itself
class LoginListener
{
    protected $router;
    protected $security;
    protected $dispatcher;

    public function __construct(Router $router, SecurityContext $security, EventDispatcher $dispatcher)
    {
        $this->router = $router;
        $this->security = $security;
        $this->dispatcher = $dispatcher;
    }

    public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
    {
        $this->dispatcher->addListener(KernelEvents::RESPONSE, array($this, 'onKernelResponse'));
    }

    public function onKernelResponse(FilterResponseEvent $event)
    {
        if ($this->security->isGranted('ROLE_FACTORY')) 
        {
            $response = new RedirectResponse($this->router->generate('factory_homepage'));
        } 
        elseif ($this->security->isGranted('ROLE_CUSTOMER')) 
        {
            $response = new RedirectResponse($this->router->generate('customer_homepage'));
        } 
        else 
        {
            $response = new RedirectResponse($this->router->generate('default_homepage'));
        }

        $event->setResponse($response);
    }
}

OPTION 2:

You can modify the vendor code at FOSUserBundleControllerSecurityController Add the following piece of code to make your loginAction look like this

public function loginAction(Request $request)
{
    $securityContext = $this->container->get('security.context');
    $router = $this->container->get('router');

    if ($securityContext->isGranted('ROLE_FACTORY')) 
    {
        return new RedirectResponse($router->generate('factory_homepage'));
    }
    elseif ($securityContext->isGranted('ROLE_CUSTOMER')) 
    {
        return new RedirectResponse($router->generate('customer_homepage'));
    }
    else
    {
        return new RedirectResponse($router->generate('default_homepage'));
    }
}
Saturday, May 29, 2021
 
xrock
answered 5 Months ago
42

if you want to do this for customer successfully then you can do this using event observer

after customer successfully magento trigger an event customer_register_success

This call an observer which will reequestion to custtom page

  Mage::app()->getResponse()->setRedirct($Yourdreicurll);

Details:

Step1: create config.xml is app/code/community/Amit/Custommodule/etc/ - See more at: http://www.amitbera.com/create-an-magento-extension-with-custom-database-table/#sthash.JSktrUD0.dpuf and it code

<?xml version="1.0" ?>
<config>
    <modules>
        <Amit_Custommodule>
            <version>1.0.0</version>
        </Amit_Custommodule>
    </modules>
    <global>
        <models>
            <custommodule>
                <class>Amit_Custommodule_Model</class>
            </custommodule>
        </models>
    </global>
    <frontend>
      <events>
          <customer_register_success>
        <observers>
          <notify_user>
            <class>custommodule/observer</class>
            <method>myredirection</method>
          </notify_user>
        </observers>
          </customer_register_success>     
        </events>
    </frontend>
</config>

Step2:

create module control file Module name as Amit_Custommodule.xml at app/etc/modules/

it code is

<?xml version="1.0"?>
<config>
    <modules>
        <Amit_Custommodule>
            <codePool>community</codePool>
            <active>true</active>
        </Amit_Custommodule>
    </modules>
</config>

Step3:

Create observer.php at Amit>Custommodule>Model

code is

 <?php
    class Amit_Custommodule_Model_Observer {
        public function myredirection(Varien_Event_Observer $observer) {
        $AccountController = $observer->getEvent()->getAccountController();

        $Customer = $observer->getEvent()->getCustomer();

         $response1 = Mage::app()->getResponse(); // observers have event args

            $url = 'http://www.example.com/';
            $response1->setRedirect($url);
            Mage::app()->getFrontController()->sendResponse();

        return;
      }
    }
Friday, August 20, 2021
 
Dave Nottage
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :