Objects PHP Accessor Functions and Magento

By ryan, January 16, 2015

OOP (Object Oriented Programming) is a concept that is difficult to truly understand early in development.  The best analogy is the Taxonomy of Life (Kingdom, Phylum, Class, Order, Family, Genus, Species) and inheritance of the levels above you.

In Magento these levels are more like: Layout, Resource, Block, Config, Model, Controller and Helper.  There are a few other families in there as well but these are the main ones that drive Magento.

By this structure different models all share a common design (Varien_Object).  When creating a new class (a group of related functions and attributes) typically you extend from something similar.  Example: class New_Model extends Model.  New_Model now inherits properties and functions of Model.

If a function is defined in the parent (Model) it can be written again in the class Test_Model and changed all together or use the parents definition instead. Ex:

class Model {
    protected $example_a;
 
    public function setExampleA($value){
        $this->example_a = $value;
    }
    public function getExampleA(){
        return $this->example_a;
    }
 
}
class New_Model extends Model{
    protected $example_b;
 
    public function setExampleB($value){
        $this->example_b = $value;
    }
    public function getExampleB(){
        return $this->example_b;
    }
}

This would create 2 objects. Model has 1 property, and 2 functions (a getter and a setter) also known as accessor functions to that property and New_Model has 2 properties with 4 accessor functions defined.

This creates often a need to not only identify the class – but also the parents as well.

In Magento this accessor pattern is actually built into the code (via: Varien_Object – /lib/Varien/Object.php). See below (paraphrased version of getData() and setData()):

 public $data = array();
 public function getData($attribute){
     return $this->data[$attribute];
 }
 public function setData($attribute, $value){
     $this->data[$attribute] = $value;
 }
 
    /* __CALL FUNCTION DEFINED AS MAGENTO */
    public function __call($method, $args)
    {
        switch (substr($method, 0, 3)) {
            case 'get' :
                //Varien_Profiler::start('GETTER: '.get_class($this).'::'.$method);
                $key = $this->_underscore(substr($method,3));
                $data = $this->getData($key, isset($args[0]) ? $args[0] : null);
                //Varien_Profiler::stop('GETTER: '.get_class($this).'::'.$method);
                return $data;
 
            case 'set' :
                //Varien_Profiler::start('SETTER: '.get_class($this).'::'.$method);
                $key = $this->_underscore(substr($method,3));
                $result = $this->setData($key, isset($args[0]) ? $args[0] : null);
                //Varien_Profiler::stop('SETTER: '.get_class($this).'::'.$method);
                return $result;
 
            case 'uns' :
                //Varien_Profiler::start('UNS: '.get_class($this).'::'.$method);
                $key = $this->_underscore(substr($method,3));
                $result = $this->unsetData($key);
                //Varien_Profiler::stop('UNS: '.get_class($this).'::'.$method);
                return $result;
 
            case 'has' :
                //Varien_Profiler::start('HAS: '.get_class($this).'::'.$method);
                $key = $this->_underscore(substr($method,3));
                //Varien_Profiler::stop('HAS: '.get_class($this).'::'.$method);
                return isset($this->_data[$key]);
        }
        throw new Varien_Exception("Invalid method ".get_class($this)."::".$method."(".print_r($args,1).")");
    }

This function that is inherited through all Models in Magento replaces the need to manually build the functions written in the Model and New_Model example above.

The __call() function in PHP is kind of an overflow method – what to do if you have nothing defined… undefined calls would fall into this function. Magento uses this by capturing the called method and triggering a get, set, unset or has function that is defined under the getData() function.

$product = Mage::getModel('catalog/product');
// Both calls below would result in the exact same result.
// they would store the value 'My Product Name' into the attribute name
// $this->data['name'] would be the location stored in object.
$product->setData('name','My Product Name');
$product->setName('My Product Name');
 
 
 
/*
    This is the one of the keys to understanding Magneto.
*/