Giter Club home page Giter Club logo

commander's Introduction

Laravel Commander

This package gives you an easy way to leverage commands and domain events in your Laravel projects.

Laravel 5 users: this package is no longer required, as the framework includes its own flexible command bus out of the box.

Installation

Per usual, install Commander through Composer.

"require": {
    "laracasts/commander": "~1.0"
}

Next, update app/config/app.php to include a reference to this package's service provider in the providers array.

'providers' => [
    'Laracasts\Commander\CommanderServiceProvider'
]

Usage

Easily, the most important piece of advice I can offer is to keep in mind that this approach isn't for everything. If you're building a simple CRUD app that does not have much business logic, then you likely don't need this. Still want to move ahead? Okay - onward!

The Goal

Imagine that you're building an app for advertising job listings. Now, when an employer posts a new job listing, a number of things need to happen, right? Well, don't put all that stuff into your controller! Instead, let's leverage commands, handlers, and domain events to clean up our code.

The Controller

To begin, we can inject this package's CommanderTrait into your controller (or a BaseController, if you wish). This will give you a couple helper methods to manage the process of passing commands to the command bus.

<?php

use Laracasts\Commander\CommanderTrait;

class JobsController extends \BaseController {

	use CommanderTrait;

	/**
	 * Publish the new job listing.
	 *
	 * @return Response
	 */
	public function store()
	{

	}

}

Good? Next, we'll represent this "instruction" (to post a job listing) as a command. This will be nothing more than a simple DTO.

<?php

use Laracasts\Commander\CommanderTrait;
use Acme\Jobs\PostJobListingCommand;

class JobsController extends \BaseController {

	use CommanderTrait;

	/**
	 * Post the new job listing.
	 *
	 * @return Response
	 */
	public function store()
	{
        $this->execute(PostJobListingCommand::class);

		return Redirect::home();
	}

Notice how we are representing the user's instruction (or command) as a readable class: PostJobListingCommand. The execute method will expect the command's class path, as a string. Above, we're using the helpful PostJobListingCommand::class to fetch this. Alternatively, you could manually write out the path as a string.

The Command DTO

Pretty simply, huh? We make a command to represent the instruction, and then we throw that command into a command bus. Here's what that command might look like:

<?php namespace Acme\Jobs;

class PostJobListingCommand {

    public $title;

    public $description;

    public function __construct($title, $description)
    {
        $this->title = $title;
        $this->description = $description;
    }

}

When you call the execute method on the CommanderTrait, it will automatically map the data from Input::all() to your command. You won't need to worry about doing that manually.

So what exactly does the command bus do? Think of it as a simple utility that will translate this command into an associated handler class that will, well, handle the command! In this case, that means delegating as needed to post the new job listing.

By default, the command bus will do a quick search and replace on the name of the command class to figure out which handler class to resolve out of the IoC container. As such:

  • PostJobListingCommand => PostJobListingCommandHandler
  • ArchiveJobCommand => ArchiveJobCommandHandler

Make sense? Good. Keep in mind, though, that if you prefer a different naming convention, you can override the defaults. See below.

Decorating the Command Bus

There may be times when you want to decorate the command bus to first perform some kind of action...maybe you need to first sanitize some data. Well, that's easy. First, create a class that implements the Laracasts\Commander\CommandBus contract...

<?php namespace Acme\Jobs;

use Laracasts\Commander\CommandBus;

class JobSanitizer implements CommandBus {

    public function execute($command)
    {
       // sanitize the job data
    }

}

...and now reference this class, when you execute the command in your controller.

$this->execute(PostJobListingCommand::class, null, [
    'JobSanitizer'
]);

And that's it! Now, you have a hook to sanitize the command/data before it's passed on to the handler class. On that note...

The Handler Class

Let's create our first handler class now:

<?php namespace Acme\Jobs;

use Laracasts\Commander\CommandHandler;
use Laracasts\Commander\Events\DispatchableTrait;

class PostJobListingCommandHandler implements CommandHandler {

    use DispatchableTrait;

    public function handle($command)
    {
        $job = Job::post($command->title, $command->description);

        $this->dispatchEventsFor($job);

        return $job;
    }

}

For this demo, our handler is fairly simple. In real-life, more would be going on here. Notice that dispatchEventsFor method? This will handle the process of firing all queued events for your entity. This way, other parts of your app may listen for when a job has been published, and respond accordingly.

Raising an Event

Here's a quick and dirty example of what that Job model might look like:

<?php namespace Acme\Jobs;

use Laracasts\Commander\Events\EventGenerator;
use Acme\Jobs\Events\JobWasPublished;

class Job extends \Eloquent {

    use EventGenerator;

    protected $fillable = ['title', 'description'];

    public static function post($title, $description)
    {
        // We're ignoring persistence for this demo
        $job = new static(compact('title', 'description'));

        $job->raise(new JobWasPublished($job));

        return $job;
    }
}

Pay close to attention to where we raise that event.

$job->raise(new JobWasPublished($job));

Once again, this JobWasPublished object is nothing more than a simple transport object.

<?php namespace Acme\Jobs\Events;

use Acme\Jobs\Job;

class JobWasPublished {

    public $job;

    public function __construct(Job $job) /* or pass in just the relevant fields */
    {
        $this->job = $job;
    }

}

Also, the raise method is available through that EventGenerator trait. It simply stores the event in an array.

Event Listeners

Now, because the handler class dispatched all events, that means you can register any number of listeners. The event name to listen for follows, once again, a simple convention:

  • Path\To\Raised\Event => Path.To.Raised.Event

So, essentially, we replace slashes with periods to make it appear just a bit more object-oriented. So, if we raise:

  • Acme\Jobs\Events\JobWasPublished

Then, the event to listen for will be:

  • Acme.Jobs.Events.JobWasPublished

Let's register a basic event listener to fire off an email.

Event::listen('Acme.Jobs.Events.JobWasPublished', function($event)
{
    var_dump('Send a notification email to the job creator.');
});

Remember: you can register multiple listeners for the same event. Maybe you also need to do something related to reporting when a job is published. Well, add a new event listener!

Now, this example above uses a simple closure. If you want, you could take a more "catch-all" approach, which this package can help with.

First, let's setup an EmailNotifier class that will be given a chance to handle all fired events for our app.

Event::listen('Acme.*', 'Acme\Listeners\EmailNotifier');

So, now, any time that you raise an event in the Acme namespace, once dispached, the EmailNotifier class' handle method will fire. Naturally, though, we don't need to respond to every event! Just a few. Well, once again, we can follow a simple method naming convention to respond to only the events that we are interested in.

The JobWasPublished event class will look for a whenJobWasPublished method on your event listener. If it exists, it will call it. Otherwise, it'll simply continue on. That means our EmailNotifier class might look like so:

<?php namespace Acme\Listeners;

use Laracasts\Commander\Events\EventListener;
use Acme\Jobs\Events\JobWasPublished;

class EmailNotifier extends EventListener {

    public function whenJobWasPublished(JobWasPublished $event)
    {
        var_dump('send an email');
    }

}

Because this class extends EventListener, that parent class will manage all the details of determining if whenJobWasPublished should be called.

File Generation

You'll likely find yourself manually creating lots and lots of commands and handler classes. Instead, use the Artisan command that is included with this package! Simply run:

php artisan commander:generate Acme/Bar/SubscribeUserCommand

This will generate both SubscribeUserCommand and a SubscribeUserCommandHandler classes. By default, it will look for that "Acme" directory within "app/". If your base domain directory is somewhere else, pass the --base="src".

The Command

<?php namespace Acme\Bar;

class SubscribeUserCommand {

    /**
     * Constructor
     */
    public function __construct()
    {
    }

}

The Handler

<?php namespace Acme\Bar;

use Laracasts\Commander\CommandHandler;

class SubscribeUserCommandHandler implements CommandHandler {

    /**
     * Handle the command.
     *
     * @param object $command
     * @return void
     */
    public function handle($command)
    {

    }

}

Or, if you also want boilerplate for the properties, you can do that as well.

php artisan commander:generate Acme/Bar/SubscribeUserCommand --properties="first, last"

When you add the --properties flag, the handle class will remain the same, however, the command, itself, will be scaffolded, like so:

<?php namespace Acme\Bar;

class SubscribeUserCommand {

    /**
     * @var string
     */
    public $first;

    /**
     * @var string
     */
    public $last;

    /**
     * Constructor
     *
     * @param string first
     * @param string last
     */
    public function __construct($first, $last)
    {
        $this->first = $first;
        $this->last = $last;
    }

}

Nifty, ay? That'll save you a lot of time, so remember to use it.

When calling this command, use forward slashes for your class path: Acme/Bar/MyCommand. If you'd rather use backslashes, you'll need to wrap it in quotes.

That Does It!

This can be complicated stuff to read. Be sure to check out the Commands and Domain Events series on Laracasts to learn more about this stuff.

commander's People

Contributors

everzet avatar grahamcampbell avatar huglester avatar imjohnbon avatar jake284773 avatar jeffreyway avatar jensmombaerts avatar jeroennoten avatar wkjagt avatar yateric avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

commander's Issues

Could the package allow for custom Mustache templates to be used when generating commands?

I don't think this is currently an option from what I can see, but is there any way to override the default command.stub or handler.stub that the package uses when generating commands? It could be useful when a project has its own common patterns which each command uses. I'm finding in one project that I'm making the same changes to the default generated commands and handlers every time.

Passing sometimes existing and sometimes non exsisting input

I have a checkbox that only exists in my post values when it's checked. When not checked, the value doesn't exist in Input::all() resulting in a InvalidArgumentException when mapping the input to the command. I toughed to be smart and gave the parameter a default value of null, this way the command executes when the checkbox is not checked, but when it's checked the value stays null. After reading theCommanderTraid::mapInputToCommand method I realised that it's coded in this way.

Though, I'm curious what people think of an approach where, when you don't always have the input available, you can give a default vale of null and make a check inside mapInputToCommand to see if the default value of the parameter is different to the value of the input from the same key. And if that's the case, assign the input value instead of the default value.

Maximum function nesting level of '100'

All of a sudden, all of my commands are throwing this error. I tried increasing the limit, but it appears there is a loop somewhere.

protected function getAlias($abstract)

Is the line that's throwing it, and it only happens when I execute a command (any command). Any ideas?

When the parameters within the construct of the Command class are many

Hi guys,
this is a not real issue, but i want to tell you what i mean.
Sometimes we need to process a lot of data, and not only a few like in the larabook's lesson.
So in this situation the mapInputToCommand method doesn't works like we expect, if we think that we have an array like params for the construct, similar to something like that:

    public function __construct(array $attributes)
    {
        $this->attributes = $attributes;
    }

what can we do ? I must simply ignore the mapInput method ? Or is a mistake think like that ?

Make mapInputToCommand optional in CommanderTrait

Hi Jeffrey,

For CommanderTrait I thought it might be handy to make mapInputToCommand in the execute method optional because sometimes you may wish to build up a command object that is not directly tied to a form input. For example, say you want to pass the currently authenticated user's id into the command. This value would not come from a form input, but directly from the controller. What do you think? Am I missing something totally obvious? As always, thanks, you do great work!

Warning: Ambiguous class resolution

Using "laracasts/commander": "~1.0" with Laravel 4.2 I get the following warning when doing composer update. Any clues?

Warning: Ambiguous class resolution, "Illuminate\Foundation\Application" was found in both
"/var/www/adsf/htdocs/vendor/laravel/framework/src/Illuminate/Foundation/Application.php"
and "/var/www/asdf/htdocs/vendor/laracasts/commander/spec/Laracasts/Commander/ValidationCommandBusSpec.php", the first will be used.

Call to undefined method Laracasts\Commander\ValidationCommandBus::decorate()

I have created a so called decorator and passed it to the execute method like so

$this->execute( ImportPlayerCommand::class, $input, [
                'ImportPlayerPositionConverter'
            ] );

the decorator isn't doing anything yet

use Laracasts\Commander\CommandBus;

class ImportPlayerPositionConverter implements CommandBus {

    public function execute( $command ) {
       die('dddddd');
    }

}

the error thrown is: Call to undefined method Laracasts\Commander\ValidationCommandBus::decorate()

regards,
Ronnie

Returning created entity

Hey,

Just wondering how I would go about getting the newly created entry in my controller after using the command. $this, doesn't get any useful information. The only way I see would be to request the database again, but if I can avoid a DB call I'll be glad.

Thanks for any help

Related Models

I've been struggling with how to handle related models.

At the moment, my requirement is to associate an image with a post.

post = [
    'body' => 'body text',
    'image_ids' => [1,2]
];

I validate the data and execute a new PublishPostCommand.

Should there be an AttachImagesToPostCommand? (and if so, how do we get the Post model outside the command?)

Or, within the PublishPostCommand should there be a repository call like:

$this->postRepository->save($post);
$this->postRepostiory->attachImages($command->image_ids);

(and if so, how do we get the Post model outside the postRepository?)

Or, within the save method of the postRepository, should there be logic to handle the attachment? (if, then attach statements)?

$this->postRepository->save($post, $command->image_ids);

I hope the question is clear. None of my solutions fall into place so I'm assuming I'm missing something.

Thanks to anyone who can help.

... at the end of the tunnel I'm assuming there's something like this in the postRepository

public function attachImage(Post $post, $image_ids)
{
    foreach($image_ids as $image_id)
    {
        $post->images()->associate($image_id);
    }
}

Duplicate UnitTester

When i installed this package, I was no longer able to run any of my codecept unit tests. I get Duplicate UnitTester Defined. It was defined in this package. As soon as I removed this package, it allowed me to run my tests again.

composer: "Your requirements could not be resolved to an installable set of packages."

Hi,

When trying to include commander via composer I get error shown below:

Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Conclusion: remove laravel/framework v4.2.7
    - Conclusion: don't install laravel/framework v4.2.7
    - Conclusion: don't install laravel/framework v4.2.6
    - Conclusion: don't install laravel/framework v4.2.5
    - Conclusion: don't install laravel/framework v4.2.4
    - Conclusion: don't install laravel/framework v4.2.3
    - Installation request for laracasts/commander 1.0 -> satisfiable by laracasts/commander[1.0].
    - Conclusion: don't install laravel/framework v4.2.2
    - Conclusion: don't install laravel/framework v4.2.1
    - laracasts/commander 1.0 requires illuminate/support 4.1.* -> satisfiable by illuminate/support[v4.1.0, v4.1.1, v4.1.10, v4.1.11, v4.1.12, v4.1.13, v4.1.14, v4.1.15, v4.1.16, v4.1.17, v4.1.18, v4.1.19, v4.1.2, v4.1.20, v4.1.21, v4.1.22, v4.1.23, v4.1.24, v4.1.25, v4.1.26, v4.1.27, v4.1.28, v4.1.29, v4.1.3, v4.1.30, v4.1.4, v4.1.5, v4.1.6, v4.1.7, v4.1.8, v4.1.9].
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.0
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.1
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.10
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.11
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.12
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.13
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.14
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.15
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.16
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.17
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.18
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.19
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.2
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.20
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.21
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.22
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.23
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.24
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.25
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.26
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.27
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.28
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.29
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.3
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.30
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.4
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.5
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.6
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.7
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.8
    - don't install laravel/framework v4.2.0|don't install illuminate/support v4.1.9
    - Installation request for laravel/framework 4.2.* -> satisfiable by laravel/framework[v4.2.0, v4.2.1, v4.2.2, v4.2.3, v4.2.4, v4.2.5, v4.2.6, v4.2.7].

Is it possible to bump illuminate/support requirements to 4.2 or is it package dependant?

Laravel 4.3

Hey Jeffrey!

Is Commander coming to Laravel 4.3? I want to start using Laravel 4.3 and this is the last dependency I need to start working with 4.3.

Decorator error when command is triggering another command

Hi,

I have the following logica in my app:
A command is creating a player which is firing a event which checks if the player already has an alias, if not it will create it using another command. The first command has a decorator. When the second command is firing it is also hitting the decorator given in the first command which should not happen.

Regards, Ronnie

Could this be used in laravel 5

I prefer to use this command bus, as it returns values from a command
in the opposite of the new laravel 5 command bus that doesn't return value.

Using CommanderTrait with Console commands

I recently hit a snag with using the CommanderTrait with a class inheriting from Illuminate/Console/Command. Because CommandTrait declares its own execute() method, there is a signature conflict with the method declared in Illuminate/Console/Command.

The solution I came up with was to create a class, CommanderExecutor, that uses the CommanderTrait and inject an instance of that CommanderExecutor as a class dependency, then referenced the object to invoke execute(). It's a little bit hacky, but it works

Validation Decorator

I used the validation decorator in many cases. Now I use a different approach to do validate the data. When I deleted the Validator classes, I got a File not found Exception.
I tried a composer dumpautoload then everything worked fine again.

CommanderTrait method getCommandBus detected as Controller action

I have the CommanderTrait in one of my Controller (not resource) and when I see the list of routes, the route uri/command-bus comes out because the method start with get, or is public (or probably both). A quick fix might be setting the method visibility to protected, since no-one will call a method from a Controller.
Here's the route:

| | GET|HEAD auth/command-bus/{one?}/{two?}/{three?}/{four?}/{five?} |  | Pixel\Http\Controllers\Auth\AuthController@getCommandBus | | |

Validation is being fired twice when using ValidationCommandBus

Hi!
I've noticed a strange bug when trying to use ValidationCommandBus. It appears that when executing command with this bus this decorator is firing validator then using the default command bus which is bound to another ValidationCommandBus via the service provider.

$this->app->bindShared('Laracasts\Commander\CommandBus', function ($app)
        {
            $default = $app->make('Laracasts\Commander\DefaultCommandBus');
            $translator = $app->make('Laracasts\Commander\CommandTranslator');

            return new ValidationCommandBus($default, $app, $translator);
        });

This code binds the interface to implementation of ValidationCommandBus so it is looping here for me. The version is 1.3.10.

Method injection CommandHandler

Hey Jeffrey!

I am trying to do method injection in a CommandHandler class like so:
public function handle($command, \UserRepository $userRepository)

Still, I'm getting the following error:
Declaration of Site\Registration\RegisterUserCommandHandler::handle() must be compatible with Laracasts\Commander\CommandHandler::handle($command)

Is it even possible to do method injection here?

Infinite recursion

I was following Laracast video on Commander. However, when I ran it I kept getting 502 bad gateway error. I've narrowed the cause down to when I inject CommandBus into registrationController __construct. As soon as I remove it, I no longer get 502 error. However, when I put it back in and run it through Codeception I see that it runs into an infinite recursion.

PHP stack trace shows this:
PHP 38. Illuminate\Foundation\Application->make() /vagrant/finit/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php:78
PHP 39. Illuminate\Container\Container->make() /vagrant/finit/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:463
PHP 40. Illuminate\Container\Container->build() /vagrant/finit/vendor/laravel/framework/src/Illuminate/Container/Container.php:432
PHP 41. Illuminate\Container\Container->getDependencies() /vagrant/finit/vendor/laravel/framework/src/Illuminate/Container/Container.php:543
PHP 42. Illuminate\Container\Container->resolveClass() /vagrant/finit/vendor/laravel/framework/src/Illuminate/Container/Container.php:576
PHP 43. Illuminate\Foundation\Application->make() /vagrant/finit/vendor/laravel/framework/src/Illuminate/Container/Container.php:617
PHP 44. Illuminate\Container\Container->make() /vagrant/finit/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:463
PHP 45. Illuminate\Container\Container->build() /vagrant/finit/vendor/laravel/framework/src/Illuminate/Container/Container.php:432
PHP 46. Illuminate\Container\Container->Illuminate\Container{closure}() /vagrant/finit/vendor/laravel/framework/src/Illuminate/Container/Container.php:507
PHP 47. Laracasts\Commander\CommanderServiceProvider->Laracasts\Commander{closure}() /vagrant/finit/vendor/laravel/framework/src/Illuminate/Container/Container.php:216
PHP 48. Illuminate\Foundation\Application->make() /vagrant/finit/vendor/laracasts/commander/src/Laracasts/Commander/CommanderServiceProvider.php:56
PHP 49. Illuminate\Container\Container->make() /vagrant/finit/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:463

Sometimes $command is empty in handler

One of my command DTOs are not getting passed through properly.

I don't know why. it is very weird... All of my other commands work fine...

# in controller
$this->execute(new ScrapeMovieReviewFeedCommand($url));

dd() in the controller gives me the expected value.

dd() in the Command gives the expected value.

dd() in the CommandHandler gives me:

object(Acme\MovieReviews\Commands\ScrapeMovieReviewFeedCommand)#339 (1) { ["url"]=> string(0) "" }

What could be the problem? I am drawing a blank...

Decorators of the parent command will be executed on the child command

I have CommandA with ONE decorator class.

I have CommandB with NO decorator classes.

In CommandA handler, I execute CommandB.

By right, when I execute CommandA, these steps should happen:

1- Decorator of CommandA should be executed
2- CommandA handler should be called
3- CommandB handler should be called

However, I found that the decorator class of CommandA will execute twice:

1- Decorator of CommandA is executed
2- CommandA handler is called
3- Decorator of CommandA is executed again
4- CommandB handler is called

I managed to fix the issue by adding this check to CommanderTrait->execute() function:

if (empty($decorators))
{
    $bus->emptyDecorators();
}

where emptyDecorators() is defined in CommandBus implementation as:

/**
* Remove all 
*/
public function emptyDecorators ()
{
    $this->decorators = [];
}

Thanks.

Unable to use $this->execute inside an artisan command

Hi,
i'm trying to use the CommanderTrait inside an artisan command, but i receive the following error:
{"error":{"type":"ErrorException","message":"Declaration of Laracasts\\Commander\\CommanderTrait::execute() should be compatible with Illuminate\\Console\\Command::execute(Symfony\\Component\\Console\\Input\\InputInterface $input, Symfony\\Component\\Console\\Output\\OutputInterface $output)","file":"\/Users\/lucacri\/Sites\/YodaImporter\/app\/commands\/ReassignVncPorts.php","line":77}}

From what i can see, the Illuminate\Console\Command has already an execute method in line 110:
protected function execute(InputInterface $input, OutputInterface $output)

and it's not working well with the CommanderTrait. Any suggestion on how to fix it?

Laravel 5

Jeff,

When can we expect an update for the commander package that can be used in laravel 5? Currently the dependencies on the older versions (Support and Filesystem) prevent Commander from being included in laravel 5 projects.

I know that laravel 5 is currently in heavy development but trying laravel 5 out with this package would be awsome.

A temporary fix could be just updating the dependencies and stability for laravel 5:

{
    "name": "laracasts/commander",
    "description": "Commands and domain events in Laravel",
    "license": "MIT",
    "authors": [
        {
            "name": "Jeffrey Way",
            "email": "[email protected]"
        }
    ],
    "require": {
        "php": ">=5.4.0",
        "illuminate/support": "~5.0",
        "illuminate/filesystem": "~5.0",
        "mustache/mustache": "~2.6"
    },
    "require-dev": {
        "phpspec/phpspec": "~2.0.0",
        "codeception/codeception": "~2.0.0"
    },
    "autoload": {
        "psr-0": {
            "Laracasts\\Commander": "src/"
        }
    },
    "minimum-stability": "dev"
}

Command in path

Just something to note. If the full namespace for the command also has command in it, it replaces all instances of it. Might be worth looking for it at the end of the line.

Triggering executeDecorators before validateCommand (in ValidationCommandBus)

When I use a decorator to sanitize data passed to the command, I would like to have that be executed before the validationCommand. The method below is from the ValidationCommandBus, but I've switched the $this->executeDecorators($command); with $this->validateCommand($command);.

Does swapping the order make sense for somebody else too? I can imagine there will be situations where this is not working as wanted (because you do want it to be validated first), but I would love to hear others opinions.

/**
 * Execute a command with validation.
 *
 * @param $command
 * @return mixed
 */
public function execute($command)
{
    // Next, we'll execute any registered decorators.
    $this->executeDecorators($command);

    // If a validator is "registered," we will
    // first trigger it, before moving forward.
    $this->validateCommand($command);

    // And finally pass through to the handler class.
    return $this->bus->execute($command);
}

One workaround would be to ignore the Validator decorator naming convention and making a JobValidator and add it after the JobSanitizer.

$this->execute(PostJobListingCommand::class, null, [
    'Acme\Job\JobSanitizer',
    'Acme\Job\JobValidator'
]);

Specify properties types

Maybe I'm just too used to generate:migration but it would be nice to be able to do this:

$ php artisan commander:generate Acme/Bar/SubscribeUserCommand --properties="first:string, last:Some\Class"

And have the docblocks updated in consequence

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.