Personally, I don’t like Jobs much. For me, it is more logical if the commands and the handlers are separate. I also don’t like injecting the dependencies in the handle()
method of self-handling jobs. I like the common command bus design where you have a command and a handler that handles that command.
Here i would like to show you a very easy way, how you can continue working with dedicated commands and command handlers as you did in some versions before with the regular command bus. Here we go:
To keep it very simple, I will just create some demo code to show you the basics.
<?php
declare(strict_types=1);
namespace App\Domain\User\Command;
final class RegisterUserCommand
{
public $username;
public function __construct(string $username)
{
$this->username = $username;
}
}
After you created your command, it is time to create the command handler that handles that command.
<?php
declare(strict_types=1);
namespace App\Domain\User\Command;
final class RegisterUserCommandHandler
{
public function handle(RegisterUserCommand $command)
{
// create user, dispatch event, or whatever necessary
return 'user created with username '.$command->username;
}
}
Now that we have the command itself and the handler that should handle the command, we have to tell the dispatcher which handler is responsible for which command. Easy! There are several ways to do that. The easiest way is that you use a ServiceProvider for it or use the already existing AppServiceProvider
.
Either you fetch the current Dispatcher out of the IoC directly or you just inject it into the boot()
method. I will show you both methods. After you resolved the Dispatcher, you use the map()
method to map the command to the command handler.
<?php
namespace App\Providers;
use App\Domain\User\Command\RegisterUserCommand;
use App\Domain\User\Command\RegisterUserCommandHandler;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
$dispatcher = $this->app->make(\Illuminate\Contracts\Bus\Dispatcher::class);
$dispatcher->map([
RegisterUserCommand::class => RegisterUserCommandHandler::class,
]);
}
// register() method...
}
<?php
namespace App\Providers;
use App\Domain\User\Command\RegisterUserCommand;
use App\Domain\User\Command\RegisterUserCommandHandler;
use Illuminate\Bus\Dispatcher;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot(Dispatcher $dispatcher)
{
$dispatcher->map([
RegisterUserCommand::class => RegisterUserCommandHandler::class,
]);
}
// register() method....
}
Let’s give it a shot and try it. We use the route file directly to test that. Like so:
Route::get('dispatch', function(\Illuminate\Bus\Dispatcher $dispatcher) {
return \Bus::dispatch(new \App\Domain\User\Command\RegisterUserCommand('my-username'));
});
If you go now to the browser you should see something like “user created with username my-username“. Yiha!