<?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; Data Layer</title>
	<atom:link href="http://www.spinonesolutions.com/tag/data-layer/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 &#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>
	</channel>
</rss>
