Magento 2 module development – a comprehensive guide – Part 3 (Observers)

Part 3 of our detailed guide about how to develop your own Magento 2 module: How to build a basic sample module and create & implement Observers.



In this article I will describe the following two topics:

  • Building up a basic sample module
  • Creating and implementing Observers

 

1) Building up a basic sample module

 

In my previous article (Part 1, Part 2) you could see how to make a sample Magento 2.0 module and how to create, edit, save and delete the database tables, admin grid and data belonging to it.

Now we are going to deal with the operation of observers within another simple Magento 2.0 module.

In the first step let’s create a basic sample module. Since I already described this topic in my earlier post, now I am presenting only the module structure.

 

magento 2 module structure

 

2) Creating and implementing observers

 

We create two Observers in the Magento 2.0 sample module that we “connect” with two separate events. In the case of Magento 1.x modules the functions (and business logics running in them), to be created with different events, were created in one Observer class.

In Magento 2.0, for every event we need to create a separate Observer class in which the business logic is created in the execute(…) function.

Before the Observer class is created, we need to define to which event your own business logic should apply. Here it’s important to decide which page you want to use it on, either on frontend or admin (adminhtml), so you need to place the definition xml file in the appropriate location.

You can place it “globally”, but I recommend placing it separately. In the first example, in case of a frontend page event, after sending the default Magento 2.0 contact form,      we want to “catch” the sent data with our own Observer class.

For this we need an events.xml file which can be found in the following location in our sample module: app/code/Aion/Sample/etc/frontend/events.xml. The file contains the following:

<?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="controller_action_postdispatch_contact_index_post">
        <observer name="aion_sample_post_capture" instance="Aion\Sample\Observer\CapturePost" />
    </event>
</config>

The file’s structure is very simple. The events we’d like to “catch” are defined in the name parameter within the event tag. In our case it is the event following the post controller in the -default Contact module of Magento 2.0. Then we define our own Observer class, to be called in the future, in the Observer tag located within the event tag. We also give it a name parameter.

We can define more “custom” Observers in a list- with this same event, and we can define more event tags in the xml file if we want to use additional “custom” Observers.

Next, we need to create our own Observer class and define the necessary business logic in it. In our sample module, the file is located here: app/code/Aion/Sample/Observer/CapturePost.php. The file contains the following:

<?php
namespace Aion\Sample\Observer;

use Magento\Framework\Event\ObserverInterface;
use Aion\Sample\Helper\Data as DataHelper;
use Psr\Log\LoggerInterface;
use Magento\Framework\Event\Observer;
use Magento\Customer\Model\Customer;
use Magento\Framework\Exception\LocalizedException;

class CapturePost implements ObserverInterface
{
    /**
     * Aion Sample helper
     *
     * @var DataHelper
     */
    protected $_helper;

    /**
     * @var LoggerInterface
     */
    protected $_logger;

    /**
     * Capture Post Observer constructor
     *
     * @param DataHelper $helper
     * @param LoggerInterface $logger
     */
    public function __construct(
        DataHelper $helper,
        LoggerInterface $logger
    ) {
        $this->_helper = $helper;
        $this->_logger = $logger;
    }

    /**
     * Sample post capture event handler
     *
     * @param Observer $observer
     * @return self
     */
    public function execute(Observer $observer)
    {
        if ($this->_helper->isEnabled()) {

            $controller = $observer->getEvent()->getControllerAction();
            $post = $controller->getRequest()->getPostValue();

            if ($post) {

                try {

                    $this->_logger->debug('CapturePostObserver');
                    $this->_logger->log(100, print_r($post, true));

                    // comment out to check data
                    //\Zend_Debug::dump($post);
                    //die();

                    // do some logic

                } catch (LocalizedException $e) {
                    $this->_logger->error($e->getMessage());
                } catch (\Exception $e) {
                    $this->_logger->critical($e);
                }

            }

        }

        return $this;
    }
}

If the event, defined in the events.xml file mentioned above, takes place, the execute function in the CapturePost class is executed. The function first checks if our own module is enabled or not. If it is enabled, it “catches” the data posted by the default Contact form of Magento 2.0.

For simplicity’s sake, we only log the array in the debug.log file. With the data provided this way, we can create our own business logic.

In the second example, with an admin-related event, after the default Magento 2.0 customer save, we want to “catch” the customer object and data with our own Observer class.

For this, we’ll need an events.xml file which can be found in our sample module under app/code/Aion/Sample/etc/adminhtml/events.xml. The file includes the following:

<?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="controller_action_postdispatch_contact_index_post">
        <observer name="aion_sample_post_capture" instance="Aion\Sample\Observer\CaptureCustomer" />
    </event>
</config>

 

 

The file structure is the same as with the events.xml described in the precious example, but this time the adminhtml directory is placed here, thus the defined CaptureCustomer class will be called only in the admin scope for the event of customer_save_commit_after.

 

Next, similarly to the previous example, we need to create our own Observer class and implement the necessary business logic in it.

 

The file is located in our sample module under app/code/Aion/Sample/Observer/CaptureCustomer.php. The file contains the following:

 

<?php
namespace Aion\Sample\Observer;

use Magento\Framework\Event\ObserverInterface;
use Aion\Sample\Helper\Data as DataHelper;
use Psr\Log\LoggerInterface;
use Magento\Framework\Event\Observer;
use Magento\Customer\Model\Customer;
use Magento\Framework\Exception\LocalizedException;

class CaptureCustomer implements ObserverInterface
{
    /**
     * Aion Sample helper
     *
     * @var DataHelper
     */
    protected $_helper;

    /**
     * @var LoggerInterface
     */
    protected $_logger;

    /**
     * Capture Customer Observer constructor
     *
     * @param DataHelper $helper
     * @param LoggerInterface $logger
     */
    public function __construct(
        DataHelper $helper,
        LoggerInterface $logger
    ) {
        $this->_helper = $helper;
        $this->_logger = $logger;
    }

    /**
     * Sample customer capture event handler
     *
     * @param Observer $observer
     * @return self
     */
    public function execute(Observer $observer)
    {
        if ($this->_helper->isEnabled()) {

            /* @var Customer $customer */
            $customer = $observer->getEvent()->getCustomer();

            if (!is_null($customer) && $customer->getEntityId()) {

                try {

                    $this->_logger->debug('CaptureCustomerObserver');
                    $this->_logger->log(100, print_r($customer->getData(), true));
                    // comment out to check data
                    //\Zend_Debug::dump($customer->getData());
                    //die();

                    // do some logic

                } catch (LocalizedException $e) {
                    $this->_logger->error($e->getMessage());
                } catch (\Exception $e) {
                    $this->_logger->critical($e);
                }

            }

        }

        return $this;
    }
}

 

If the event, defined in the second events.xml file mentioned above, takes place, the function in the CaptureCustomer class is executed. The function first checks if our own module is enabled or not. If it is enabled, it “catches” the customer object after the described save in Magento 2.0.

For simplicity’s sake, we only log the data of the object in the debug.log file. With the object and data provided this way, we can create our own business logic.

 

Summary

In this article we illustrated with the help of two examples how to define and create custom or unique modules in Magento 2.0, for different events on both the fronted and admin pages.

 

See also Part 1 (comprehensive guide), Part 2 (create admin grid) and Part 4 (Knockout JS).

 

 


Do you need our support?
  • Magento Site Check
  • Magento Code Audit
  • Magento SEO Audit
  • Magento Project Rescue
Request help

NEED A RELIABLE, PROFESSIONAL MAGENTO DEVELOPMENT PARTNER?

Contact us if you have any question or requirement related to the preparation of a new or renewal of an existing online store.

Next