Navigating Magento 2 Architecture: Discovering Plugin Architecture for Newcomers
Tags: php, beginners, tutorial, magento2
Published: 2023-07-17 18:15:13

Hello again, and welcome back to our series on Magento 2 Architecture for newcomers! We're glad to see you return for the second part of our journey, a clear indicator of your dedication to understanding and mastering this powerful platform. In our first post, we delved into the fascinating world of Magento 2's Observer Architecture. We explored its unique functionality and got our hands dirty with practical examples to bolster our knowledge.

Today, we will be unraveling the intricacies of Magento 2's Plugin Architecture. Our aim is to ensure you not only understand the concept theoretically but also gain the practical skills necessary to apply them efficiently. So buckle up, as we gear up for another exciting ride through the world of Magento!

## The Role of Plugins in Magento 2

In Magento 2, plugins, also referred to as Interceptors, play a critical role in extending the functionality of existing public methods within a class. They provide a mechanism that allows us to alter or extend the behavior of public methods without modifying the actual class.

The charm of plugins lies in their ability to interact with a method at three different points: before, after, and around. This allows developers to modify the input or output data or even change the flow of processing.

## Registering a Plugin

To leverage the power of plugins, we need to register them first. This is done in the `di.xml` file of your module. Here's a basic example:

```xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\App\Action\Action">
        <plugin name="vendor_module_slack_notifier" type="Vendor\Module\Plugin\SlackNotifier" sortOrder="10"/>
    </type>
</config>
```

In this example, we've registered a plugin named `vendor_module_slack_notifier` for the class `Magento\Framework\App\Action\Action`. The plugin's class is `Vendor\Module\Plugin\SlackNotifier`.

## Writing a Plugin

Now, let's get down to the nitty-gritty of writing our plugin. Remember our goal here is to send a Slack message at a clever place. A good idea could be to notify a Slack channel whenever a new order is placed on the website. In this case, let's consider we are writing a plugin for the `placeOrder` method in the `Magento\Sales\Model\Service\OrderService` class.

```php
namespace Vendor\Module\Plugin;

class SlackNotifier
{
    protected $slack;

    public function __construct(
        \Vendor\Module\Model\Slack $slack
    ) {
        $this->slack = $slack;
    }

    public function afterPlaceOrder(
        \Magento\Sales\Model\Service\OrderService $subject,
        $result
    ) {
        $message = "New order placed with ID: " . $result;
        $this->slack->sendMessage($message);
        return $result;
    }
}
```

In this plugin, we are using the `after` plugin to send a Slack message after an order has been placed.

## Unit Testing a Plugin

After we've written our plugin, it's important to test it to ensure it behaves as expected. Here's how you can use PHPUnit to test your plugin.

```php
namespace Vendor\Module\Test\Unit\Plugin;

class SlackNotifierTest extends \PHPUnit\Framework\TestCase
{
    protected $slackNotifier;

    protected function setUp(): void
    {
        $this->slackNotifier = $this->getMockBuilder(\Vendor\Module\Plugin\SlackNotifier::class)
                                    ->disableOriginalConstructor()
                                    ->getMock();
    }

    public function testAfterPlaceOrder()
    {
        $orderServiceMock = $this->createMock(\Magento\Sales\Model\Service\OrderService::class);
        $result = "100001";
        $this->slackNotifier->expects($this->once())
                            ->method('afterPlaceOrder')
                            ->with($orderServiceMock, $result);

        $this->slackNotifier->afterPlaceOrder($orderServiceMock, $result);
    }
}
```

## Observers vs Plugins

While observers and plugins might seem similar, they serve different purposes and their usage depends on your requirements. Plugins are great for modifying the behavior of existing public methods. However, if you're interested in reacting to specific events in the application, observers would be a more suitable choice.

The observer pattern can be seen as a more global approach, as it enables a certain type of code (observers) to react to system-wide events without coupling the observers to the code that emits those events. Plugins, on the other hand, are more targeted, allowing us to interact with a method at specific points in its execution.

With the knowledge you've gained from this post and the previous one, you are now well-equipped to start implementing these concepts into your projects. Next in this series, we will dive deeper into the world of Magento 2 architecture. Stay tuned and happy coding!