Using dependency injection to pass classes to your own class

In Magento 2, they introduced the usage of dependency injection, which is a well-known design pattern that changes the way you use resources in the code. Using dependency injection, all the required resources are created when the class is instantiated instead of creating an object (through the Magento 1.x Mage class) when necessary. The benefit of this is that it is easier to use unit testing as it is possible to mock the required objects.

Getting ready

In this example, we will see how to create a new record in the demolist model created in the previous chapter. The record is created using an observer on the sales_order_place_after event that is dispatched after a new order is saved.

How to do it…

Follow these steps on how to use dependency injection:

  1. First, we declare the Observer to listen to the event that we want:

    etc/events.xml:

    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
      <event name="sales_order_place_after">
        <observer name="sample" instance="GenmatoSampleObserverPlaceOrder"/>
      </event>
    </config>
  2. Next, we create the Observer class as defined in step 1:

    Observer/PlaceOrder.php:

    <?php
    namespace GenmatoSampleObserver;
    
    use MagentoFrameworkEventObserverInterface;
    use MagentoFrameworkEventObserver as EventObserver;
    use GenmatoSampleModelDemoFactory;
    
    class PlaceOrder implements ObserverInterface
    {
      /**
      * @var DemoFactory
      */
      protected $demoFactory;
    
      /**
      * @param DemoFactory $demoFactory
      */
      public function __construct(DemoFactory $demoFactory)
      {
        $this->demoFactory = $demoFactory;
      }
    
      /**
      * Add record to demoList when new order is placed
      *
      * @param EventObserver $observer
      * @return void
      */
      public function execute(EventObserver $observer)
      {
        /** @var MagentoSalesModelOrder $order */
        $order = $observer->getEvent()->getOrder();
    
        $demoList = $this->demoFactory->create();
    
        $demoList->setTitle(__('New order (%1) placed!', $order->getIncrementId()));
    
        try {
          $demoList->save();
        } catch (Exception $ex) {
          // Process error here....
        }
    
      }
    }
  3. Refresh the cache:
    bin/magento cache:clean
    

How it works…

In the Observer class defined in step 2, the object that we need to create a new record in is injected into the constructor function:

public function __construct(DemoFactory $demoFactory)

During the instantiation of the class, the necessary classes are injected by the Magento 2 dependency injection (DI) framework. In this case, it adds the GenmatoSampleModelDemoFactory class to the constructor. This class is not a real existing class; this is because the class that we want to use is a non-injectable class. A non-injectable class is a class that you create yourself through the new [classname] command or the Mage::getModel() call in Magento 1.x. With the use of dependency injection, creating a new object should be handled by the object manager, but in order to be able to use unit testing, it is not advisable to create the object directly in the code. To solve this, the Magento framework uses autogenerated classes. In this example, the generated class is stored in var/generation/Genmato/Sample/Model/DemoFactory.php:

<?php
namespace GenmatoSampleModel;

/**
 * Factory class for @see GenmatoSampleModelDemo
 */
class DemoFactory
{
  /**
  * Object Manager instance
  *
  * @var MagentoFrameworkObjectManagerInterface
  */
  protected $_objectManager = null;

  /**
  * Instance name to create
  *
  * @var string
  */
  protected $_instanceName = null;

  /**
  * Factory constructor
  *
  * @param MagentoFrameworkObjectManagerInterface $objectManager
  * @param string $instanceName
  */
  public function __construct(MagentoFrameworkObjectManagerInterface $objectManager, $instanceName = '\Genmato\Sample\Model\Demo')
  {
    $this->_objectManager = $objectManager;
    $this->_instanceName = $instanceName;
  }

  /**
  * Create class instance with specified parameters
  *
  * @param array $data
  * @return GenmatoSampleModelDemo
  */
  public function create(array $data = array())
  {
    return $this->_objectManager->create($this->_instanceName, $data);
  }
}

In this case, the autogenerated class is a Factory class that has only the create() function available. In the create function, the object manager is used to instantiate the GenmatoSampleModelDemo class; this object can then be used to load an existing record or create a new record and save the data stored in the object.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.9.124