Dispatch Event Messages

Within the Event Listener chapter an event listener was developed out that automatically adds a row to the disaster_volunteers database table upon every user being created. Instead listening for messages, let's now dispatch a message making the project more extensible and allowing other developers to more easily integrate with the package by creating their own event listeners every time a new project is created.

Open the /src/Disaster/Controllers/ProjectController.php file and at the top within the use declarations add the line:

use Apex/Svc/{Dispatcher, MessageRequest};

Within the properties section of the class where other injection attributes are, add the following injection attribute:

[data-line=27]
#[Inject(Dispatcher::class)]
private Dispatcher $dispatcher;

At the bottom of the create() method just before the return statement add the lines:

[data-line=47]
// Dispatch message
$msg = new MessageRequest('disaster.projects.create', $proj->id);
$this->dispatcher->dispatch($msg);

The entirety of the ProjectController.php file should now be:

<?php
declare(strict_types=1);

namespace App\Disaster\Controllers;

use Apex\Svc\{App, Db, Dispatcher};
use App\Disaster\Models\Project;
use Apex\App\Base\Lists\CountryList;
use App\Webapp\Notifications\Notifications;
Use Apex\Svc\MessageRequest;

/**
 * Project controller
 */
class ProjectController
{

    #[Inject(App::class)]
    private App $app;

    #[Inject(Db::class)]
    private Db $db;

    #[Inject(Notifications::class)]
    private Notifications $notifications;

    #[Inject(Dispatcher::class)]
    private Dispatcher $dispatcher;

    /**
        * Create project
     */
    public function create():?Project
    {

        // Create project
        $proj = Project::insert([
            'location_id' => $this->app->post('location_id'),
            'status' => $this->app->post('status'),
            'title' => $this->app->post('title'),
            'description' => $this->app->post('description')
        ]);

        // Send notifications
        $this->notifications->process(DisasterNotificationController::class, $this->app->getUuid(), ['status' => $this->app->post('status')]);

        // Dispatch message
        $msg = new MessageRequest('disaster.projects.create', $proj->id);
        $this->dispatcher->dispatch($msg);


        // Return
        return $proj;
    }

    /**
     * Create location options
     */
    public function createLocationOptions(string $selected = ''):string
    {

        // Go through locations
        $options = '';
        $rows = $this->db->query("SELECT id,country,city FROM disaster_locations WHERE is_active = %b ORDER BY id", true);
        foreach ($rows as $row) {
            $chk = $selected == $row['id'] ? 'selected="selected"' : '';
            $name = $row['city'] . ', ' . CountryList::$opt[$row['country']]['name'];
            $options .= "<option value=\"$row[id]\" $chk>$name</option>";
        }

        // Return
        return $options;
    }

}

Conclusion

With the above modifications, every time a new project is created a message will be dispatched via the Apex Cluster package, and any event listeners listening on the disaster.projects.create routing key will be executed. This provides more extensibility to the package allowing other developers to execute PHP code as desired when a project is created.

For full details, please consult the Events and Queues section of the developer documentation.