laravel-actions

⚡️ Laravel components that take care of one specific task

MIT License

Downloads
3.5M
Stars
2.5K
Committers
26

Bot releases are hidden (Show)

laravel-actions - v1.1.5

Published by lorisleiva about 4 years ago

🚑 Fixes ignored default values in handle method (#66)

laravel-actions - v1.1.4

Published by lorisleiva about 4 years ago

🚑 Bug fix

laravel-actions - v1.1.3

Published by lorisleiva about 4 years ago

⬆️ Add support for Laravel 8

laravel-actions - v1.1.2

Published by lorisleiva about 4 years ago

📝 Use expectsJson instead of wantsJson to determine if we should use jsonResponse for Actions as controllers.

laravel-actions - v1.1.1

Published by lorisleiva over 4 years ago

laravel-actions - v1.1.0

Published by lorisleiva over 4 years ago

This release slightly adjusts the dependency injection logic by supporting nullable typehints. Let's go through a few examples to understand what that really means.

A) Optional injections

Assuming $service is not an attribute of this action, prior to this version, it would have resolved the MyInjectedService class from the container even though it's an optional typehint (notice the ? prefix). Now, it will not even try to resolve it from the container. This mechanism can be helpful to turn dependency injection off for certain arguments.

class MyAction extends Action
{
    public function handle(?MyInjectedService $service)
    {
        // ...
    }
};

The reason behind this change is to make sure Laravel Actions does not try to become too intrusive when resolving the arguments of your methods.

B) Optional route bindings

Consider the example below where the User model is typehinted but marked as nullable. Prior to this version, Laravel Actions would have thrown an exception if the provided user identifier did not successfully retrieve a user from the database. Now, it will return null instead of throwing an exception if the user cannot be found via the provided identifier.

class MyAction extends Action
{
    public function handle(?User $user)
    {
        // if $user is "1" and User::find(1) exists, it returns the fetched model.
        // if $user is "42" and User::find(42) does not exist, it returns null instead of throwing an exception
        // if $user is null, it returns null instead of throwing an exception
    }
};

The reason behind this change is to allow a more flexible route model binding.


Whilst these changes can break some existing code (hence the jump to 1.1) it is very unlikely that it will. Chances are, if you were marking a typehint as nullable before, you were already planning for that argument to be null.

laravel-actions - v1.0.4

Published by lorisleiva over 4 years ago

📝 Add controllerMiddleware method to avoid conflicts with job middleware. If the controllerMiddleware is not provided, it falls back to using middleware to avoid breaking changes.

laravel-actions - v1.0.3

Published by lorisleiva over 4 years ago

🤝 Add support for custom implicit route bindings (e.g. /articles/{article:slug}) and nested route bindings (e.g. /users/{users}/articles/{article:slug}) for Laravel 7 only (see Laravel documentation).

laravel-actions - v1.0.2

Published by lorisleiva over 4 years ago

Make handle method optional. This allows for actions acting as pure authorisation or validation guards as well as actions that simply need a response method to render some view. (See #39)

laravel-actions - v1.0.1

Published by lorisleiva over 4 years ago

Adjust PHPStorm annotations to allow for custom getAttributeFromConstructor logic.

laravel-actions - v1.0.0

Published by lorisleiva over 4 years ago

What's new?

⚡️ Run actions as commands (documentation)

You can now run actions as commands by simply providing the commandSignature static property.

class PublishANewArticle extends Action
{
    protected static $commandSignature = 'make:article {title} {body}';
    protected static $commandDescription = 'Publishes a new article';

    // ...
}

🚗 Register routes directly in actions (documentation)

You can now register your routes directly in the routes static method of your actions.

class GetArticlesFromAuthor extends Action
{
    public static function routes(Router $router)
    {
        $router->get('author/{author}/articles', static::class);
    }

    public function handle(User $author)
    {
        return $author->articles;
    }
}

🧙‍♂️ instantiate an action with custom arguments (documentation)

Imagine the following GetItineraryInstructions action that returns an array of strings given an address and a transportation mode. Here is how you would need to instantiate this action:

$action = new GetItineraryInstructions([
    'address' => $address,
    'mode' => 'driving',
]);

However, in this particular case, this action will always take an address and a mode attribute so wouldn't it be better if we could just write this instead?

$action = new GetItineraryInstructions($address, 'driving');

Well, starting from v1.0, you can. All you need to do to make this work is to define your custom logic in the getAttributesFromConstructor method. See the documentation to learn more about this.

Note that, this will also work with the run and dispatch static methods.

// As an object.
GetItineraryInstructions::run($address, 'driving');

// As a job.
GetItineraryInstructions::dispatch($address, 'driving');

How to upgrade from 0.x?

📦 Composer update

# In your composer.json
"lorisleiva/laravel-actions": "^1.0",
composer update lorisleiva/laravel-actions

🚨 Potential breaking changes

  • The register method has been renamed initialized. It will be called every single time an action is instantiated no matter how it is running. (See The lifecycle of an action).

  • In order to register actions as commands and register routes directly within actions, Laravel Actions need to know where your Actions are kept. By default, it will look inside the app/Actions directory. This new discovery mechanism might interfere with your current architecture. If this is the case, you can tell Laravel Actions were to look for actions using Actions::paths([...]) in a service provider. Alternatively you can disable this altogether via the Actions::dontRegister() method. (See Registering actions).

  • - public function updateAttributeWithResolvedInstance($key, $instance)
    + protected function updateAttributeWithResolvedInstance($key, $instance): void
    
    - protected function findAttributeFromParameter($name, $extras = [])
    + protected function findAttributeFromParameter($name, $extras = []): array
    
    - protected function resolveMethodDependencies($instance, $method, $extras = [])
    + protected function resolveMethodDependencies($instance, $method, $extras = []): array
    
    - public function delegateTo($actionClass)
    + public function delegateTo(string $actionClass)
    
laravel-actions - v0.3.0

Published by lorisleiva over 4 years ago

⬆️ Add support for Laravel 7 (#35)
🐎 No longer instantiate every listener to check if it's an action (#33)
✨ Add the following new static helpers to run actions (#36)

MyAction::make([/* ... */])

// Equivalent to:
new MyAction([/* ... */]);
MyAction::run([/* ... */])

// Equivalent to:
(new MyAction)->run([/* ... */]);

⚠️ This is a potential breaking change if your application is overriding the run method. If that's the case make sure to override the handleRun method instead.

// Previous signature to override.
public function run(array $attributes = [])

// New signature to override.
protected function handleRun(array $attributes = [])
laravel-actions - v0.2.5

Published by lorisleiva almost 5 years ago

Add support for dependency injection to the following methods: rules(), messages() and attributes().

This means you can now resolve your Eloquent models or Service classes before even reaching the handle() method.

This could be helpful, for example, when excluding a model in a unique rule.

class UpdateTeamProfile extends Action
{
    public function rules(Team $team)
    {
        return [
            'name' => ['filled', 'max:255'],
            'slug' => [
                'filled',
                'alpha_dash',
                Rule::exists('teams')->ignore($team->id),
            ],
        ];
    }
    
    public function handle(Team $team)
    {
        $team->update($this->validated());

        return $team;
    }
}
laravel-actions - v0.2.4

Published by lorisleiva almost 5 years ago

🐛 Edit the Bus Dispatcher so that it uses the action itself as a job handler instead of a proxy. This allows the use of properties like public $timeout directly within the action. (see #28)

laravel-actions - v0.2.3

Published by lorisleiva almost 5 years ago

  • 📝 Define __isset magic method. (#27)
  • 🐛 Restart validation every time we re-run an action. (#26)
laravel-actions - v0.2.2

Published by lorisleiva almost 5 years ago

  • Clear cached Event Facade instance (46028c294da9825a1231ac1eb4035b7b1eaa8433)
  • Add prepareForValidation method (9c99635af7cd8d20a8034bec49e50c107896c818)
laravel-actions - v0.2.1

Published by lorisleiva about 5 years ago

⬆️ Add support for Laravel 6.x

laravel-actions - v0.2.0

Published by lorisleiva about 5 years ago

⚠️ Middleware registration (breaking changes) In preparation of Laravel 6, the middleware registration changes slightly to follow the same API as the upcoming Job middleware.

// Before.
public function register()
{
    $this->middleware('auth');
}

// After.
public function middleware()
{
    return ['auth'];
}

Actions are now invokable as objects

// When running an action as an object.
$action = new PublishANewArticle([
    'title' => 'My blog post',
    'body' => 'Lorem ipsum.',
]);

// You can now run it like this...
$action();

// Which is equivalent to...
$action->run();
laravel-actions - v0.1.4

Published by lorisleiva about 5 years ago

🚑 Fix namespace typo (#16)

laravel-actions - v0.1.3

Published by lorisleiva over 5 years ago

🚑 Fix issue #7 by decorating the existing event dispatcher instead of overriding it with a new instance.