The Process and Configuration of Class Overrides in Magento. Register an Observer (Magento Certified Developer Exam)

We suppose you continue following our Magento certification-dedicated posts in our blog. This time we will describe two topics – the Process and Configuration of Class Overrides in Magento and Register an Observer.

In the previous post we have described the following factory methods, used in Magento.

1

2

3

•forblocksMage_Core_Model_Layout::createBlock(...)

•formodelsMage::getModel(...)andgetResourceModel(...)

•forhelpersMage::helper(...)

Due to the use of these factory methods, it became possible to implement rewrite.

What is it and how can we make use of it?

Let’s take the example of a model. As we mentioned, due to the getModel(‘catalog/product’) method, Magento returns an object of a certain class the way as follows:

1) It defines class name.
2) It creates an object for this class and calls autoloader.
a. It turns class name into Mage/Catalog/Model/Product.php path.
b. Server searches this file automatically among 3 codepools (local, community, core) and in the lib directory.

As a result, Magento loads the first found class according to the order, defined in include_path.

If we want to change basic Magento functionality, here are the options.

To do poorly. We can simply duplicate the file and its path (see the ‘a’ step above) into local codepool. Our class will be loaded from the local folder due to the priority of this codepool in the list, mentioned in include_path. Now make the necessary changes in the copied file.

So why is it bad? Because after copying the entire file, we will most likely miss all changes, made in a new version of the file, when Magento update is released. This method is better to be used for fast and dirty fixes.

To act smart. Inherit this class and describe in it changes only. There is a huge plus, compared to the previous method – readability. After all, we immediately see what was changed. Rewrite hurries to our rescue here. It allows us on the very first define class name stage to replace the name of the existing class with the name of our class (inherited from the original one).

How to describe it

Let’s create a module. In config.xml inside globals -> models, blocks and helpers we can specify our rewrites. For example, to override the standard class of the Mage_Catalog_Model_Product product, you need to use:

1

2

3

4

5

6

7

8

9

10

11

<global>

...

<models>

...

<catalog>

<rewrite>

<product> Namespace_Modulename_Model_Myproduct </product>

</rewrite>

</catalog>

</models>

</global>

Principle is the same as in Magento path.

<catalog> – specify module namespace (catalog – node name can be viewed in module configuration in the section for modules);
<rewrite> – mark that next the list of module rewrites will be described;
<product> – part of the classname following the group classname (Mage_Catalog_Model). A new class name is specified inside, and the class will be used instead of the standard one.

To override the Mage_Adminhtml_Sales_Order_Create class, we will add the following lines in configuration (models section):

getGroupedClassName makes search in rewrites, described in the layout. What will happen if we describe several rewrites for a single class? The first found will be executed. Peep inside a previous post Module Conflicts to find out more about such cases.

Creating rewrite for Blocks and Helpers is similar. We also have another integral part of Magento MVC – controllers. How can we change the functionality of a standard controller?

Controllers

To override the controller, we add a new router to config.xml of the module (expect to read more about router in the future posts). In brief, the pattern below helps establish the connection between router (used in the url) and a particular module.

1

2

3

4

5

6

7

8

9

10

11

<frontend>

<routers>

<modulename>

<use>standard</use>

<args>

<module>Namespace_Modulename</module>

<frontName>routername</frontName>

</args>

</modulename>

</routers>

</frontend>

Creating modules, we normally set the connection between our router and a module. In this case we override the connection of existing router with our module.

1

2

3

4

5

6

7

8

9

10

11

12

13

<frontend>

<routers>

<prevmodulename>

<args>

<modules>

<namespace_modulename before="Prevnamespace_Prevmodulename">

Namespace_Modulename

</namespace_modulename>

</modules>

</args>

</prevmodulename>

</routers>

</frontend>

Now we create a controller with the same name in our module like this:

Prevnamespace, Prevmodulename – name space and modul name, where we need to override the controller.Filename – the name of an overridable controllerNamespace, Modulename– name space and module name with an extended controller.

Rewrites may certainly be inevitable. But they cause modules conflicts and problems with updates. How do we pull ourselves through this? Let’s have a look at a very classy way to affect Magento.

This pattern helps developing independent modules that embed their functionality with the help of events. It means it will be way more preferable to find an “observer” instead of rewriting the class. This observer will allow executing events at a certain time, influencing some kind of data. How is it realized?

Look for the mentioned notes in the codeMage::dispatchEvent(‘event_name’, $event_arguments);

This note is an “observer” that allows executing methods, attached to it, transferring $event_arguments data array into methods.

For example, there is a great “observer” in the Mage_Core_Model_Abstract class, which allows impacting any object after it has been saved in database as far as models inherit Mage_Core_Model_Abstract.

Let’s have a look at the Mage_Catalog_Model_Product model. After saving the product, the described method will be called.

1

2

3

4

5

6

$this->_eventPrefix='catalog_product';

$this->_getEventData()=array(

'data_object'=>$this,

‘product’=>$this,

);

Here is what we get:Mage::dispatchEvent(‘catalog_product_save_after’, array(…, ‘product’ => $this));

Events that will be called are described in config.xml via layout. In our case:

1

2

3

4

5

6

7

8

9

10

11

12

13

<adminhtml>

<events>

<catalog_product_save_after>

<observers>

<my_individual_name>

<type>singleton</type>

<class>modulename/observer</class>

<method>methodName</method>

</my_individual_name>

</observers>

</catalog_product_save_after>

</events>

</adminhtml>

(In this case I announce the event for area adminhtml, but events may also be described both by global and, of course, frontend).

1

2

3

4

5

6

7

8

classNamespace_Modulename_Model_Observer

{

publicfunctionmethodName(Varien_Event_Observer$observer)

{

...

}

}

We can get the data of the array, transferred in dispatchEvent method, via $observer object. In our example array(…, ‘product’ => $this) is transferred. To receive the element of the product array, we should use $observer->getEvent()->getProduct().

Together with other events we are free to use the ones, formed automatically and individually for your module and for models and controllers, created in it.

controller_action_layout_render_before_**
(described in a controller, it mostly concerns blocks)

* – RouteName
** – RouteName_ControllerName_ActionName

Using Observers, described in Magento core, is a very good habit. Remember to create Observers in the main locations of your modules. It will help developers use and customize extensions in their projects easily.

The topic is believed to be of a great importance, as it is dedicated to a currently central theme “How to create a theme for Magento 2.”. At the time of writing the recent version is 2.1.7. If we compare the first version with the second one, the latter is considered as the most up-to-date and upgraded. As for theme development, modular code structure has been implemented. Now all static files such as js, CSS, and images located in web folder while skin folder has been removed from Magento home directory. (more…)

In default Magento 2 (here and after it is considered on the basis of Luma theme) HTML5 standard is applied. <!DOCTYPE html> tag is indicative of standard version (“html” value defines that HTML5 is used, but HTML4 is backward compatible). In Magento 2 the following features that have been appeared in HTML5 are used.(more…)

3 comments

A very good post and in general a helpful blog. But I think there is a small mistake:
… To override the Mage_Adminhtml_Sales_Order_Create class, we will add the following lines in configuration (models section):

shouldn’t is rather be:
… to overwrite the Mage_Adminhtml_Model_Sales_Order_Create class…