Book Image

Magento PHP Developer????s Guide, 2nd Edition

By : Allan MacGregor
Book Image

Magento PHP Developer????s Guide, 2nd Edition

By: Allan MacGregor

Overview of this book

Table of Contents (16 chapters)
Magento PHP Developer's Guide Second Edition
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Factory names and functions


Magento makes use of factory methods to instantiate models, helpers, and block classes. A factory method is a design pattern that allows us to instantiate an object without using the exact class name and using a class alias instead.

Magento implements the following factory methods:

  • Mage::getModel()

  • Mage::getResourceModel()

  • Mage::helper()

  • Mage::getSingleton()

  • Mage::getResourceSingleton()

  • Mage::getResourceHelper()

Each of these methods takes a class alias that is used to determine the real class name of the object that we are trying to instantiate. For example, if we want to instantiate a product object, we can do so by calling the getModel() method:

$product = Mage::getModel('catalog/product'); 

Notice that we are passing a factory name composed of group_classname/model_name. Magento will resolve this to the actual class name of Mage_Catalog_Model_Product. Let's take a closer look at the inner workings of getModel():

public static function getModel($modelClass = '', $arguments = array())
    {
        return self::getConfig()->getModelInstance($modelClass, $arguments);
    }

getModel calls the getModelInstance from the Mage_Core_Model_Config class.

public function getModelInstance($modelClass='', $constructArguments=array())
{
    $className = $this->getModelClassName($modelClass);
    if (class_exists($className)) {
        Varien_Profiler::start('CORE::create_object_of::'.$className);
        $obj = new $className($constructArguments);
        Varien_Profiler::stop('CORE::create_object_of::'.$className);
        return $obj;
    } else {
        return false;
    }
}

In return, getModelInstance() calls the getModelClassName() method that takes a class alias as a parameter. Then, it tries to validate the existence of the returned class, and if the class exists, it creates a new instance of that class and returns it to our getModel() method:

public function getModelClassName($modelClass)
{
    $modelClass = trim($modelClass);
    if (strpos($modelClass, '/')===false) {
        return $modelClass;
    }
    return $this->getGroupedClassName('model', $modelClass);
}

The getModelClassName() method calls the getGroupedClassName() method, which is actually in charge of returning the real class name of our model.

The getGroupedClassName() method takes two parameters, namely $groupType and $classId. The $groupType parameter refers to the type of object that we are trying to instantiate. Currently, only models, blocks, and helpers are supported. The $classId that we are trying to instantiate is as follows:

public function getGroupedClassName($groupType, $classId, $groupRootNode=null)
{
    if (empty($groupRootNode)) {
        $groupRootNode = 'global/'.$groupType.'s';
    }
    $classArr = explode('/', trim($classId));
    $group = $classArr[0];
    $class = !empty($classArr[1]) ? $classArr[1] : null;

    if (isset($this->_classNameCache[$groupRootNode][$group][$class])) {
        return $this->_classNameCache[$groupRootNode][$group][$class];
    }
    $config = $this->_xml->global->{$groupType.'s'}->{$group};
    $className = null;
    if (isset($config->rewrite->$class)) {
        $className = (string)$config->rewrite->$class;
    } else {
        if ($config->deprecatedNode) {
            $deprecatedNode = $config->deprecatedNode;
            $configOld = $this->_xml->global->{$groupType.'s'}->$deprecatedNode;
            if (isset($configOld->rewrite->$class)) {
                $className = (string) $configOld->rewrite->$class;
            }
        }
    }
    if (empty($className)) {
        if (!empty($config)) {
            $className = $config->getClassName();
        }
        if (empty($className)) {
            $className = 'mage_'.$group.'_'.$groupType;
        }
        if (!empty($class)) {
            $className .= '_'.$class;
        }
        $className = uc_words($className);
    }
    $this->_classNameCache[$groupRootNode][$group][$class] = $className;
    return $className;
}

As we can see, getGroupedClassName() is actually doing all the work. It grabs our class alias catalog/product and creates an array by exploding the string on the slash character.

Then, it loads an instance of Varien_Simplexml_Element and passes the first value in our array (group_classname). It also checks if the class has been rewritten, and if it has, we will use the corresponding group name.

Magento also uses a custom version of the uc_words() function that will capitalize the first letters and convert separators of the class alias if needed.

Finally, the function will return the real class name to the getModelInstance() function. In our example case, this will return Mage_Catalog_Model_Product: