laravel / ideas

Issues board used for Laravel internals discussions.
938 stars 28 forks source link

[Proposal] Laravel Actions #1868

Open rogervila opened 4 years ago

rogervila commented 4 years ago

Hello,

@lorisleiva has created a Laravel Actions package that unifies all the necessary steps to do a specific task under a single component class: https://github.com/lorisleiva/laravel-actions

I think that this is a very interesting pattern and I would like to know what the community thinks about implementing it natively.

Thank you.

martinbean commented 4 years ago

@rogervila It’s already possible to wrap actions in a single class:

$ php artisan make:job CreateArticle --sync
class ArticleController extends Controller
{
    public function store(StoreArticleRequest $request)
    {
        $article = CreateArticle::dispatchNow($request->validated());
    }
}
rogervila commented 4 years ago

Hi @martinbean On your example, there are at least 4 files involved:

  1. Routes file (web.php)
  2. StoreArticleRequest
  3. ArticleController
  4. CreateArticle

@lorisleiva's package wraps all related steps that are part of a single action inside only one file. Then, instead of modifying 4 files, only 1 is affected, making it more easy to maintain.

martinbean commented 4 years ago

@rogervila The route, controller, and form request were an example of how to dispatch a job. The actual logic is still contained to the job class only.

Even an “action” still needs invoking somehow. Probably in a controller action, which will need to be hooked up with a route to be accessible…

lorisleiva commented 4 years ago

Hi @martinbean,

Even though I don't think Laravel is ready to switch to such a different paradigm that is Laravel Action, I feel like some points need to be clarified with regards to the value it provides.

Currently, the entire ecosystem of the app directory defaults to categorising your building blocks based on implementation patterns.

There is absolutely nothing wrong with organising things this way. It's the system I fell in love with when I originally learned Laravel.

However, this is not an organisation paradigm that really fits with my mental model. When I think of my application I don't see it as bags of requests, controllers, policies, jobs, listeners, etc. I see it as a set of features, a set of values that I bring to my users or (dare I say) a set of domains.

Which is why I started to organise some of my applications as a collection of actions. An action being: "something my application can do". And this action encapsulates any authorisation, validation and execution logic that is needed to run it as well as encapsulating how it is being run.

Therefore, I think that a synchronous job called in a dedicated method of a controller is not a fair comparison to Laravel Action. I highly recommend you have a read through the documentation of Laravel Action to check out everything that it can do.

I hope this helps anyone understands my motivations behind this package and perhaps, in a future major release, the Laravel framework will be inspired by this approach and implement something similar.

martinbean commented 4 years ago

@lorisleiva I have read through the documentation. I’ve been aware of the package for a little while now (can’t remember if I came across it on Twitter or in a Laravel News newsletter).

I’ve nothing wrong with you doing something that fits your personal mental model, but it doesn’t mean it should be something that’s included in a PHP framework by default. In my view, it’s fine to live as a third-party package. Otherwise, I may as well start opening ideas for a more accepted paradigm such as ADR, or “request-driven development” (which, coincidentally, look similar to your “action” classes).

To clarify, I’m not denying that this “action” class-based approach does not provide any value. I’m just saying I don’t think it’s something that warrants being included in the core framework. An organisation paradigm that more “fits with [your] mental model” needs more of a reason to be included in a framework that’s been downloaded tens of millions of times by developers who don’t share your mental model.

lorisleiva commented 4 years ago

Oh absolutely, my comment was purely a reply to your statement:

"It’s already possible to wrap actions in a single class [by calling a synchronous job in a dedicated method of a controller]".

As I've mentioned before I don't think that the Laravel framework is ready for such a big change and, if it was, why would it choose this one when no other frameworks seem to be interested in this approach?

In any case, I thank @rogervila for opening this issue because it's a valid topic to debate and I think that's the whole point of laravel/ideas, i.e. to discuss ideas that might or might not be suitable for the framework at this time.