Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

JeffreyWay's avatar

Command Bus Stuff in Laravel 4.3

One thing Laravel 4.3 introduces is a new system for validating and authorizing form requests.

https://laracasts.com/series/whats-new-in-laravel-4-3/episodes/3

Now, if you think about it, form requests can function as commands. Yes, they're more than dumb, immutable DTOs, however they still carry the data we require (and can easily be cast to StdClasses), as well as a name that perfectly describes the instruction from the user.

So, that means, if you wanted to, you could very easily implement your own makeshift command bus type setup. You don't need a package for this. For instance:

<?php namespace Laracasts\Http\Controllers;

use Illuminate\Routing\Controller;
use Laracasts\Core\ExecutableTrait;
use Laracasts\Http\Requests\ScheduleTaskRequest;

class TasksController extends Controller {

    use ExecutableTrait;

    /**
     * Schedule a new task.
     *
     * @param ScheduleTaskRequest $request
     * @return Response
     */
    public function store(ScheduleTaskRequest $request)
    {
        // At this point, validation and authorization have passed.

        // So let's handle this instruction.
        // This will trigger Laracasts\Handlers\ScheduleTaskHandler
        $this->execute($request);

        return Redirect::somewhere();
    }

}

And then your execute method (or dependency) could just determine which handler to resolve out of the container, and then call it, while passing through something like (object) $request->all().

<?php namespace Laracasts\Handlers;

class ScheduleTaskHandler implements CommandHandler {

    /**
     * @param $task
     */
    public function handle($task)
    {
        // delegate to schedule the task
    }

}

With this approach, you get away from that issue, where your naming convention for form requests and commands are incredibly similar.

Has anyone experimented with this approach yet? (Or need more info?) Any downsides? Just thinking out loud right now.

0 likes
42 replies
ax3lst's avatar

Wow, this is very cool! I didn't thought about that. Could you maybe post your ExecutableTrait? I wan't to see how you do this.

coderabbi's avatar

I was thinking as well that there are some projects that this would provide the encapsulation of intent and distinct separation between the application layer and the domain/infrastructure without the overhead of a dedicated command bus, yes. In more involved projects, I prefer Commands to be composed of Value Objects rather than Scalars, so the Command Bus infrastructure would still be required (as the Controller would be primarily responsible for constructing the Command). That said, if you're comfortable with the Controller handling Handler resolution, there's no reason that you couldn't do this even before 4.3. All Request Objects do for you is push validation one step up the stack.

JeffreyWay's avatar

Yes, the controller can handle "handler resolution," or a dependency can. It doesn't matter. Whatever you want.

Form request objects do more than that. As of 4.3, basically everyone is going to be using them. So, that means we'll have a big list of classes that describe the intent of the user... even if you're not following a command bus approach.

  • UpgradeSubscriptionRequest
  • ArchiveTaskRequest
  • PayInvoiceRequest

So, this means it could be significantly easier to adopt this style of architecture.

coderabbi's avatar

Oh, absolutely. I think it's definitely a great feature. Having a DTO (the Request object) that is responsible for its own validation (the rules live inside the object rather than externally) is a big step forward. I'm just not sure it replaces Commands composed of Value Objects in every case. I do fear that by moving validation "up the stack", the otherwise anemic Controller will be "put to work" in ways that it shouldn't, but that's more a question of education rather than any issue with the new Request objects.

Valorin's avatar

How easy is it to use these new Request Objects outside of controllers? For example, implementing an Artisan command which accepts the same input an HTML form - can the request object be easily used to validate this input too?

rrosiek's avatar

@Valorin, I was going to just ask the same exact question. If request objects truly replace commands, shouldn't they be compatible at the command line and other methods of entry?

They might be able to be cast into this role as is, I really have no idea (and thus not much of a help), but given they're in the "http" namespace by default, I'm not sure that would be their intent. Also, for most web projects, we're coming and going via http, I don't think it's time to go nuts over it. I suppose if you're building something that needs all that flexibility, you're going to use separate command DTOs and common validators anyway. I think I just talked myself in and out of that twice...

I actually created an abstract command that add validation upon instantiation, all pre-4.3 of course, so these request objects are a breath of fresh air.

airbornfoxx's avatar

@JeffreyWay, @coderabbi, @Valorin, @rrosiek - I think Jeffrey Way is trying to say that form requests can be used "as" command objects, not necessarily "in place of" command objects.

I've been working on an expansion of Jeffrey Way's Commander package. I've tried to make it framework agnostic and have included more tests. I also just updated it to include the use of Laravel 4.3 form requests as command objects.

I mostly used this as a project for practicing package development, but I hope it will also help people with their own projects. The link to the Github package is below. Let me know your thoughts.

CommandCenter

1 like
rejecthelogic's avatar

If I understand correctly you want to extend Request Object functionality to work as Command Object DTO too? If so I think this is a great idea.

JeffreyWay's avatar

Yeah - I'm saying that you basically already have command objects, when you create these. In my mind, the naming is the most important part. It signals intent.

So, if folks are curious about this style of architecture, they now have a pretty easy way to try it out...without having to pull in a package, or learn some new API.

2 likes
salebab's avatar

Note that controller methods are command (request) handlers now, and there is a method injection also, so probably you don't need a separate class to execute a command.

But if you want to, you can just simple call new ScheduleTaskHandler($task), right? Or better, to use IoC.

Maybe it's just me, but I tried to use you commander and now I have a lot of commands, handlers and decorators, and it is to hard to follow the code. For example, in PhpStorm, I can not jump (cmd+click) to the handler, I must read a command name and then to cmd+o and type the name (or copy) plus to type 'Handler' at the end. So, for now, I think it's not the best way :(

jgx's avatar

I'm unsure about using the new Request in place of a Command.

I like to do my application/infrastructure validation (checking the uniqueness of an Entity for example) after the Request reached the Controller, in a CommandHandler object. Like this I have all the business logic related to a command in one place. For the domain validation rules, I put them in the models / values objets as they're responsible for their own consistencies.

Edit : But it's a very good step forward ! :D

thepsion5's avatar

You could easily extend the FormRequest class to have a toCommand() function that would use some of the magic already in @JefferyWay's package to translate a form request into a command of the same name (CreateUserFormRequest gets turned into CreateUserCommand and map the input to it's constructor). Then, all you need is your command DTO, and $this->execute($request->toCommand()); in your controller.

Craftyx's avatar

It would work and makes our job much easier, but what about SRP ?

This object will be responsible for data validation, authorization and being a command ?

JeffreyWay's avatar

@AoSiX - It's not responsible for being a command. It just conveniently contains the data we need. You can cast it to an array or object, if you prefer.

pobble's avatar

This is great stuff but I have a question for Jeff.

Are you perhaps going to extend the Commander package a little bit to accommodate this idea?

Maybe a tiny configuration file where you could specify the replacement and replaced string in CommandTranslator?

airbornfoxx's avatar

That functionality is extended in the CommandCenter package. You would use the request object as a command passing it to the command bus. It will automatically map to a handler class without doing anything extra.

1 like
bbloom's avatar

There are decorators that execute during the request phase, especially authentication, access control, and validation(?). However, would it not be good to preserve a "decorator" function within Commander for L4.3, for things we might want to do before do persistance?

Are you saying that Commander for L4.3 will not need a "PublishJobCommand" class? That would be good! Better to get right to "PublishJobCommandHandler", without having to "manually" build the DTO object.

L4.3 does seem to blow up Commander somewhat. Which is why I think I have to dive into L4.3 sooner than later to forestall refactoring when L4.3 officially releases in November (it's Nov?).

I hope this makes sense.

bbloom's avatar

An update. Given the changes coming in L4.3 --oops, L5 (http://www.buzzsprout.com/11908/203720-laravel-io-episode-17-laravel-4-3-i-mean-laravel-5), and given that these changes will materially affect @jeffreyway Commander package, I am using only the command/commandhandler aspect of Commander.

The decorater --> not using it.

The event handling --> not using it.

Event handling in Commander I should be using because L5 does not affect it. However, I am finding my personal preference to handle events outside of Commander's purview.

I am launching my decorators within my command handlers. Similarly my events. As a consequence, my command handlers share the same pathology as the original problem in my controller: stuffing 'em with everything! Although my handler is much neater than my controller ever was!

Well, my command handlers are in transition, with refactoring on the way. My sense of the L5 change is that my decorators will be moved out of the command bus altogether, leaving the persistence and event handling in the command bus.

1 like
RobinMalfait's avatar

This looks awesome but does this mean that is highly coupled to the framework or not?

bbloom's avatar

@BenSmith wow! who needs sleep anyways! Thank you for posting this. Definitely going to study it.

airbornfoxx's avatar

The package is made agnostic to be used with any framework. It just happens to come with a Laravel implementation.

Both command objects and request objects will work with the package, regardless of framework you choose.

CommandCenter

jhauraw's avatar

@bbloom similar approach here. I broke out the events from Commander into its own package called "Eventer". To me the Eventing was a separate concern from the Commanding.

I agree with what @jeffreyway is saying - that if we can accomplish a similar goal as Commanding/Dispatching/Eventing within Laravel core, and keep it simple, that is better overall for the adaptation and growth of Laravel than using a package.

I'm all for getting rid of the PublishJobCommand DTO parts, and just have the meat of the matter, the *Handler - or now, after watching the Small Objects video (https://laracasts.com/lessons/small-objects-are-good-things) - what seem to be called Listeners\*Notifiers now.

So from Laracasts\Commander compared to L5:

  • PublishJobValidator, PublishJobCommand => PublishJobRequest (injected in Controller method)

  • JobWasPublishedEvent => No separate class, fired directly in Controller method (or elsewhere).

  • Listen for Event: start/global.php => Providers\JobPublishServiceProvider

  • PublishJobHandler => Listeners\PublishNotifier@whenJobWasPublished

Thoughts?

1 like
thepsion5's avatar

You shouldn't use events to trigger the command handler. Firing an event implies that the action the event is signalling has already completed, for example "JobWasPublished". So using an event to call your event handler (the thing that actually does the work) is backwards. What if the handler fails to complete its task? That puts you in the odd position of having to cancel an event that, based on the name, has occurred in the past.

Plus what if some other package registers its event listener before your handler? It would be trying to send out a welcome email for a user that didn't register due to an invalid email address. The order in which listeners are subscribed to an event should not impact whether the event actually happens or not.

I think you're better off using explicitly using the handler instead of registering it as an event listener.

Next

Please or to participate in this conversation.