Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Magento 2 Development Quick Start Guide

You're reading from   Magento 2 Development Quick Start Guide Build better stores by extending Magento

Arrow left icon
Product type Paperback
Published in Sep 2018
Publisher Packt
ISBN-13 9781789343441
Length 218 pages
Edition 1st Edition
Languages
Tools
Concepts
Arrow right icon
Author (1):
Arrow left icon
Branko Ajzele Branko Ajzele
Author Profile Icon Branko Ajzele
Branko Ajzele
Arrow right icon
View More author details
Toc

Table of Contents (11) Chapters Close

Preface 1. Understanding the Magento Architecture FREE CHAPTER 2. Working with Entities 3. Understanding Web APIs 4. Building and Distributing Extensions 5. Developing for Admin 6. Developing for Storefront 7. Customizing Catalog Behavior 8. Customizing Checkout Experiences 9. Customizing Customer Interactions 10. Other Books You May Enjoy

Events and observers

Magento has a neat publish-subscribe pattern implementation that we call events and observers. By dispatching events when certain actions are triggered, we can run our custom code in response to the triggered event. The events are dispatched using the Magento\Framework\Event\Manager class, which implements Magento\Framework\Event\ManagerInterface.

To dispatch an event, we simply call the dispatch method of the event manager instance, providing it with the name of the event we are dispatching with an optional array of data we wish to pass on to the observers, as per the following example taken from the <MAGENTO_DIR>/module-customer/Controller/Account/CreatePost.php file:

$this->_eventManager->dispatch(
'customer_register_success',
['account_controller' => $this, 'customer' => $customer]
);

Observers are registered via an events.xml file, as per the following example from the <MAGENTO_DIR>/module-persistent/etc/frontend/events.xml file:

<event name="customer_register_success">
<observer name="persistent" instance="Magento\Persistent\Observer\RemovePersistentCookieOnRegisterObserver" />
</event>

By doing a lookup for the eventManager->dispatch string across the entire <MAGENTO_DIR> directory's *.php files, we can see hundreds of events examples, spread across the majority of Magento's modules. While all of these events are of the same technical importance, we might say that some are likely to be used more on a day to day basis than others.

This makes it worth taking some time to study the following classes and the events they dispatch:

  • The Magento\Framework\App\Action\Action class, with the following events:
    • controller_action_predispatch
    • 'controller_action_predispatch_' . $request->getRouteName()
    • 'controller_action_predispatch_' . $request->getFullActionName()
    • 'controller_action_postdispatch_' . $request->getFullActionName()
    • 'controller_action_postdispatch_' . $request->getRouteName()
    • controller_action_postdispatch
  • The Magento\Framework\Model\AbstractModel class, with the following events:
    • model_load_before
    • $this->_eventPrefix . '_load_before'
    • model_load_after
    • $this->_eventPrefix . '_load_after'
    • model_save_commit_after
    • $this->_eventPrefix . '_save_commit_after'
    • model_save_before
    • $this->_eventPrefix . '_save_before'
    • model_save_after
    • clean_cache_by_tags
    • $this->_eventPrefix . '_save_after'
    • model_delete_before
    • $this->_eventPrefix . '_delete_before'
    • model_delete_after
    • clean_cache_by_tags
    • $this->_eventPrefix . '_delete_after'
    • model_delete_commit_after
    • $this->_eventPrefix . '_delete_commit_after'
    • $this->_eventPrefix . '_clear'
  • The Magento\Framework\Model\ResourceModel\Db\Collection class, with the following events:
    • core_collection_abstract_load_before
    • $this->_eventPrefix . '_load_before'
    • core_collection_abstract_load_after
    • $this->_eventPrefix . '_load_after'

Some more important events can be found in a few of the types defined under the <MAGENTO_DIR>/framework/View directory:

  • view_block_abstract_to_html_before
  • view_block_abstract_to_html_after
  • view_message_block_render_grouped_html_after
  • layout_render_before
  • 'layout_render_before_' . $this->request->getFullActionName()
  • core_layout_block_create_after
  • layout_load_before
  • layout_generate_blocks_before
  • layout_generate_blocks_after
  • core_layout_render_element

Let's take a closer look at one of these events, the one found in the <MAGENTO_DIR>/framework/Model/AbstractModel.php file:

public function afterCommitCallback() {
$this->_eventManager->dispatch('model_save_commit_after', ['object' => $this]);
$this->_eventManager->dispatch($this->_eventPrefix . '_save_commit_after', $this->_getEventData());
return $this;
}

protected function _getEventData() {
return [
'data_object' => $this,
$this->_eventObject => $this,
];
}

The $_eventPrefix and $_eventObject type properties are particularly important here. If we glimpse over types such as Magento\Catalog\Model\Product, Magento\Catalog\Model\Category, Magento\Customer\Model\Customer, Magento\Quote\Model\Quote, Magento\Sales\Model\Order, and others, we can see that a great deal of these entity types are essentially extending from Magento\Framework\Model\AbstractModel and provide their own values to replace $_eventPrefix = 'core_abstract' and $_eventObject = 'object'. What this means is that we can use events such as $this->_eventPrefix . '_save_commit_after' to specify observers via events.xml.

Let's take a look at the following example, taken from the <MAGENTO_DIR>/module-downloadable/etc/events.xml file:

<config>
<event name="sales_order_save_commit_after">
<observer name="downloadable_observer" instance="Magento\Downloadable\Observer\SetLinkStatusObserver" />
</event>
</config>

Observers are placed inside the <ModuleDir>/Observer directory. Every observer implements a single execute method on the Magento\Framework\Event\ObserverInterface class:

class SetLinkStatusObserver implements \Magento\Framework\Event\ObserverInterface {
public function execute(\Magento\Framework\Event\Observer $observer) {
$order = $observer->getEvent()->getOrder();
}
}

Much like plugins, badly implemented observers can easily cause bugs or even break the entire application. This is why we need to keep our observer small and computationally efficient—to avoid performance bottlenecks.

The cyclical event loop is a trap that's easy to fall into. This happens when an observer, at some point, is dispatching the same event that it listens to. For example, if an observer listens to the model_save_before event, and then tries to save the same entity again within the observer, this would trigger a cyclical event loop.

To make our observers as specific as possible, we need to declare them in an appropriate scope:

  • For observing frontend only events, you can declare observers in <ModuleDir>/etc/frontend/events.xml
  • For observing backend only events, you can declare observers in <ModuleDir>/etc/adminhtml/events.xml
  • For observing global events, you can declare observers in <ModuleDir>/etc/events.xml

Unlike plugins, observers are used for triggering the follow-up functionality, rather than changing the behavior of functions or data which is part of the event they are observing.

You have been reading a chapter from
Magento 2 Development Quick Start Guide
Published in: Sep 2018
Publisher: Packt
ISBN-13: 9781789343441
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime