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

JeffreyWay's avatar

A handler class is not the same as an event listener. So I would not equate PublishJobHandler to Listeners\PublishNotifier. Definitely not. Different purposes.

1 like
keevitaja's avatar

with laravel 5.0 request form validation, would it be wise to give the request object to the command?

thepsion5's avatar

No, because the command object is only a DTO - it should only contain the information it actually needs. Plus, that means it becomes impossible to use the command with anything other than HTTP requests.

Instead, you could do something like this:

class EditFooCommand
{
    public function __construct($fooId, $title, $description, array $categories)
    {
        $this->fooId = $fooId;
        $this->title = $title;
        $this->description = $description;
        $this->categories = $categories;
    }

    public static function fromRequest($fooId, EditFooFormRequest $request)
    {
        return new static(
            $fooId,
            $request->get('title'),
            $request->get('description'),
            $request->get('categories')
        );
    }
}

But honestly, that still makes your command object aware of what your html form fields are named. You're probably better off leaving that in the controller.

coderabbi's avatar

I've been experimenting with an almost identical approach, @thepsion5.

It's a tradeoff. Either the CommandObject is aware of the internals of the RequestObject, or you lose the advantage of validation in the RequestObject as you'd be hydrating the CommandObject with scalars and it couldn't simply rely on typehinting against the RequestObject to protect its validity.

As I write this, it's becoming clearer to me that the right answer may be that the RequestObject should provide accessors for its internals, allowing you to leverage typehinting against it while still maintaining encapsulation.

1 like
coderabbi's avatar

Of course, the more that I think about it, this isn't right, either. It would be, if only PHP had return type declarations. Without them, even if the CommandObject typehints against the RequestObject, it cannot rely on the RequestObject for its validity.

This limits the value of the RequestObject somewhat.

RFC, anyone? :-)

1 like
bbloom's avatar

I just spent way more time than I'd want to confess re(-re-re-)factoring my little (not really so little anymore) blog app to use the command bus structure.

I had the classic controller bloat problem -- now my controllers are very straight forward. Having gone through this exercise, a first, was a real eye opener.

I do think I've listened to maybe one too many Laracast videos and Laravel podcasts, because Jeffrey's voice is haunting me now. I actually said to myself, but almost with Jeffrey's voice, "you can extract that to a separate class". Happened on two specific occassions, both times I did extract and both times my app is much better for the exercise.

My issue with Jeffrey's Commander package is my wanting to deal with the "cycle" in a different way. Commander is too convenient in a way, dealing nicely with the decorators and events. Although we focus a lot on the events, I had more action with my decorators than with my events. I wanted an explicit way of invoking my decorators, rather than putting 'em into a Commander parameter to be cranked out within the Commander package. A big reason is pedagogical -- I need to understand the request cycle better. Using Commander's conveniences hides the cycle. Probably not consistent with command bus orthodoxy, but I invoke my decorators within my command handler class. Yes, it does bloat my handler class, but my blog app is just for me (for the time being) and it's been fabulous for my learning to hand craft every facet of the request-response cycle. Once I had things organized in my handler, I started extracting things out. There's an explicit access control decorator, sanitizer, validator. Then persistence. Then events. Then back to the controller for flash message and redirect. So my handlers are very busy.

Once I studied Jeffrey's Commander package, and went through the related Laracast videos over-and-over, I decided to ease up on following the architecture strictly. I got the gestalt, I am working on my own app so I can take liberties, and I needed to learn by refactoring my bloated controllers into a "command bus" structure. Mission accomplished.

I recently moved from Joomla ecommerce programming to Laravel. Little did I imagine that I'd be authoring my own blog app! Now that I have a handle (couldn't resist) on the command bus structure, my blog app is starting to look like something. And, a lot of other things about Laravel are starting to make sense.

Thank you, @JeffreyWay, for your Command Bus Laracast videos and packages. And thank you everyone for your comments, a very big help.

I would literally write a blog post about this, but I have to get my blog app's version 1.0 done first before I can blog! Getting close...

faisal.arbain@gmail.com's avatar

I think there is a different intent between formRequest and Command.

FormRequest

Responsible for validating form view. FormRequest will need to change with the form view (blade template) changes.

Controller

receive request from view and compose the formRequest to command and send into CommandBus

Command and CommandHandler

Domain layer. command and command handle should not need to change when html form is changed or CLI flow is changed.

Http form and Artisan command will have different way of validating inputs, but they both may use the same command/command handler.

example:

in my html form view, todo list is view as a dropdown list, so it is very readable and user can just pick from the list and html will send todo list ID without user need to know the ID.

however, in CLI version, user did not know the ID, so CLI will request user to enter the name instead and id.

<?php 

class AddTaskCommand{

 public $listId;
 public $task;

 public function __construct($listId, $task){

  $this->listId = $listId;
  $this->task = $task;

 }

}

class TasksController{

 public function store(AddTaskRequest $request){

   $this->execute(new AddTaskCommand($request->listId, $request->task));

   // redirect to somewhere   

 }

}

class AddTaskArtisanCommand{

 public function fire(){

  $listId = $this->askForTodoList();
  $task = $this->askForTask();

  $this->execute(new AddTaskCommand($listId, $task));

   //do something...
 }

 protected function askForTodoList(){

  $listName = $this->ask("Which todo list you want to add task?");
  $todoList = $this->todoListRepository->findByName($listName);

  if(!$todoList){

   $this->error("Todo list $listName not found!");
   return $this->askForTodoList();

  }

  return $todoList->id;

 }

 protected function askForTask(){

  $task = $this->ask("What you like to do?");

  //validate task

  return $task;

 }

}

?>

image

1 like
BenSmith's avatar

I’ve just put together a quick implementation of how you could go about transforming a request to a command object. I’ve created a BaseRequest object that extends the FormRequest class and adds a toCommand function. All requests then extend this base request.

In the controller:

public function store(RegisterUserRequest $request, Authenticator $auth)
 {
        $user = $this->execute($request->toCommand());
        …
 }

The base request class

<?php namespace Larabook\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class BaseRequest extends FormRequest {

    public function toCommand($options = [])
    {
        $class = $this->command;

        if (!class_exists($class)) {
            $message = "Command object [$class] does not exist.";
            throw new Exception($message);
        }

        $fields = array_merge($this->all(), $options);

        return $this->container->make($class, $fields);
    }

}

The request class:

<?php namespace Larabook\Http\Requests;

class RegisterUserRequest extends BaseRequest {

    public $command = 'Larabook\Registration\RegisterUserCommand';

    ...

}

I don't like how we would now have to store the fully qualified command name on the controller but I can't see a way of resolving the command from the request without it being there.

It does allow for the easy addition of extra information to the command class that is not passed to us through the form. For example, imagine we have a form to post a status and we needed the status message and the logged in users id for the command. Rather than adding a hidden field in the form to contain the logged in users id we could add this to the command from our controller as follows:

public function store(PublishStatusRequest $request)
 {
  $status = $this->execute($request->toCommand['user_id' => Auth::user()->id);
        Flash::message('Your status has been updated');
        return redirect()->back();
 }

This would then populate our command with logged in users id. Let me know what you think. I'm sure there must be a more elegant way of doing this.

nschiffelbein's avatar

@BenSmith I like your approach. Two things that I ran into while implementing this on a new project:

The toCommand function only needs to generate the Command class name and validate it prior to sending it into the execute method. Jeffrey's CommanderTrait will use the ReflectionClass to instantiate the provided command. By using the CommanderTrait in this way you can also ditch the static string for the Command name in your request class.

public function toCommand()
    {
        $class = str_replace('Request', 'Command', get_class($this));

        if (!class_exists($class)) {
            $message = "Command object [$class] does not exist.";
            throw new \Exception($message);
        }

        return $class;
    }

The second thing is you no longer need to pass additional parameters through the toCommand function since the execute method in the CommandTrait will accept override input data as a second parameter.

public function store(PublishStatusRequest $request)
 {
  $status = $this->execute($request->toCommand(), array_merge(Input::all(), ['user_id' => Auth::user()->id]));
        Flash::message('Your status has been updated');
        return redirect()->back();
 }

These changes make the code testable as well since passing an instantiated Command object to the execute method will cause it to be re-instantiated requiring you to pass your additional inputs to both the toCommand function and as a second parameter in the execute methods. Let me know if anything seems out of place or incorrect. I just completed a few functions with this approach and it seems to be working well, but if anyone sees an iceberg I haven't please let me know.

2 likes
BenSmith's avatar

@nschiffelbein, thanks for the reply. I had completely forgotten that the commander package instantiated the command object for you.

The reason that I hardcoded the command path as a field within the request object was because I envisioned them being kept in different directories. I think it makes sense to store the request objects within the default App\Http\Requests namespace as in my mind they are not part of the core domain.

As far as I can remember, the commander package translates a command name to a handler by doing a string replace of command to handler. This will not work if the objects are stored in different namespaces.

For example if I have a request: App\Http\Requests\RegisterUserRequest and I try and translate it to a command it will return App\Http\Requests\RegisterUserCommand.

I'm not sure if there is a way to resolve this without hardcoding the command path into the request object. It's inelegant but it works. Let me know if you think of a way around it.

jhauraw's avatar

@BenSmith you can implement your own CommandTranslator class to use different directories and/or file naming conventions. Instructions on this were in the Commander readme.md but where removed in the current master branch. Here is a link to the old Readme on that topic:

https://github.com/laracasts/Commander/blob/1f65b8c038cb33410e4662a7442fcc7878508160/readme.md#overriding-paths

For example, in our web app, I have the dirs like this:

/src/Users/
-- Commands/CreateUserCommand.php
-- Handlers/CreateUserHandler.php
-- Events/, Listeners/, etc...

/src/Tenants/
-- Commands/CreateTenantCommand.php
-- Handlers/CreateTenantHandler.php
-- Events/, Listeners/, etc...

It's a big app and so there are many commands for the main models and having each model contained in its own dir works well for us.

1 like
Previous

Please or to participate in this conversation.