<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SpinOneSolutions &#187; Model</title>
	<atom:link href="http://www.spinonesolutions.com/tag/model/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.spinonesolutions.com</link>
	<description>I waste my time so that you don't have to...</description>
	<lastBuildDate>Fri, 16 Apr 2010 21:39:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Magento Partial Refund Amount Correction for Authorize.net</title>
		<link>http://www.spinonesolutions.com/2010/01/partial-refund-amount-correction-for-authorize-net/</link>
		<comments>http://www.spinonesolutions.com/2010/01/partial-refund-amount-correction-for-authorize-net/#comments</comments>
		<pubDate>Wed, 20 Jan 2010 22:04:48 +0000</pubDate>
		<dc:creator>Will Wright</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Model]]></category>

		<guid isPermaLink="false">http://www.spinonesolutions.com/2009/11/partial-refund-amount-correction-for-authorize-net/</guid>
		<description><![CDATA[The Problem: You&#8217;ve enabled partial refunds in the Authorizenet Model, but it&#8217;s not refunding the proper amounts.  This is due to, in my view, a bug in the core which I&#8217;ll show you how to patch! The Solution: What you need to do is overload the refund method in the Authorizenet model. Create a new [...]]]></description>
			<content:encoded><![CDATA[<h3>The Problem:</h3>
<p>You&#8217;ve enabled partial refunds in the Authorizenet Model, but it&#8217;s not refunding the proper amounts.  This is due to, in my view, a bug in the core which I&#8217;ll show you how to patch!</p>
<h3>The Solution:</h3>
<p>What you need to do is overload the <strong>refund</strong> method in the Authorizenet model.</p>
<p>Create a new model that extends the original Authorizenet model.  You&#8217;ll need to follow the general instructions for how to <a title="Magento Custom Module Part I" href="http://www.spinonesolutions.com/2009/09/magento-custom-module-part-i/" target="_blank">create a custom module</a> if you don&#8217;t already know how to do so.</p>
<pre class="php" name="code">
class Spinonesolutions_General_Model_Paygate_Authorizenet extends Mage_Paygate_Model_Authorizenet {
//Override Mage_Paygate_Model_Authorizenet

protected $_canRefund = true;

public function refund(Varien_Object $payment, $amount) {
  $error = false;
  if ($payment-&gt;getRefundTransactionId() &amp;&amp; $amount&gt;0) {
    $payment-&gt;setAnetTransType(self::REQUEST_TYPE_CREDIT);
    $request = $this-&gt;_buildRequest($payment, $amount);
    $request-&gt;setXTransId($payment-&gt;getRefundTransactionId());
    $result = $this-&gt;_postRequest($request);
    if ($result-&gt;getResponseCode()==self::RESPONSE_CODE_APPROVED) {
      $payment-&gt;setStatus(self::STATUS_SUCCESS);
    } else {
      $error = $result-&gt;getResponseReasonText();
    }
  } else {
    $error = Mage::helper('paygate')-&gt;__('Error in refunding the payment');
  }

  if ($error !== false) {
    Mage::throwException($error);
  }

  return $this;
}
}</pre>
<p>Now all we need to do is let Magento know that we&#8217;ve got a custom model.  In config.xml add</p>
<pre class="xml" name="code">
&lt;?xml version="1.0"?&gt;
&lt;config&gt;
  &lt;modules&gt;
    &lt;Spinonesolutions_General&gt;
      &lt;version&gt;0.0.1&lt;/version&gt;
    &lt;/Spinonesolutions_General&gt;
  &lt;/modules&gt;
  &lt;global&gt;
    &lt;models&gt;
      ...
      &lt;paygate&gt;
        &lt;rewrite&gt;
          &lt;authorizenet&gt;Imagistic_General_Model_Paygate_Authorizenet&lt;/authorizenet&gt;
        &lt;/rewrite&gt;
      &lt;/paygate&gt;
      ...
    &lt;/models&gt;
  &lt;/global&gt;
&lt;/config&gt;
</pre>
<p>That should do it!  Questions and comments welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spinonesolutions.com/2010/01/partial-refund-amount-correction-for-authorize-net/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Magento &#8211; Enable Paygate Refunds</title>
		<link>http://www.spinonesolutions.com/2009/10/magento-enable-paygate-refunds/</link>
		<comments>http://www.spinonesolutions.com/2009/10/magento-enable-paygate-refunds/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 21:43:26 +0000</pubDate>
		<dc:creator>Will Wright</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Model]]></category>

		<guid isPermaLink="false">http://www.spinonesolutions.com/?p=435</guid>
		<description><![CDATA[The Problem: You want to issue a refund, electronically, through your payment gateway from Magento. The Solution: By default, the community edition of Magento has refunds disabled in the Paygate Models.  In order to enable them you need to create a custom Model and overwrite a protected variable.  Refer to Part IV: Extending Models for [...]]]></description>
			<content:encoded><![CDATA[<h3>The Problem:</h3>
<p>You want to issue a refund, electronically, through your payment gateway from Magento.</p>
<h3>The Solution:</h3>
<p>By default, the community edition of Magento has refunds disabled in the Paygate Models.  In order to enable them you need to create a custom Model and overwrite a protected variable.  Refer to <a title="Part IV - Extending Models" href="http://www.spinonesolutions.com/2009/10/magento-part-i…tending-models/">Part IV: Extending Models</a> for more details on extending a Model.</p>
<p>First, lets take a look at the native Model so that you can understand what&#8217;s standing in the way.  I&#8217;m going to use the Authorize.net gateway as my example.</p>
<p>The top portion of <strong>Mage_Paygate_Model_Authorizenet</strong> (/Mage/Paygate/Model/Authorizenet.php)</p>
<pre class="php" name="code">class Mage_Paygate_Model_Authorizenet extends Mage_Payment_Model_Method_Cc
{
    const CGI_URL = 'https://secure.authorize.net/gateway/transact.dll';

    const REQUEST_METHOD_CC     = 'CC';
    const REQUEST_METHOD_ECHECK = 'ECHECK';

    const REQUEST_TYPE_AUTH_CAPTURE = 'AUTH_CAPTURE';
    const REQUEST_TYPE_AUTH_ONLY    = 'AUTH_ONLY';
    const REQUEST_TYPE_CAPTURE_ONLY = 'CAPTURE_ONLY';
    const REQUEST_TYPE_CREDIT       = 'CREDIT';
    const REQUEST_TYPE_VOID         = 'VOID';
    const REQUEST_TYPE_PRIOR_AUTH_CAPTURE = 'PRIOR_AUTH_CAPTURE';

    const ECHECK_ACCT_TYPE_CHECKING = 'CHECKING';
    const ECHECK_ACCT_TYPE_BUSINESS = 'BUSINESSCHECKING';
    const ECHECK_ACCT_TYPE_SAVINGS  = 'SAVINGS';

    const ECHECK_TRANS_TYPE_CCD = 'CCD';
    const ECHECK_TRANS_TYPE_PPD = 'PPD';
    const ECHECK_TRANS_TYPE_TEL = 'TEL';
    const ECHECK_TRANS_TYPE_WEB = 'WEB';

    const RESPONSE_DELIM_CHAR = ',';

    const RESPONSE_CODE_APPROVED = 1;
    const RESPONSE_CODE_DECLINED = 2;
    const RESPONSE_CODE_ERROR    = 3;
    const RESPONSE_CODE_HELD     = 4;

    protected $_code  = 'authorizenet';

    /**
     * Availability options
     */
    protected $_isGateway               = true;
    protected $_canAuthorize            = true;
    protected $_canCapture              = true;
    protected $_canCapturePartial       = false;
    protected $_canRefund               = false;
    protected $_canVoid                 = true;
    protected $_canUseInternal          = true;
    protected $_canUseCheckout          = true;
    protected $_canUseForMultishipping  = true;
    protected $_canSaveCc = false;

    protected $_allowCurrencyCode = array('USD');</pre>
<p>The variable that we&#8217;re interested in is <strong>_canRefund</strong>.  The game plan is to create a custom Model that overrides <strong>Mage_Paygate_Model_Authorizenet</strong> and in that Model, override <strong>_canRefund</strong>.  If you&#8217;re thinking, why not just change false to true right here, right now!  Well my friend, you certainly could, but you&#8217;d certainly break your upgrade path too, check out <a title="Part IV - Extending Models" href="../2009/10/magento-part-i%E2%80%A6tending-models/">Part IV: Extending Models</a> and <a title="Part I - Custom Module" href="http://www.spinonesolutions.com/2009/09/magento-custom-module-part-i/">Part I: Custom Module</a>.</p>
<p>I&#8217;m going to create the class: <strong>Spinonesolutions_Paygate_Model_Authorizenet</strong> (/local/Spineonesolutions/Paygate/Model/Authorizenet.php) and extend <strong>Mage_Paygate_Model_Authorizenet</strong>.  Now I just override <strong>_canRefund</strong> and we&#8217;re halfway there.</p>
<pre class="php" name="code">&lt;?php
class Spinonesolutions_Paygate_Model_Authorizenet extends Mage_Paygate_Model_Authorizenet
{
 //Override Mage_Paygate_Model_Authorizenet
 protected $_canRefund = true;
}
?&gt;</pre>
<p>If you read <a title="Part IV - Extending Models" href="../2009/10/magento-part-i%E2%80%A6tending-models/">Part IV: Extending Models</a> you&#8217;ll know that there&#8217;s one last step, and that is to modify config.xml so that our custom Model overrides the native Model.</p>
<p>/Spinonesolutions/Paygate/etc/config.xml</p>
<pre class="xml" name="code">&lt;global&gt;
  &lt;models&gt;
  ...
    &lt;paygate&gt;
      &lt;rewrite&gt;
        &lt;authorizenet&gt;Spinonesolutions_Paygate_Model_Authorizenet&lt;/authorizenet&gt;
      &lt;/rewrite&gt;
    &lt;/paygate&gt;
  ...
  &lt;/models&gt;
&lt;/global&gt;</pre>
<p>That should do it!  If you&#8217;ve got everything else setup correctly this should enable the Model to post refunds electronically to your gateway.  Of course, if you want to enable more than one gateway, or perhaps a gateway that&#8217;s not Authorize.net you can do that by just following the same steps above with the Model for the gateway of your choice.</p>
<p>As always, questions and comments are welcome!</p>
<h3>Update: From Commenter Cindy</h3>
<p>Afer doing the above (and not forgetting to fill in app/etc/modules/MyNameSpace_All.xml to activate the new module), I still wasn’t getting authorize.net to really refund the cc.</p>
<p>I found that I needed to add the CC to the request, and then add the actual amount to be refunded. Now issuing a credit memo on the invoice will cause authorize.net to issue a refund to the CC.</p>
<p>Also, it appears that the ‘refund’ button only shows up if you click credit memo from an invoice – it doesn’t show up if you click credit memo on an order (only ‘refund offline’ shows up then).</p>
<p>Anyway, this is the code to make this work for me:</p>
<pre class="php" name="code">//
// Override Mage_Paygate_Model_Authorizenet
//    enable online refunds via credit memos
//    enable partial refunds
//
class Sbr_Paygate_Model_Authorizenet extends Mage_Paygate_Model_Authorizenet {
  protected $_canCapturePartial = true;
  protected $_canRefund = true;

  //
  // override _buildRequest to fill in the CC number as it is required yet not set peviously
  //
  protected function _buildRequest (Varien_Object $payment) {
    if (($payment-&gt;getAnetTransMethod() == self::REQUEST_METHOD_CC) &amp;&amp;($payment-&gt;getCcLast4()))
      $payment-&gt;setCcNumber($payment-&gt;getCcLast4());
   
      return parent::_buildRequest($payment);
  }

  // Override refund in order to fill out the amount
  //
  public function refund(Varien_Object $payment, $amount) {
    $error = false;
    if ($payment-&gt;getRefundTransactionId() &amp;&amp; $amount&gt;0) {
      $payment-&gt;setAnetTransType(self::REQUEST_TYPE_CREDIT);
      $request = $this-&gt;_buildRequest($payment);

      // set the amount (beginning of changes)
      $order = $payment-&gt;getOrder();
      $request-&gt;setXAmount($amount,2);
      $request-&gt;setXCurrencyCode($order-&gt;getBaseCurrencyCode());
      // (end of changes)

      $request-&gt;setXTransId($payment-&gt;getRefundTransactionId());
      $result = $this-&gt;_postRequest($request);

      if ($result-&gt;getResponseCode() == self::RESPONSE_CODE_APPROVED) {
        $payment-&gt;setStatus(self::STATUS_SUCCESS);
      } else {
        $error = $result-&gt;getResponseReasonText();
      }
    } else {
      $error = Mage::helper(’paygate’)-&gt;__(’Error in refunding the payment’);
    }

    if ($error !== false) {
      Mage::throwException($error);
    }

    return $this;
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.spinonesolutions.com/2009/10/magento-enable-paygate-refunds/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Magento &#8211; Part V: Data Layer</title>
		<link>http://www.spinonesolutions.com/2009/10/magento-part-v-data-layer/</link>
		<comments>http://www.spinonesolutions.com/2009/10/magento-part-v-data-layer/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 21:03:35 +0000</pubDate>
		<dc:creator>Will Wright</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[Data Layer]]></category>
		<category><![CDATA[Model]]></category>

		<guid isPermaLink="false">http://www.spinonesolutions.com/?p=439</guid>
		<description><![CDATA[The Problem: You need a custom Model to interact with a database. The Solution: By now you’ve read all the previous posts, right, and you want to take your custom module to the next level.  You not only have business logic to perform, but you need to read and write data to a custom database table.  [...]]]></description>
			<content:encoded><![CDATA[<h3>The Problem:</h3>
<p>You need a custom Model to interact with a database.</p>
<h3>The Solution:</h3>
<p>By now you’ve read all the previous posts, right, and you want to take your custom module to the next level.  You not only have business logic to perform, but you need to read and write data to a custom database table.  No problem, let’s take a look at Magento’s database layer.</p>
<p>There’s a lot of voodoo that goes into the Database layer, most of the confusion stems from a heavy reliance on naming conventions.  Once you understand these conventions you’ll have a much easier time getting data in and out of your database.</p>
<p>As always I’m going to use an example.  Let’s say that you need to create a Widget Model that stores Widgets into a database table.  We’ll need a Model to describe our Widget, a Class for the data layer, and the appropriate config files to let Magento know about our customizations.</p>
<p>I’m going to start with the Widget Model since it’s already been covered and should be the most familiar.</p>
<p>/app/code/local/Spinonesolutions/Helloworld/Model/Widget.php:</p>
<pre class="php" name="code">class Spinonesolutions_Helloworld_Model_Widget extends Mage_Core_Model_Abstract {
  function __construct() {
    parent::__construct();
    $this-&gt;_init("spinonesolutions_helloworld/widget");
  }

  public function save() {
    $this-&gt;setCreated(now());
    $this-&gt;setUpdated(now());

    parent::save();
    return $this;
  }
}</pre>
<p>There are a couple of important things to make note of in the Class above.  First, I’ve extended <strong>Mage_Core_Model_Abstract</strong>, this is Magento’s basic Data Layer Class and it will provide the functions that we need to interact with the database.</p>
<p>Second, the <strong>_init()</strong> function’s parameter should match your config.xml, as we’ll see in just a moment.  Lastly, I’ve put a little bit of business logic in the <strong>save()</strong> method.  As we’ll see this sets the created, and modified fields in our table to the current datetime when we call <strong>save()</strong>.</p>
<p>/app/code/local/Spinonesolutions/etc/config.xml:</p>
<pre class="xml" name="code">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;config&gt;
  &lt;modules&gt;
    &lt;Spinonesolutions_Helloworld&gt;
      &lt;version&gt;0.1.0&lt;/version&gt;
    &lt;/Spinonesolutions_Helloworld&gt;
  &lt;/modules&gt;
  &lt;frontend&gt;
    &lt;routers&gt;
      &lt;spinonesolutions&gt; &lt;!-- I make this match my front name but I'm not sure it matters --&gt;
        &lt;use&gt;standard&lt;/use&gt; &lt;!-- Use standard routing as opposed to admin. IE: frontend vs admin --&gt;
        &lt;args&gt;
          &lt;module&gt;Spinonesolutions_Helloworld&lt;/module&gt; &lt;!-- The module to search for controllers --&gt;
          &lt;frontName&gt;spinonesolutions&lt;/frontName&gt; &lt;!-- The first descriminator in the path. "spinonesolutions" in http://localhost/spinonesolutions/ --&gt;
        &lt;/args&gt;
      &lt;/spinonesolutions&gt;
    &lt;/routers&gt;
  &lt;/frontend&gt;
  &lt;global&gt;
    &lt;models&gt;
      &lt;spinonesolutions_helloworld&gt; &lt;!-- This is used when istanting your Model EG: Mage::getModel("spinonesolutions_helloworld/hellworld") --&gt;
        &lt;class&gt;Spinonesolutions_Helloworld_Model&lt;/class&gt; &lt;!-- That class to use when isntanting objects of type above. --&gt;
        &lt;resourceModel&gt;spinonesolutions_helloworld_mysql4&lt;/resourceModel&gt; &lt;!-- Use a custom table instead of EAV, the Model is defomed below --&gt;
      &lt;/spinonesolutions_helloworld&gt;
      &lt;spinonesolutions_helloworld_mysql4&gt; &lt;!-- Define a new Model to represent the Data Layer --&gt;
        &lt;class&gt;Spinonesolutions_Helloworld_Model_Mysql4&lt;/class&gt;
        &lt;entities&gt;
          &lt;widget&gt;&lt;table&gt;widget&lt;/table&gt;&lt;/widget&gt; &lt;!-- map a table (widget) to an entity "widget" --&gt;
        &lt;/entities&gt;
      &lt;/spinonesolutions_helloworld_mysql4&gt;
      &lt;paygate&gt;
        &lt;rewrite&gt;
          &lt;authorizenet&gt;Imagistic_General_Model_Paygate_Authorizenet&lt;/authorizenet&gt;
        &lt;/rewrite&gt;
      &lt;/paygate&gt;
    &lt;/models&gt;
    &lt;resources&gt;
     &lt;spinonesolutions_helloworld_write&gt;
       &lt;connection&gt;&lt;use&gt;core_write&lt;/use&gt;&lt;/connection&gt;
     &lt;/spinonesolutions_helloworld_write&gt;
     &lt;spinonesolutions_helloworld_read&gt;
       &lt;connection&gt;&lt;use&gt;core_read&lt;/use&gt;&lt;/connection&gt;
     &lt;/spinonesolutions_helloworld_read&gt;
   &lt;/resources&gt;
  &lt;/global&gt;
&lt;/config&gt;</pre>
<p>Let’s start at the top and work our way down.  Note: I’m going to skip the custom Model stuff and just focus on what’s new for this post.</p>
<pre class="xml" name="code">&lt;spinonesolutions_helloworld&gt; &lt;!-- This is used when istanting your Model EG: Mage::getModel("spinonesolutions_helloworld/hellworld") --&gt;
  &lt;class&gt;Spinonesolutions_Helloworld_Model&lt;/class&gt; &lt;!-- That class to use when isntanting objects of type above. --&gt;
  &lt;resourceModel&gt;spinonesolutions_helloworld_mysql4&lt;/resourceModel&gt; &lt;!-- Use a custom table instead of EAV, the Model is defomed below --&gt;
&lt;/spinonesolutions_helloworld&gt;</pre>
<p>We just mapped a new resource Model (<strong>spinonesolutions_helloworld_model_mysql4</strong>) to <strong>spinonesolutions_helloworld</strong>.  You’ll notice that the Model itself is defined right after this line.</p>
<pre class="xml" name="code">&lt;spinonesolutions_helloworld_mysql4&gt; &lt;!-- Define a new Model to represent the Data Layer --&gt;
  &lt;class&gt;Spinonesolutions_Helloworld_Model_Mysql4&lt;/class&gt;
  &lt;entities&gt;
    &lt;widget&gt;&lt;table&gt;widget&lt;/table&gt;&lt;/widget&gt; &lt;!-- map a table (widget) to an entity "widget" --&gt;
  &lt;/entities&gt;
&lt;/spinonesolutions_helloworld_mysql4&gt;</pre>
<p>Just as we did for our custom Model before, we’ve now defined a new Model (<strong>spinonesolutions_helloworld_mysql4</strong>) and told Magento what its class is (<strong>Spinonesolutions_Helloworld_Model_Mysql4</strong>).  Notice that we’ve already used this new Model as the resourceModel for <strong>spinonesolutions_helloworld</strong>.</p>
<p>As well as linking this Model to its Class we’ve also mapped a table to it in the entities section.  Now the “widget” entity maps to the table “widget” in our magento database.</p>
<p>We need one more file; we’ve mapped <strong>spinonesolutions_helloworld_mysql4</strong> to the class <strong>Spinonesolutions_Helloworld_Model_Mysql4</strong> so we need to create a file to house this code.</p>
<p>/app/code/local/Spinonesolutions/Helloworld/Model/Mysql4/Widget.php:</p>
<pre class="php" name="code">class Spinonesolutions_Helloworld_Model_Mysql4_Widget extends Mage_Core_Model_Mysql4_Abstract {
  public function _construct() {
    $this-&gt;_init("spinonesolutions_helloworld/widget", "id");
  }
}</pre>
<p>Throughout this tutorial I’ve been following Magento’s naming conventions for Class definitions and file names.</p>
<p>The first parameter passed to the <strong>_init()</strong> function is the Model that defines our table, and the second parameter is the name of the PrimaryKey field.</p>
<p>Last but not least we have the “resources” section of the config.xml.  The read and write sections tell Magento what connection to use for read operations and write operations.  As long as you keep true to the naming conventions you shouldn’t need to change these values too much.</p>
<p>Let’s put it all together and do a test.  I’m going to create a table “widgets”:</p>
<p><span style="text-decoration: underline;">widgets<br />
</span>id (int) – PK<br />
title (varchar255)<br />
description (varchar255)<br />
created(datetime)<br />
modified(datetime)</p>
<p>Now we’ll create a controller to manage CRUD for our new Model.  I’ll call it WidgetController.</p>
<p>/app/code/local/Spinonesolutions/Helloworld/controllers/WidgetController.php</p>
<pre class="php" name="code">class Spinonesolutions_Helloworld_WidgetController extends Mage_Core_Controller_Front_Action {
  //indexAction is the default Action for any controller
  function indexAction() {
    echo "Spinonesolutions_Helloworld_WidgetController.indexAction()";
  }

  //{base}/spinonesolutions/widget/create/
  function createAction() {
    echo "Spinonesolutions_Helloworld_WidgetController.createAction()";
    $widget = Mage::getModel("spinonesolutions_helloworld/widget");
    $data = array(
      "title" =&gt; "My new title",
      "description" =&gt; "My new description"
    );

    $widget-&gt;setData($data);
    $widget-&gt;save();
  }
}</pre>
<p>Requesting {base}/spinonesolutions/widget/create/ results in the insertion of a new record into my widget table!  Let’s deconstruct what I’ve done a little bit to gain some understanding.</p>
<p>You’ll recognize the instantiation of the Model from my previous posts on custom Modules and Models.  Magento stores all of an object’s data in an array which is stored in a private variable <strong>_data</strong>.  Each of the array elements corresponds to a field in the table.  All Models derived from the abstract classes have getters and setters for their variables.  You can always call them by using the “get” and “set” prefix followed by camel case variable name.</p>
<p>So if the field in my database table is named “foo_bar”.  In the object, the value will be stored in <strong>_data[“foo_bar”]</strong>.  I can set the value by calling <strong>$object-&gt;setFooBar(“value”)</strong>.  I can get the value by calling <strong>$object-&gt;getFooBar()</strong>;</p>
<p>That’s all for this post!  I’ll go over widget CRUD in the next!</p>
<p>Download the source &#8211; <a title="Helloworld Source V4" href="http://www.spinonesolutions.com/wp-content/uploads/2009/11/Helloworld_v4.rar">Helloworld_v4</a></p>
<ol>
<li><a title="Part I : Custom Module" href="http://www.spinonesolutions.com/2009/09/magento-custom-module-part-i/">Part I : Custom Module</a></li>
<li><a title="Part II : Models" href="http://www.spinonesolutions.com/2009/10/magento-part-ii-models/">Part II : Models</a></li>
<li><a title="Part III : Controllers" href="http://www.spinonesolutions.com/2009/10/magento-part-iii-controllers/">Part III : Controllers</a></li>
<li><a title="Part IV : Extending Models" href="http://www.spinonesolutions.com/2009/10/magento-part-iv-extending-models/">Part IV : Extending Models</a></li>
<li><a title="Part V: Data Layer" href="http://www.spinonesolutions.com/2009/10/magento-part-v-data-layer/">Part V : Data Layer</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.spinonesolutions.com/2009/10/magento-part-v-data-layer/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Magento &#8211; Part II : Models</title>
		<link>http://www.spinonesolutions.com/2009/10/magento-part-ii-models/</link>
		<comments>http://www.spinonesolutions.com/2009/10/magento-part-ii-models/#comments</comments>
		<pubDate>Fri, 02 Oct 2009 16:18:49 +0000</pubDate>
		<dc:creator>Will Wright</dc:creator>
				<category><![CDATA[Magento]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Model]]></category>

		<guid isPermaLink="false">http://www.spinonesolutions.com/?p=362</guid>
		<description><![CDATA[The Problem: You need to work with Magento Models, how chic! The Solution: Well, let&#8217;s be honest&#8230; I don&#8217;t have THE solution, but I do have some useful snippets of information to pass along. Models are the meat of an MVC application.  They contain the definitions for your application&#8217;s components.  Stop for a moment and [...]]]></description>
			<content:encoded><![CDATA[<h2>The Problem:</h2>
<p>You need to work with Magento Models, how chic!</p>
<h2>The Solution:</h2>
<p>Well, let&#8217;s be honest&#8230; I don&#8217;t have THE solution, but I do have some useful snippets of information to pass along.</p>
<p>Models are the meat of an MVC application.  They contain the definitions for your application&#8217;s components.  Stop for a moment and think conceptually about your application.  Anything that is represented by a database table is most likely going to be a Model.  Anything that can be mentally packaged up and labeled could be a Model.  How are Models built, used, and made use of in Magento?  Let&#8217;s find out.</p>
<p>In the Previous <a title="Part I - Custom Module" href="http://www.spinonesolutions.com/2009/09/magento-custom-module-part-i/">post</a> I showed you how to create a custom Module and one of the main pieces of that Module was the Model <strong>Helloworld</strong>.</p>
<pre class="php" name="code">&lt;?php
class Spinonesolutions_Helloworld_Model_Helloworld extends Varien_Object {
  function __construct() {
    parent::__construct();
  }

  function helloworld($arg) {
    echo "&lt;br&gt;Hello World! My argument is : " . $arg;
  }
}</pre>
<p>I&#8217;m going to examine it now, in more detail, to flush out some of the intricacies of Magento.</p>
<p>Notice the class definition:</p>
<p><strong>Spinonesolutions_Helloworld_Model_Helloworld</strong></p>
<p>It&#8217;s important to maintain this naming convention since Magento uses an autoloader to load class files when they&#8217;re called for.  If they&#8217;re not named correctly it will look at the wrong place in the file system for the file which SHOULD contain the class it&#8217;s looking for, but alas it will not be there, and thus; it will not find it and you will receive an error.</p>
<p>Deconstructing the above:</p>
<p><strong>Spinonsolutions_Helloworld_Model_Helloworld</strong><br />
{Namespace}_{Module}_Model_{Model}.php</p>
<p>Let’s look at some permutations to get a deeper understanding:</p>
<p><strong>Spinonesolutions_Helloworld_Model_Worldhello</strong><br />
\Spinonesolutions\Helloworld\Model\Worldhello.php</p>
<p><strong>Spinonesolutions_Helloworld_Model_Foo_Bar<br />
</strong>\Spinonesolutions\Helloworld\Model\Foo\Bar.php</p>
<p><strong>Spinonesolutions_Helloworld_Model_Foo_Helloworld<br />
</strong>\Spinonesolutions\Helloworld\Model\Foo\Helloworld.php</p>
<p>Picking up the pattern?  Good!</p>
<p> The _<strong>_consruct</strong> method is called when Magento builds an instance of this Model.  My constructors always contain, at least, a call to the parent constructor and sometimes more depending on the Model.</p>
<p> To instantiate an instance of a Model use <strong>Mage::getModel($modelClass,$arguments)</strong> or <strong>Mage::getSingleton($modelClass,$arguments)</strong>.  The parameter <strong>$modelClass</strong> is a string, the construction of which is partially determined by the <strong>config.xml</strong> and partly by the Model’s class definition.  Let’s look at <strong>IndexController</strong> from <a title="Part I: Magento Custom Module" href="http://www.spinonesolutions.com/2009/09/magento-custom-module-part-i/">Part I</a>, line 23.</p>
<pre class="php" name="code">&lt;?php
//IndexController is the default controller
//EG: http://localhost/spinonesolutions/
//Notice there's no parameters being passed as a parameter (Nothing after trailing "/")
//IndexController will be called since it's the default.
//"spinonesolutions" is the frontname as defined in confg.xml
class Spinonesolutions_Helloworld_IndexController extends Mage_Core_Controller_Front_Action {

  //indexAction is the default Action for any controller
  function indexAction() {
    echo "indexAction";
    $helloworld = Mage::getModel("spinonesolutions_helloworld/helloworld");
    $helloworld-&gt;helloworld("helloworld");
  }
}</pre>
<p>The piece of <strong>$modelClass</strong> that comes before the backslash (spinonesolutions_helloworld) is defined in the <strong>config.xml</strong> file included in the <strong>etc</strong> directory of your Module.</p>
<pre class="xml" name="code">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;config&gt;
&lt;modules&gt;
&lt;Spinonesolutions_Helloworld&gt;
&lt;version&gt;0.1.0&lt;/version&gt;
&lt;/Spinonesolutions_Helloworld&gt;
&lt;/modules&gt;
&lt;frontend&gt;
&lt;routers&gt;
&lt;spinonesolutions&gt; &lt;!-- I make this match my front name but I'm not sure it matters --&gt;
&lt;use&gt;standard&lt;/use&gt; &lt;!-- Use standard routing as opposed to admin. IE: frontend vs admin --&gt;
&lt;args&gt;
&lt;module&gt;Spinonesolutions_Helloworld&lt;/module&gt; &lt;!-- The module to search for controllers --&gt;
&lt;frontName&gt;spinonesolutions&lt;/frontName&gt; &lt;!-- The first descriminator in the path. "spinonesolutions" in http://localhost/spinonesolutions/ --&gt;
&lt;/args&gt;
&lt;/spinonesolutions&gt;
&lt;/routers&gt;
&lt;/frontend&gt;
&lt;global&gt;
&lt;models&gt;
&lt;spinonesolutions_helloworld&gt; &lt;!-- This is used when istanting your Model EG: Mage::getModel("spinonesolutions_helloworld/hellworld") --&gt;
&lt;class&gt;Spinonesolutions_Helloworld_Model&lt;/class&gt; &lt;!-- That class to use when isntanting objects of type above. --&gt;
&lt;/spinonesolutions_helloworld&gt;
&lt;/models&gt;
&lt;/global&gt;
&lt;/config&gt;</pre>
<p>Notice the <strong>models</strong> element.  It’s defining a label for the class (and folder) <strong>Spinonesolutions_Helloworld_Model</strong>.  Said in another way; given <strong>spinonesolutions_helloworld</strong>, the <strong>models</strong> element tells Magento what class and, by naming convention, what folder to look in for the second piece; that which comes after the backslash.</p>
<p>The piece that comes after the backslash (helloworld) tells Magento what particular Model you’re looking for.  In my example, it’s simply <strong>helloworld</strong>, so the autoloader is going to be looking for a file named <strong>Helloworld.php</strong> that contains a class definition <strong>Spinonesolutions_Helloworld_Model_Helloworld</strong>.  Lets extend the permutations that we used earlier adding how to instantiate each.</p>
<p><strong>Spinonesolutions_Helloworld_Model_Worldhello</strong><br />
\Spinonesolutions\Helloworld\Model\Worldhello.php<br />
$objModel = Mage::getModel(‘spinonesolutions_helloworld/worldhello’);</p>
<p><strong>Spinonesolutions_Helloworld_Model_Foo_Bar<br />
</strong>\Spinonesolutions\Helloworld\Model\Foo\Bar.php<br />
$objModel = Mage::getModel(‘spinonesolutions_helloworld/foo_bar’);</p>
<p><strong>Spinonesolutions_Helloworld_Model_Foo_Helloworld<br />
</strong>\Spinonesolutions\Helloworld\Model\Foo\Helloworld.php<br />
$objModel = Mage::getModel(‘spinonesolutions_helloworld/foo_helloworld’);</p>
<p>A great way to get a handle on how the naming conventions work is to meander through the <strong>core</strong> and note of name of the file and the folder structure it’s been placed in; then compare that to the class definition contained within.</p>
<p>One more time; since it took me a while to figure this out!</p>
<p><span style="color: #ff0000;">\Spinonesolutions\Helloworld\Model</span>\<span style="color: #3366ff;">Helloworld.php</span></p>
<p><span style="color: #ff0000;">Spinonesolutions_Helloworld_Model</span>_<span style="color: #3366ff;">Helloworld</span></p>
<p><span style="color: #339966;">&lt;spinonesolutions_helloworld&gt;</span><br />
    &lt;class&gt;<span style="color: #ff0000;">Spinonesolutions_Helloworld_Model</span>&lt;/class&gt;<br />
<span style="color: #339966;">&lt;/spinonesolutions_helloworld&gt;<strong></strong></span></p>
<p>$objModel = Mage::getModel(‘<span style="color: #339966;">spinonesolutions_helloworld</span>/<span style="color: #3366ff;">helloworld</span>);</p>
<p>Do you see it!  Do you!?</p>
<p>One awesome, and very useful, property of Models is that they can extend any other Model you want.  This is, in general, how you extend <strong>core</strong> Models with your own functionality.</p>
<p>This is absolutely essential when you want to add on to the Magento code base.  If you just fire up your text editor and make your changes to the <strong>core,</strong> the next time you upgrade Magento, there’s a relatively good chance you’ll lose all your work.</p>
<p>That’s all for Models! Not really though, I’ve just covered the basics here, read on for more as I cover extending!</p>
<p>Download the source &#8211; <a href="http://www.spinonesolutions.com/wp-content/uploads/2009/09/Helloworld.rar">Helloworld</a></p>
<ol>
<li><a title="Part I : Custom Module" href="http://www.spinonesolutions.com/2009/09/magento-custom-module-part-i/">Part I : Custom Module</a></li>
<li><a title="Part II : Models" href="http://www.spinonesolutions.com/2009/10/magento-part-ii-models/">Part II : Models</a></li>
<li><a title="Part III : Controllers" href="http://www.spinonesolutions.com/2009/10/magento-part-iii-controllers/">Part III : Controllers</a></li>
<li><a title="Part IV : Extending Models" href="http://www.spinonesolutions.com/2009/10/magento-part-iv-extending-models/">Part IV : Extending Models</a></li>
<li><a title="Part V: Data Layer" href="http://www.spinonesolutions.com/2009/10/magento-part-v-data-layer/">Part V : Data Layer</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.spinonesolutions.com/2009/10/magento-part-ii-models/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
