Open RemiCollin opened 6 years ago
Really nice article @RemiCollin . One question I have, what folder structure do you use to store these action classes?
Thank you !
I usually group them by model/related group of models :
app/Actions/Users
app/Actions/Orders
...
Though in biggest projects, I tend to make an Actions
subfolder by logical "module" of the application :
/app/Cart/Actions
/app/Users/Actions
Does not really matter I guess as long as it make sense with the project you're working with and you keep things consistant ;)
Great, thank you very much :)
Interesting, my question is as your action classes are growing, so does the the register
method of your AppServiceProvider
. It would be nice if you could discuss that as well. And by the way I don't buy returning value on command class.
@JeyKeu I personally use synchronous Job for this, which avoid this registering issue.
@JeyKey : the register will grow only if you use adapters for your classes, otherwise classical DI works fine. Also I have a trick for generating adapters for all actions classes which prevent it from growing, but it could be the subject of an entire article by itself.
@JeyKeu & @stvnyung : Actions are not Jobs or CQRS commands. They are meant to return data in a generic way which will be translated into a Response
. I think of them as the logical 'API' of an application. They can be a database Query as well. The important part is that they have to be Request/Response agnostic. I guess I should have insisted on this in the article :) Thanks for your feedback, really appreciated !
Also I have a trick for generating adapters for all actions classes which prevent it from growing, but it could be the subject of an entire article by itself.
Where I can read this article? :)
@melokki : i'll ping you once i've written it :)
@RemiCollin I get the point ! What is the benefits of creating a Action instead of a sync Job then ? I feel like both could do the same thing, are they really different or just the same in the end ?
P.S.: The idea of using Job like this mainly come from there https://github.com/lucid-architecture/laravel
@RemiCollin can sync jobs return objects/values? I think a job logically will contain bunch of actions.
@stvnyung ; from what I read Action would be closer to the Feature part in lucid architecture. Jobs are basically fire and forget; as @monaam pointed out, they cannot return values; they are designed for time-consuming task which you do not need to wait the response for completing a request, like sending an email, posting some data to a 3rd party API... edit : after further reading, lucid's jobs are not really like laravel's jobs hence the confusion. I'd say that the main difference is by design is that Actions always have resolvable dependencies, and can be injected inside a controller/method, and lucid's jobs have their parameters in the constructor, so they cannot be injected
@monaam : Yes I often embed one/several actions inside a job, if I need a time consuming script to run async in the queue.
@RemiCollin ping me too, great article 👍
@RemiCollin and me! 👍
@melokki @twocngdagz @orangeShadow : Decorating Action classes using generated proxies
@RemiCollin
Great article, I think what are you doing is somewhat ( ADR pattern ), but you don't separate the response in a new class ( the ADR way ).
In your way, how you deal with ( API Resources ) and where you put them ? inside actions ? or in the controller ?
@RemiCollin great article. How do you deal with retrieving models. Do you create an action for a simple User::where('active', 1)->orderBy('id', 'desc')->get()?
I know it's an older post. @RemiCollin this is great article, before running into it, I used similar approach (but with Service providers), but the problem I ran into is dealing with nested eager loading. Maybe you can shed some light onto it:
Let's take your example: User (1-M)> Blogs (1-M)> Comments > (1-M)> User
Let's say I need to load user with latest blog posts and 5 top comments with comment's user. Do I eager load in my Action/User/LoadUser.php
User::with['blog','blog.comments', 'blog.comments.user'])...
But let's say I don't need to load comments with their users for some sections of my website. Should I create: Action/User/LoadUserWithComments.php ?
Sometimes nested eagerloading can get pretty hectic (Especially for reporting) Or do I create a separate actions for each situation? Seems to be a lot of redundant code. Especially if business logic comes at play. (For example, only certain UserType(s) can be loaded or only logged in users can see comments. etc).
Maybe I am misunderstanding this?
Hi, @RemiCollin I have the same question with @michaelkove, should we create a new action class for a simple action such as getting data from a table? And how to deal with more complex queries that come with some different sections? Such as some controllers need A & B action, but some controllers else also need C & D (both A, B, C, D are just simple actions). Should I create AActionClass, BActionClass, CActionClass and DActionClass? This issue was not active for a long time, I glad to hear from you, sir!
https://medium.com/@remi_collin/keeping-your-laravel-applications-dry-with-single-action-classes-6a950ec54d1d