Properly Override Mage_Customer_AccountController to Add Your Own Actions

There are often times where you may want to add your own custom action to the Mage_Customer_AccountController. You may have a module which falls under the category of a “customer action”. You may have already tried and got redirected to the login action. This can be infuriating, so let’s take a closer look at what’s really happening.

In any controller which inherits from Mage_Core_Controller_Front_Action, we have a preDispatch function which is called before we actually get to the specific action which was requested. (If you go even further up the inheritance, you’ll find Mage_Core_Controller_Varien_Action’s preDispatch function which has observer events specific to a controller which are handy to hook into carefully if you need to before an action is run – ‘controller_action_predispatch_’ . $this->getFullActionName(). But this is beside the point from what we’re doing here.) This function is to get everything set properly before we execute code in our specific action.

Let’s open up the preDispatch function in Mage_Customer_AccountController

  /**

    * Action predispatch

    *

    * Check customer authentication for some actions

    */

   public function preDispatch()

   {

       // a brute-force protection here would be nice

       parent::preDispatch();

       if (!$this->getRequest()->isDispatched()) {

           return;

       }

       $action = $this->getRequest()->getActionName();

       $openActions = array(

           ‘create’,

           ‘login’,

           ‘logoutsuccess’,

           ‘forgotpassword’,

           ‘forgotpasswordpost’,

           ‘resetpassword’,

           ‘resetpasswordpost’,

           ‘confirm’,

           ‘confirmation’

       );

       $pattern = ‘/^(‘ . implode(‘|’, $openActions) . ‘)/i’;

       if (!preg_match($pattern, $action)) {

           if (!$this->_getSession()->authenticate($this)) {

               $this->setFlag(”, ‘no-dispatch’, true);

           }

       } else {

           $this->_getSession()->setNoReferer(true);

       }

   }

In this function, we first run our parent’s preDispatch function, which if you traverse to runs important internal Magento / Varien cookie settings and information. You can see that we have a variable called $openActions which actually lists all actions we can hit on the frontend. You then can see it uses a regex pattern to match if the current action is within the open actions. If it doesn’t match any of these actions, you can see it will try to authenticate the current customer session.

How to set up the authenticate function

/**

    * Authenticate controller action by login customer

    *

    * @param   Mage_Core_Controller_Varien_Action $action

    * @param   bool $loginUrl

    * @return  bool

    */

   public function authenticate(Mage_Core_Controller_Varien_Action $action, $loginUrl = null)

   {

       if ($this->isLoggedIn()) {

           return true;

       }

       $this->setBeforeAuthUrl(Mage::getUrl(‘*/*/*’, array(‘_current’ => true)));

       if (isset($loginUrl)) {

           $action->getResponse()->setRedirect($loginUrl);

       } else {

           $action->setRedirectWithCookieCheck(Mage_Customer_Helper_Data::ROUTE_ACCOUNT_LOGIN,

               Mage::helper(‘customer’)->getLoginUrlParams()

           );

       }

       return false;

   }

First of all, if we’re already logged in we’ve already been authenticated, so we will return true. We are not passing in a $loginUrl, therefore we will be setting a redirectWithCookieCheck to the constant (url) ROUTE_ACCOUNT_LOGIN – which is the login URL. This just sets a redirect to the account login page. This all looks a little confusing, which is why it may be a little confusing to figure out what’s going on. But fear not! All we need to do is add our custom action when overriding Mage_Customer_AccountController. Please see below:

/**

    * Action predispatch

    *

    * Check customer authentication for some actions

    */

   public function preDispatch()

   {

       Mage_Core_Controller_Front_Action::preDispatch();

       if (!$this->getRequest()->isDispatched()) {

           return;

       }

       $action = $this->getRequest()->getActionName();

       $openActions = array(

           ‘create’,

           ‘login’,

           ‘logoutsuccess’,

           ‘forgotpassword’,

           ‘forgotpasswordpost’,

           ‘resetpassword’,

           ‘resetpasswordpost’,

           ‘confirm’,

           ‘confirmation’,

           // By Demac

           // Add our own open actions

           ‘ourcustomaction’,

       );

       $pattern = ‘/^(‘ . implode(‘|’, $openActions) . ‘)/i’;

       if (!preg_match($pattern, $action)) {

           if (!$this->_getSession()->authenticate($this)) {

               $this->setFlag(”, ‘no-dispatch’, true);

           }

       } else {

           $this->_getSession()->setNoReferer(true);

       }

   }

Notice that we’re calling the parent of Mage_Customer_AccountController’s preDispatch() function which is important instead of just calling the PHP reference ‘parent’ as this would just call Mage_Customer_AccountController’s preDispatch() function. This would in turn override our changes to this function and importantly the $openActions variable where we defined our own actions.

Good luck adding your own customer actions!