Best Practices for Laravel 5 Command Bus

I'm trying to refactor controllers and have a look at the Laravel command bus.

After reading a bunch of articles and watching a few videos, this seems like a great way to refactor my controllers.

However, it also seems that I shouldn't be returning anything from the command.

When using commands, you follow the Command Query Splitting (CQS) principle: a function is either a request (i.e. it returns something) or a command (i.e. affects state). Both are mutually exclusive. So the command shouldn't return anything, and the query shouldn't change anything. source

I created a command CreateCustomerCommand

:

namespace App\Commands;

use QuickBooks_IPP_Service_Customer;

use App\Commands\Command;
use Illuminate\Contracts\Bus\SelfHandling;

class CreateCustomer extends Command implements SelfHandling
{
    private $qb;
    private $customer_service;
    private $customer;
    private $is_same_address;
    private $name;
    private $primary_phone;
    ...

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->qb = Quickbooks::Instance();
        $this->qb->ipp->version(QuickBooks_IPP_IDS::VERSION_3);

        $this->customer_service = new QuickBooks_IPP_Service_Customer();

        $this->is_same_address = $request->input('customer.isSameAddress');
        $this->name = ucwords(strtolower($request->input('customer.name')));
        $this->primary_phone = $request->input('customer.primaryPhone');
    }
    ...

    /**
     * Execute the command.
     *
     * @return void
     */
    public function handle()
    {
        $this->customer->setDisplayName($this->name);

        ...

        $this->customer_service->add(...);



    }
}

      

Three questions regarding best practices:

  • After the call $this->customer_service->add()

    , the client returns id

    . How can I send this one id

    back to the controller?

  • Where is the best place to enable activity log?

Activity:

$activity = new Activity();
$activity->event = 'Created Customer: ' . $this->name;
$activity->user = Auth::user()->name;
$activity->save();

      

Wouldn't it be best to include this at the end CreateCustomerCommand

?

  1. How about an event?

Event:

event(new CustomerWasCreatedOrUpdated);

      

I am new to application architecture and am looking for a way to simplify and maintain my controllers. I wish someone could point me in the right direction.

+3


source to share


1 answer


First, you should strive to keep your controllers "simple and easy to use." You may not always be able to achieve this goal, but achieving it will more often than not pay off.

How do I send the id back to the controller?

The team is a specialized case of general service. Your team can declare additional public methods that interrogate the result of a state change. If the command was used by a CLI application, that application might do something like echo $this->command->getAddedCustomerId()

. A network controller could use it in a similar way.

However, the advice you gave is to either change state without output or query with output is sage. If you are changing a state and need to know the result of changing that state, you are probably overusing the command.

As an analogy, consider the Linux command "useradd", which you would invoke as useradd -m 'Clara Barton' cbarton

. This command runs and gives you a simple indication of success or failure. But notice that you gave it the primary key "cbarton". You can request this key yourself, for example grep cbarton /etc/passwd

, but it's important useradd

not to create an identifier for you.

Thus, the team that changes state should most likely tell you success or failure. If you want to test the result of this state change, you must give the command the keys it needs to look for the state change.

So what you probably want is a generic service. The team can use this service, the controller can use this service, the model can use this service. But a service is just a generic class that does one job and provides the required API.

Where can I turn on the activity log?



Assuming you are not using PHP-AOP, careful and rigorous activity logging practices should be established ahead of time and followed throughout the development lifecycle.

To a large extent, the location of the activity log depends on the underlying architectural model of your system. If you rely heavily on events, then a good place might be to extend the facade Event

or log events. If you rely heavily on DI, you can pass the Logger to the code you require to register.

In the specific case of the command, you will go anyway, again depending on your underlying architectural model. If you are avoiding events, then you must enter the logger via LARARE the normal DI hint type. If you have enabled events, then you can do something likeEvent::fire('log', new LogState('Blah Blah', compact ($foo, $bar)));

Most importantly, though, you rely on a pluggable and customizable logging service that you can modify and customize for testing, quality assurance, and production needs.

How about events?

Okay, things are great. This is not the case yet. In my experience, events can get really complicated as they, IMO, abuse data transfer and affect state.

Events are like teleporters: you walk down a path, then there is a fire, and suddenly you teleport all over the codebase and pop up in a completely different place, then you do something and get right where you were. You must think in a specific way and be efficient in executing code when Events are playing.

If Laravel events are your first exposure to events, I would discourage you from making significant use of them. Instead, I suggest that you limit them to one specific package or part of your application until you get a feel for the power they offer and the architectural rigor they require.

+5


source







All Articles