Magento Module Development Series – Part6- Module – Models

In this blog, we will learn about magento models, and how to perform basic sql operations.

Model are used to logical + data operations in MVC pattern. In magento, these are used for the same propose.
In this blog, we will continue on the previous blog created, will make these changes to the config.xml file.
There are two parts to models in magento, 1st is the Model file and 2nd Model resource files. Models are used to for logical operation and resource files are used to perform actual database queries. Below are additions that we need to make the config.xml file, to include models in our module.

    <global>
        <models>
            <test>
                <class>Excellence_Test_Model</class> <!-- Location of all model class files -->
                <resourceModel>test_mysql4</resourceModel> <!-- Location of resource model -->
            </test>
            <test_mysql4>
                <class>Excellence_Test_Model_Mysql4</class>
                <entities>
                    <test> 
                        <table>test_tablename</table>  <!-- Actual table name in sql  -->
                    </test>
                </entities>
            </test_mysql4>
        </models>
        <resources>  <!-- These are resource setting giving access to module, read/write permission on database --> 
            <test_setup>
                <setup>
                    <module>Excellence_Test</module>
                </setup>
                <connection>
                    <use>core_setup</use>
                </connection>
            </test_setup>
            <test_write>
                <connection>
                    <use>core_write</use>
                </connection>
            </test_write>
            <test_read>
                <connection>
                    <use>core_read</use>
                </connection>
            </test_read>
        </resources>
    </global>

Explanation of important few sections added above.

<entities>
   <test>  
        <table>test_tablename</table>  <!-- Actual table name in sql  -->
   </test>
</entities>

Here basically, we add a list of all our tables we would like to use in our module.
For example,

<entities>
   <test>  
        <table>test_tablename</table>
   </test>
   <test2>  
        <table>test_tablename2</table>
   </test2>
   <test3>  
        <table>test_tablename3</table>
   </test3>
</entities>

As you will see ahead, in magento we reference all database table names using a different identifier, and in the <entities> tag, we defined the relation between magento table identifies and actual table name. For e.g.
“test/test” => test_tablename
“test/test2” => test_tablename2
“test/test3” => test_tablename3

Next we will create the model file. Lets create file Test.php in the model folder as follows

<?php
class Excellence_Test_Model_Test extends Mage_Core_Model_Abstract
{
    public function _construct()
    {
        parent::_construct();
        $this->_init('test/test'); // this is location of the resource file.
    }
}

It’s important to note here that ‘test/test’ in the $this->_init() function points to the location of the resource file.

Next we need to create the resource files, for that create a Mysql4 folder in Model folder.And then create a Test.php file inside Mysql4 folder.
So file location is \app\code\local\Excellence\Test\Model\Mysql4\Test.php

<?php
class Excellence_Test_Model_Mysql4_Test extends Mage_Core_Model_Mysql4_Abstract
{
    public function _construct()
    {    
        $this->_init('test/test', 'test_id');  // here test_id is the primary of the table test. And test/test, is the magento table name as mentioned in the       //config.xml file.
    }
}

Again important to note here, that ‘test/test’ here is the magento table identifier we create in the config.xml file.

Now let’s create the sql file to create the database table. In the sql folder, create a sub folder called test_setup. And create a file called mysql4-install-0.1.0.php [here 0.1.0 is the version of the module as mentioned in the config.xml file.]

<?php
$installer = $this;  //Getting Installer Class Object In A Variable
$installer->startSetup();
$installer->run("
-- DROP TABLE IF EXISTS {$this->getTable('test')}; 
CREATE TABLE {$this->getTable('test')} (
  `test_id` int(11) unsigned NOT NULL auto_increment,
  `title` varchar(255) NOT NULL default '',
  `filename` varchar(255) NOT NULL default '',
  `content` text NOT NULL default '',
  `status` smallint(6) NOT NULL default '0',
  `created_time` datetime NULL,
  `update_time` datetime NULL,
  PRIMARY KEY (`test_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
");
$installer->endSetup();
?>

As you can see clearly, here we are creating the SQL table. One important thing to notice here is the function used for table name $this->getTable(‘test’). We use the getTable function here, so the table name automatically gets prefixed with the magento tables prefix (if any added during the installation process.). So, now our Model, Resource Model, and sql table are setup.

This sql file which is created is executed when any magento page is opened in the browser. They way it works is, there is a database table called, “core_resource”. This file maintains module version and name of each module loaded into magento. For example in our case module name would be test_setup i.e the folder of the sql files and module version is 0.0.1. What magento does is check the module version in database and the module version our config.xml file. If the version in config.xml greater than database version, it executes the corresponding sql file and update the module version in database.
In our case, we had already loaded the module before(in our previous blogs.), without the sql file. So, our db table already has the version 0.0.1 and also our current module version is also 0.0.1 , so our sql won’t get executed. You can test this by opening phpmyadmin and your new table won’t be created in the database, when you open magento. So, to execute our sql file, we need to remove the row of our module in the core_resource table of our module only and then open magento again.
Another way or rather the correct way to load sql file is, that we will increase our version number of our module to 0.0.2. So in our config.xml file in the <version> tag, we will put in the version no 0.0.2. And similarly, we will create a new sql file named mysql4-upgrade-0.0.1-0.0.2.php. Now when we open our magento pages again, magento will check the ‘core_resource’ table, and in that table our module version number would be 0.0.1. But in our config.xml file we have updated our version number to 0.0.2, so magento will check if we have any sql update file and execute it. After executing it, the version in the ‘core_resource’ table will again be updated to the latest version. This will also give a hint on how magento update process works.

Save, Load and Delete Functions

All models in magento which inherit the class Mage_Core_Model_Abstract have save(), delete() and load() function, among many other important functions. Before going into these functions, there is another important thing to learn. Every model in magento you call any getter and setter function.
For eg. $model->setAbc() will work and $model->getAbc() will return the value. Similarly, $model->setManish(), $model->setCreatedDate() can be done. Another function to remember, is $model->getData(). This function returns an array, of all that has been ‘set’ in the models through the setter functions.
If you are wondering how these setters and getters are implemented, it done through php magic functions. And these are implemented in classes Varien_Object.

Save function is used to do the INSERT operation in a table. So, before saving a model, you need to first set all the values in the model. In our case,

$model = Mage::getModel(‘test/test’);
$model->setTitle(‘test title’);
$model->setFilename(‘filename’);
$model->setContent(‘abc abc abc’);
$model->setStatus(1);
$model->setCreatedTime(strtotime(‘now’));
$model->setUpdatedTime(strtotime(‘now’));
$model->save();

As you would notice, these are same as our database table columns. This will insert all these values into corresponding columns in the table. After, save operation is done. You will get the Primary Key (test_id) of the table.
For this you can do,

$id = $model->getTestId();
Or
$id = $model->getId();

Load, function as the name suggests, is used to read a row from the table and set the values in the model.
For load function to work, you need to have primary key of the table. For eg.

$test_id = 3;
$model = Mage::getModel(‘test/test’)->load($test_id);
echo $model->getTitle();
print_r($model->getData());
$model->setTitle(‘new title’);
$model->save();  //This will update the existing row in the table, for the primary key loaded with. This will not insert a new column.

Delete, function will delete the row from the table, based on the primary key. So, if we do $model->delete() it will delete the row, for the primary key loaded in the model.

$test_id = 3;
$model = Mage::getModel(‘test/test’)->load($test_id);
$model->delete();
_before and _after functions

As our model classes inherit Mage_Core_Model_Abstract, we get access to many useful function in our model classes. We have already discussed save(),load() and delete() functions. Other useful function are, _beforeSave(), _afterSave(), _beforeLoad(), _afterLoad(), _beforeDelete(), _afterDelete(). As the name suggests, these functions are called before and after their respective operations.
_beforeSave(): is called just before saving a model. So if you want to perform a validation before saving, you can do it here.
E.g if suppose before saving a User Model, we need to check for duplicate email address. So code for that would be like

protected function _beforeSave()
    {
        parent::_beforeSave();
        if($this->getResource()->checkDuplicate($this)){
           throw new Exception('User Email Already Exists');
        }
//$this->getResource()   returns the object of the resource model, where can put in the sql operations
        return $this;
    }

Similarly, we can use other functions as well.

Exercise:
1. Create a table UI in fronted magento to do Add/Edit/Delete/View operation on a database table.
2. Extend the previous question, to do Add/Edit/Delete/View operations on two tables.
  • Abc

    good post

  • Yaboosa

    Hello Manish, I’m passing on review all your tutorials and they are very interisting. Concerning Module Developement, on this serie, I’d like to have explanations about the Save, Load and Delete functions on which file we have to write (call) them, on the model or phtml? thank you for your help.

    • Manish Prakash

      Well save(), load() and delete() function you can them in both model file and phtml file. 

      In a phtml file suppose page/html/header.phtml  or in any file in magento i.e controllers, helopers, blocks
      you  can write
      Mage::getModel(‘your_module/your_model’)->load(10);
      and similarly other functions 

      If you are writing code inside the model itself, 
      then you can use $this->load(19); $this->delete(); etc

      Hope this is clear. 

  • tegs

    Hi Manish, your posts on the module development series are very helpful!
    With regards to the script example for mysql4-install-0.1.0.php, I think instead of:
    $this->getTable(‘test’) 

    it would be more accurate to have the argument as ‘module/table’,
    $this->getTable(‘test/test’)  

    otherwise the name that gets used is what is put in the argument ‘test’ and not ‘test_tablename’.

  • Geoff Safcik

    Hi Manish,

    Thank you so much for the tutorials. I’m following them using MAMP on Mac OSX and I’m stuck at the “upgrade” part. Everything seems to go smoothly when I upgrade but no table is made. Why would this be? I check in core_resource and the version does upgrade with every upgrade file (and version change to config.xml) but NO table is ever created…

    • Geoff Safcik

      Figured out my issue. The 1st two lines of the install script sql (“DROP TABLE…” and “CREATE TABLE…”) needed tick marks (accent marks) around the “{$this->getTable(‘test’)}” to look like this:

      DROP TABLE IF EXISTS `{$this->getTable(‘test’)}`;CREATE TABLE `{$this->getTable(‘test’)}` (

      instead of this:

      DROP TABLE IF EXISTS {$this->getTable(‘test’)};CREATE TABLE `{$this->getTable(‘test’)} (

      Small thing but caused an Internal Server Error on my localhost.

  • Kalashri

    You are simply Awesome!!!! 🙂

  • Tuan

    nice tutorial
    thx u

  • vikas

    hi ,

    i get an error :”Can’t retrieve entity config: .

    can you help me .

  • rohit patel

    after creating table all tutorials post is confusing. where should i put the save(), load(), delete() code, in which file ? before clearing this i can’t go ahead. please replay ASAP if anyone know.

  • shihab

    Hi Manish

    The tutorial is looking great. i would like to get the this module complete files … because i am missing some files.
    please send me the link to download the files

    thanks
    shihab

    • Manish Prakash

      Hi Shihab,

      Thanks for complement, currently all of our modules are in up gradation phase for latest Magento Releases.
      If you need module you can contact [email protected]

      Thanks