12. Laravel Actions. Fat Models or Fat Controllers? Service Layer?
Video version
(Leave your feedback on YouTube)
USE Actions. For Laravel - Laravel action package
Laravel action is absolutely the best solution I have worked with.
The documentation is comprehensive, but here are a few tips from my personal experience:
- "Cherry picking" - allows you to limit an Action to only the set of tools that are used. This is, of course, a micro-optimization, but it makes project maintenance easier. The developer will have a better understanding of how an Action is used. For stub Actions, I recommend setting the "AsController" trait by default - it will be encountered most frequently.
- Do not use
public static function routes(Router $router)
. Unfortunately, it is not cached.route:cache
does not work. And since it is static, Laravel Octane does not work well with it. - Use
handler
as the base function. Write all differences for each usage variant in specific functions (asController
,asJob
, etc.). $this->handler
should be called from all specific functions. If this is not the case, you most likely have crammed 2 Actions into one.run
is a convenient function but does not allow the use of PHP8 named parameters.SomeAction::make()->handler()
will make navigation a bit easier.runIf
,dispatchIf
,runUnless
,dispatchUnless
- reduce the cognitive complexity of the code.- Laravel Actions are well tested. A small tip - when an Action is simple, a feature test is sufficient. When it is complex, test only access and response formats in feature tests, and test the ActionHandler itself with unit tests.
AsFake
is very helpful when testing ActionAsObject. Test ActionAsObject separately and simply call its mock in the Actions where it is used. CheckshouldRun
,shouldNotRun
. Check input parameters withshouldRun->with
. And mock the result withshouldRun->andReturn
.- It is better to move validation to
FormRequest
. This will reduce code and allow for proper reuse ofFormRequest
. - The
WithAttributes
trait makes the code more complex. It is better to fully utilize PHP8 named parameters. And, of course, running validation on parameters that we set ourselves in the method is not very productive. - One task - one Action. Do not create extra layers of code, do not use extra patterns, do not create extra services. An Action will cover the vast majority of your requests.
- Action is ideal for interaction between modules. In the case of moving a module to a service, an Action will simply start calling the code from the service.