Table of Contents for
Magento 2 Development Quick Start Guide

Version ebook / Retour

Cover image for bash Cookbook, 2nd Edition Magento 2 Development Quick Start Guide by Branko Ajzele Published by Packt Publishing, 2018
  1. Magento 2 Development Quick Start Guide
  2. Title Page
  3. Copyright and Credits
  4. Magento 2 Development Quick Start Guide
  5. Packt Upsell
  6. Why subscribe?
  7. Packt.com
  8. Contributors
  9. About the author
  10. About the reviewer
  11. Packt is searching for authors like you
  12. Table of Contents
  13. Preface
  14. Who this book is for
  15. What this book covers
  16. To get the most out of this book
  17. Download the example code files
  18. Code in Action
  19. Conventions used
  20. Get in touch
  21. Reviews
  22. Understanding the Magento Architecture
  23. Technical requirements
  24. Installing Magento
  25. Modes
  26. Areas
  27. Request flow processing
  28. Modules
  29. Creating the minimal module
  30. Cache
  31. Dependency injection
  32. Argument injection
  33. Virtual types
  34. Proxies
  35. Factories
  36. Plugins
  37. The before plugin
  38. The around plugin
  39. The after plugin
  40. Events and observers
  41. Console commands
  42. Cron jobs
  43. Summary
  44. Working with Entities
  45. Technical requirements
  46. Understanding types of models
  47. Creating a simple model
  48. Methods worth memorizing
  49. Working with setup scripts
  50. The InstallSchema script
  51. The UpgradeSchema script
  52. The Recurring script
  53. The InstallData script
  54. The UpgradeData script
  55. The RecurringData script
  56. Extending entities
  57. Creating extension attributes
  58. Summary
  59. Understanding Web APIs
  60. Technical requirements
  61. Types of users
  62. Types of authentication
  63. Types of APIs
  64. Using existing web APIs
  65. Creating custom web APIs
  66. Understanding search criteria
  67. Summary
  68. Building and Distributing Extensions
  69. Technical requirements
  70. Building a shipping extension
  71. Distributing via GitHub
  72. Distributing via Packagist
  73. Summary
  74. Developing for Admin
  75. Technical requirements
  76. Using the listing component
  77. Using the form component
  78. Summary
  79. Developing for Storefront
  80. Technical requirements
  81. Setting up the playground
  82. Calling and initializing JS components
  83. Meet RequireJS
  84. Replacing jQuery widget components
  85. Extending jQuery widget components
  86. Creating jQuery widgets components
  87. Creating UI/KnockoutJS components
  88. Extending UI/KnockoutJS components
  89. Summary
  90. Customizing Catalog Behavior
  91. Technical requirements
  92. Creating the size guide
  93. Creating the same day delivery
  94. Flagging new products
  95. Summary
  96. Customizing Checkout Experiences
  97. Technical requirements
  98. Passing data to the checkout
  99. Adding order notes to the checkout
  100. Summary
  101. Customizing Customer Interactions
  102. Technical requirements
  103. Understanding the section mechanism
  104. Adding contact preferences to customer accounts
  105. Adding contact preferences to the checkout
  106. Summary
  107. Other Books You May Enjoy
  108. Leave a review - let other readers know what you think

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.