Determine the publish message architecture

Before we start publishing messages to the queue, we’ll first need to determine the precise moment we’ll want to carry out this task.

Remember that we want to know or hook into when someone leaves a review for a product. Let’s visit the product page, scroll down to the Reviews section, input a rating, nickname, summary, and review text. To see what happens when they submit this form, let’s inspect the page and find out exactly where this form is posting to.

Looking through the response, we’ll notice that the form submits to review/product/post.

Let’s go ahead and exam that review module at vendor/magento/module-review, and then go to the related controller at Controller/Product/Post.php. This file contains the execute() function that responds to this submission post.

Determining the trigger

Our next step is to find out the best way to publish a message to the queue from the code that we have access to.

Can we use a plugin?

Initially, you’ll probably think to use a plugin, as the execute() function is public. However, this function returns a redirect response, not the review data that we’ll need.

In order to link our sentiment analysis response back to the review, we need access to the Review ID, and we don’t have access to this piece of data if we were to use a plugin.

Will creating a new Class Preference work?

Creating a class preference to override the default behavior is another option. But, this approach requires writing a new class to replace the existing one, and would also add a lot of bloat to our code. Class preferences are hard to maintain, as it would be difficult to tell the difference between the core code and our custom code. Also, if the base class also ever got updated, it would require our custom class to also be updated.

What about dispatching a new event?

We could also dispatch a new event within a class preference, which would not add much code to this class, but the inherent complexity of creating a class preference here outweighs the needs for our current objective.

Implement using a built-in event

So what's the solution? Magento has a few built-in events that trigger when an entity is saved to the database, and one of these is save_commit_after. This event fires after any entity in Magento is saved, after the database transaction is committed. By observing the event related to reviews, we can tap into this built-in event to get access to the review ID we need.

Following Magento’s event-driven architecture also prevents the need to alter core files or interface with the database directly.

First, we create an events.xml file to register our event:

etc/events.xml

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="<http://www.w3.org/2001/XMLSchema-instance>" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="review_save_commit_after">
        <observer name="macademy_sentimate_add_review_to_queue" instance="Macademy\\Sentimate\\Observer\\AddReviewToQueue"/>
    </event>
</config>

We'll listen for an event named review_save_commit_after. Let’s name our observer macademy_sentimate_add_review_to_queue, and assign it to a new class that will be named Macademy\\Sentimate\\Observer\\AddReviewToQueue. It’s always best practice to name an event observer after the specific action that is carried out, as it really helps to keep our class sizes small by staying focused on one specific action.

Next, we’ll create the AddReviewToQueue class which will implement the ObserverInterface. In the execute() method, we will add in the $observer argument to access the saved review object. Then, we can create a $review variable and assign it to the event in that data object.

Since we're only interested in new reviews right now, we can also use the isObjectNew() method to only handle new reviews.

Observer/AddReviewToQueue.php

<?php

declare(strict_types=1);

namespace Macademy\\Sentimate\\Observer;

use Exception;
use Magento\\Framework\\Event\\Observer;
use Magento\\Framework\\Event\\ObserverInterface;
use Magento\\Framework\\MessageQueue\\PublisherInterface;
use Magento\\Framework\\Serialize\\SerializerInterface;
use Psr\\Log\\LoggerInterface;

class AddReviewToQueue implements ObserverInterface
{
    public function execute(Observer $observer): void
    {
        $review = $observer->getEvent()->getData('object');

        if ($review->isObjectNew()) {
            // Add logic to push message to the queue
        }
    }
}

Since we changed some XML, we’ll also need to remember to flush the Magento cache with bin/magento cache:flush. Now the architecture is in place to push messages to the queue whenever a review is saved.

Complete and Continue  
Extra lesson content locked
Enroll to access all lessons, source code & comments.
Enroll now to Unlock