SpinOneSolutions | I waste my time so that you don’t have to…

Oct/09

22

Magento – Part IV : Extending Models

The Problem:

You want to expand upon or change some functionality within Magento.

The Solution:

Extend a Model!  I’m going to use a real world example here because I believe that examples are the best tools for teaching.

I was faced with a request for additional functionality in regards to the Authorize.net payment method.  Basically, the customer wanted an email to be sent to an administrator if the gateway experienced an error while trying to processes a payment; a very reasonable request.

To accomplish this I extended Mage_Paygate_Model_Authorizenet, the model responsible for Authorize.net.  There are two very important reasons why I went about it the way I did.

First, as I mentioned earlier, all custom code should go in the /local/ directory.  If I had made my changes directly to Mage_Paygate_Model_Authorizenet (/core/Mage/Paygate/Model/Authorizenet) then the modifications would be in serious danger if the core were ever updated, essentially breaking the upgrade path.

Secondly, by extending the core class I can make reference to anything contained in the parent class.  This is good OOP architecture; I’m just adorning the parent class with additional functionality, leveraging all the work that has come before and maintaining good compartmentalization.

There are two basic steps to extending a core class.  Firstly, you need to create your new (custom) class in a custom Module living in /local/.  I’ll continue expanding upon my previous examples and make a new Model within Spinonesolutions/Helloworld.  I’m going to put the new Model in its own folder, mirroring the structure of the core.

Parent Class Path:
/Mage/Paygate/Model/Authorizenet.php

Custom Class Path:
/Spinonesolutions/Helloworld/Model/Paygate/Authorizenet.php

Naming conventions dictate that my custom Class’s name be:
Spinonesolutions_Helloworld_Model_Paygate_Authorizenet

Let’s jump right into the source and dissect what’s going on.

<?php
class Spinonesolutions_Helloworld_Model_Paygate_Authorizenet extends Mage_Paygate_Model_Authorizenet {

  private $_order;

  function __construct() {
    parent::__construct();     
  }

  public function capture(Varien_Object $payment, $amount) {
    $this->_order = $payment->getOrder();
    try {
      parent::capture($payment,$amount);
    } catch (Exception $error) {
      $this->_sendEmail($error);
      throw $error;
    }           
    return $this;
  }
}

The declaration is import to note because this is where we do the actual extending.  Although it’s not necessary for this example I’ve included a call to the constructor, and placed a call to the parent constructor within it.  This way, both the custom and parent model are instantiated correctly.

OK, onto the meat, the capture() function.  To fully understand this we need to understand what we’re trying to extend.  Looking at Mage_Paygate_Model_Authorizenet (/Mage/Paygate/Model/Authorizenet.php) will yield the answer.

As you can see Mage_Paygate_Model_Authorizenet contains a capture method with the exact same signature: public function capture(Varien_Object $payment, $amount).  What I’m doing is overriding this method with my method.  I add my additional functionality and then call the parent method at the appropriate time to drop the system back into its default workflow.

Notice that all I’m doing is wrapping the parent method call in a try catch block so that if an Exception is thrown I can catch it and send an email.  I’ve successfully extended the core functionality without touching a line of the core code!

I’ve left out one small, but hugely important bit of information.  In order to get this to work we have to let Magento know that there’s a custom Model which overrides this particular Model.  To accomplish this we turn to the config.xml.

<?xml version="1.0" encoding="UTF-8" ?>
<config>
      <modules>
            <Spinonesolutions_Helloworld>
                  <version>0.1.0</version>
            </Spinonesolutions_Helloworld>
      </modules>
    <frontend>
        <routers>
            <spinonesolutions>      <!-- I make this match my front name but I'm not sure it matters -->
                <use>standard</use> <!-- Use standard routing as opposed to admin.  IE: frontend vs admin -->
                <args>
                    <module>Spinonesolutions_Helloworld</module>  <!-- The module to search for controllers -->
                    <frontName>spinonesolutions</frontName> <!-- The first descriminator in the path.  "spinonesolutions" in http://localhost/spinonesolutions/ -->
                </args>
            </spinonesolutions>
        </routers>
    </frontend>
      <global>
            <models>
                  <spinonesolutions_helloworld> <!-- This is used when istanting your Model EG: Mage::getModel("spinonesolutions_helloworld/hellworld") -->
                        <class>Spinonesolutions_Helloworld_Model</class>      <!-- That class to use when isntanting objects of type above. -->
                  </spinonesolutions_helloworld>
              <paygate>
                  <rewrite>
                        <authorizenet>Spinonesolutions_Helloworld_Model_Paygate_Authorizenet</authorizenet>
                  </rewrite>
              </paygate>
            </models>
      </global>
</config>

Notice line:24 and the paygate element.  This is the element that is telling Magento to now look in our custom class for the Model, and not the core.

That’s all there is to it!  You can now extend Magento’s core functionality to your heart’s content.

I bet you astute readers out there noticed that ALL of the models thus far have extended a core class.  My first Model Spinonesolutions_Helloworld_Model_Helloworld extends Varien_Object.  Even the controllers extend Mage_Core_Controller_Front_Action.

Oh Snap!

Download the source – Helloworld_v3

  1. Part I : Custom Module
  2. Part II : Models
  3. Part III : Controllers
  4. Part IV : Extending Models
  5. Part V : Data Layer
Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • Kirtsy
  • Propeller
  • Reddit
  • Slashdot
  • StumbleUpon
  • Suggest to Techmeme via Twitter
  • Technorati

RSS Feed

1 Comment for Magento – Part IV : Extending Models

Dan Waldron | October 22, 2009 at 7:16 am

I found your site on technorati and read a few of your other posts. Keep up the good work. I just added your RSS feed to my Google News Reader. Looking forward to reading more from you down the road!

Leave a comment!

«

»

Find it!

Theme Design by devolux.org