Magento: How to create a Magento Model Triad

Star InactiveStar InactiveStar InactiveStar InactiveStar Inactive
 

The finished code is available on GitHub.

1. Structure

To start we need to create a custom module in local/{Namespace} with the following folder structure:

NaughtyOrNice
  |___etc/
  |___Helper/
  |___Model/
      |___List.php
      |___Resource/
          |______List.php
          |______List/
                |____Collection.php
 

2. Setup the basic module:

Create the following files within your folder structure to get the the basic module with an installer.

etc/config.xml:

Define the modules config to have a model, helper and installer resource.

<?xml version="1.0"?>
<config>
    <modules>
        <Invent_NaughtyOrNice>
            <version>0.1.0</version>
        </Invent_NaughtyOrNice>
    </modules>
    <global>
        <models>
            <invent_naughtyornice>
                <class>Invent_NaughtyOrNice_Model</class>
                <resourceModel>invent_naughtyornice_resource</resourceModel>
            </invent_naughtyornice>
            <invent_naughtyornice_resource>
                <class>Invent_NaughtyOrNice_Model_Resource</class>
                <entities>
                    <list>
                        <table>invent_naughtyornice_list</table>
                    </list>
                </entities>
            </invent_naughtyornice_resource>
        </models>
        <helpers>
            <invent_naughtyornice>
                <class>Invent_NaughtyOrNice_Helper</class>
            </invent_naughtyornice>
        </helpers>
        <resources>
            <invent_naughtyornice_setup>
                <setup>
                    <module>Invent_NaughtyOrNice</module>
                </setup>
            </invent_naughtyornice_setup>
        </resources>
    </global>
</config>
 
 
Helper/Data.php:

Define an empty Helper as per Magento best practices to ensure the translation subsystem works.

<?php
class Invent_NaughtyOrNice_Helper_Data extends Mage_Core_Helper_Abstract {}
 
 

sql/invent_naughtyornice_setup/install-0.1.0.php

This is where we setup our database table. I am going to keep this very simple with 3 fields:

Field Type
id Auto incremental integer primary key
customer_id Foreign Key to Customer
is_naughty Boolean with default false

With this setup each customer can have many entries which can act like a voting system.

<?php
 /* @var $installer Mage_Core_Model_Resource_Setup */
$installer = $this;
 
$installer->startSetup();
 
//get the table name from etc/config.xml
$table = $installer->getTable('invent_naughtyornice/list');
 
//if the table exists we drop and recreate, useful for development rollbacks.
if ($installer->tableExists($table)) {
        $installer->getConnection()->dropTable($table);
}
 
/** @var $ddlTable Varien_Db_Ddl_Table */
$ddlTable = $installer->getConnection()->newTable($table);
 
$ddlTable
        ->addColumn('id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
                'primary' => true, //primary key
                'identity' => true, //auto_increment
                'unsigned' => true, //not a minus number
                'nullable' => false //not null
        ), 'id')
        ->addColumn('customer_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
                'nullable' => false
        ), 'Customer ID')
        ->addColumn('is_naughty', Varien_Db_Ddl_Table::TYPE_BOOLEAN, null, array(
                'nullable' => false,
                'default' => 0 //default to false aka nice
        ), 'Is Naughty')
        ->addForeignKey( //add a foreign key constraint to the customer
                $installer->getFkName(
                    'invent_naughtyornice/list',
                    'customer_id',
                    'customer/entity',
                    'entity_id'),
                    'customer_id',
                    $installer->getTable('customer/entity'),
                    'entity_id',
.                    Varien_Db_Ddl_Table::ACTION_CASCADE,
                     Varien_Db_Ddl_Table::ACTION_CASCADE
        )->setComment('Invent Naughty Or Nice');
// CASCADE means if the customer is deleted their record will be deleted
 
$installer->getConnection()->createTable($ddlTable);
$installer->endSetup();
 
Magento root/app/etc/modules/{Namespace/Invent}_NaughtyOrNice.xml

Enable the module

<?xml version="1.0"?>
<config>
    <modules>
        <Invent_NaughtyOrNice>
            <active>true</active>
            <codePool>local</codePool>
        </Invent_NaughtyOrNice>
    </modules>
</config>

3. Building the triad

The triad consists of a model, resource model and a resource collection.

Model/
 |___List.php
 |___Resource/
     |_____List.php
     |_____List/
           |_____Collection.php

 

3a. Model

The model will handle our business logic, create the following in Model/List.php:

<?php
class Invent_NaughtyOrNice_Model_List extends Mage_Core_Model_Abstract
{
        /**
         * Initialise the resource model in order to connect to the database.
         */
        protected function _construct()
        {
                $this->_init('invent_naughtyornice/list');
        }
 
        /**
         * Add random customer to be randomly naughty or nice.
         *
         * @return bool
         */
        public function addRandomCustomer()
        {
                $collection = Mage::getModel('customer/customer')->getCollection();
                $collection->getSelect()
                        ->order('RAND()') //randomise order
                        ->limit(1); //limit to one
 
                if ($collection->getSize()) {
                        $customer_id = $collection->getFirstItem()->getId();
 
                        $this->setCustomerId($customer_id)
                                ->setIsNaughty(mt_rand(0, 1)) //true or false random
                                ->save();
 
                        return true;
                }
 
                return false;
 
        }
 
        /**
         * Get a single random nice entry from our table
         *
         * @return Varien_Object
         */
        public function getRandomNiceCustomer()
        {
                /* @var $collection Invent_NaughtyOrNice_Model_Resource_List_Collection */
                $collection = $this->getCollection();
 
                $collection->addRandomSelect()->addNiceFilter();
 
                return $collection->getFirstItem();
 
        }
 

 

}

 

3b. Resource Model

The resource model  makes the connection with our database, create the following in Model/Resource/List.php:

<?php
class Invent_NaughtyOrNice_Model_Resource_List extends Mage_Core_Model_Resource_Db_Abstract
{
 
        /**
         * Link the resource model to our table and tell it our primary id
         */
        protected function _construct()
        {
                $this->_init('invent_naughtyornice/list', 'id');
        }
 
}

 

3c. Resource Collection

The resource collection allows us to build reusable collection methods to query the data. Create the following in Model/Resource/List/Collection.php

<?php
class Invent_NaughtyOrNice_Model_Resource_List_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract
{
 
        /**
         * Initialise the base collection for the list
         */
        protected function _construct()
        {
                $this->_init('invent_naughtyornice/list');
        }
 
        public function addRandomSelect() {
                $this->getSelect()
                        ->order('RAND()') //randomise order
                        ->limit(1);
 
                return $this;
        }
 
        public function addNaughtyFilter() {
                $this->addFieldToFilter('is_naughty', true);
 
                return $this;
        }
 
        public function addNiceFilter() {
                $this->addFieldToFilter('is_naughty', false);
 
                return $this;
        }
 
}

 

4. Success!

Hopefully now you will have a fully database integrated model, lets try the methods we defined to add some data and get our nice customers.

I am going to use a shell script, in your Magento roots shell folder put the following in shell.php.

<?php
require_once 'abstract.php';
 
class HOHOHO extends Mage_Shell_Abstract
{
 
        public function run()
        {
                $model = Mage::getModel('invent_naughtyornice/list');
                if ($this->getArg('add')) {
                        $model->addRandomCustomer();
                } elseif ($this->getArg('get')) {
                        $entry = $model->getRandomNiceCustomer();
                        if ($entry) {
                                echo sprintf('Customer ID (%d) is nice', $entry->getCustomerId()) . PHP_EOL;
                        }
 
                } else {
                        echo $this->usageHelp();
                }
        }
 
}
 
$shell = new HOHOHO();
$shell->run();

 

Finally, run the following commands from the shell:

php shell.php add                    [Randomly adds customer to table]

php shell.php get                     [Gets first nice customer]

 

Thanks for reading, I hope you have found it useful and please leave any feedback/questions and I will try and get back to you.


© 2019 SQLI LTD. All Rights Reserved.