Laravel Controller: Move Logic to Action or Service Class

preview_player
Показать описание
In this live-coding experiment, I will try to move the logic outside of the Controller, and create an Action class, and later a Service class, performing the same thing. Which one do you prefer?

- - - - -
Support the channel by checking out our products:
Рекомендации по теме
Комментарии
Автор

I’m not keen on the abort calls in the action/service class. I think one of the main responsibilities of the controller is to decide which response should be returned (although the content of that response might come from a template or API resource, so having some responses in the service or action, and others in the controller doesn’t seem right to me. I could easily imagine coming to a project like this somewhere down the line and trying to figure out why it’s returning a 500 result all of a sudden. In this case I’d hope to be able to see the abort call in the controller itself rather than having to dig through the action service classes to find it, especially if they’re complex. Throwing an exception out of the service would be my preferred option for this reason.

JimOHalloran
Автор

As for me one of the main criteriums of a good application is the ability to call core logic from console, that's why I'm a huge fan of services that I can call from every place in my application

andrewwwlife
Автор

This reminded me of the correct way to use controllers, a concept I learned years ago with the Spring Framework. While others suggested using services in the comments, the simplicity of actions made it easier for me to understand and cleared the way for further learning. Thx!

dalok
Автор

1/ Checking, if someone can or can't do something is responsibility of Request (or Gate if necessery). You use authorization method in request always as true. But you can move this logic here. In single responsibility principle, store method is not about checking user.
2/ For this reason I preffer service layer which each part of logic is separated. Request checks user authorization and validate inputs. If is needed, throws exception which is handled by Exception Handler.
Next Controller call service layer which call all neccessery service methods. If is no exception throws, model is returned to controller and controller make response - ideally through Resource layer.
3/ This approach is nice for later adding new features without updating existing code and for writing unit tests (one for request, other for services) and one global as integration test with calling endpoint and testing valid response structure.

michalbabic
Автор

I've seen the service implementation on my previous rails job, didn't know I could do it with laravel too.

daleryanaldover
Автор

Cool stuff.. we are using services approach..

NSlides
Автор

Services are more interesting because as it has many methods, the service is not directly related to the main controller. Then another controller could have a need of one method of that service.
For example having a paymentService that has a create_wallet(), that method could be called from any other class like a listener to create user wallet when any new user registration.
Be in an handle method couldn't be that easy

jacquesmatike
Автор

The action is more popular called by Command Pattern, when every method in service make the service class too big to maintain then every method moved to one class to maintain individually

feryadialoi
Автор

Iam applying this knowledge to my proyect rigth now, and i like how looks the code

hederperez
Автор

In my opinion, in the action class the handle should return voice, but in your code in some condition it returns voice in other condition it returns void.
Then in the controller you recheck again the voice if it was recently created, which is a repetition, so the handle function should return voice and the conditions should be in the controller based on the returned voice object.
I dont know maybe i'm wrong but i prefer the insert update logic of controller to be in the controller and seperate the logic only in one case if i'm sure that the logic will be reused in other classes or methods

mohamadcheaib
Автор

I usually create actions as invokable classes just for keeping things clean.

soopercoco
Автор

Great content sir, this way we can handle request from frontend and API from the same Action/Service class logic. Can we implement this Service/Action class with livewire components?

NehalPatelTheBest
Автор

Thank you so much for the video. Instead of a try/catch in each controller method, can we not have a global Handler.php(as given by Laravel) which handles anything that is not caught by controller & service/action?

sateesh.ilavenil
Автор

Love your videos, thank you for a great resource. Are you planning on making a video of Laravel Octane, with pros and cons?

antonlindell
Автор

06:11 I saw you recommending in another video (Jr code review) to not leave the abort for the service, since it's not supposed to do that, but throwing an exception to the controller, which is the right place to do such thing.

AfmpJR
Автор

thanks for all the tutorials that you've made, I've been watching your video about optimization lately but is there any way to StressTest LaravelApp, I currently using artillery for that, but I don't quite understand, would u like to make a video about stress test?

amrullahdev
Автор

I believe the main purpose of single responsibility classes is to promote code re-usability.

Lets say I need to do the same action for api/web/command then the best thing would be to take all the logic into one place and use it everywhere and send the response as per where it is used. If I am using the action in api controller then handling the status code and returning data as json structure is the controller responsibility similarly if used in web it is the controller responsibility to either send some html or redirect to another page.

What I don't like in this video is that you are passing Request class as an argument to the action class which will limit the reuse of the action class as the request structure will be different for api/web/command so we should rather work with something like DTO (a plain class which contains almost no logic and contains only information needed to do the action). In this way your action class will be independent of how the request is made and hence can be easily tested without doing any http calls.

Most of the time you don't need to do this but if you want to make you controller shorter then just use service classes(or model or private/protected method in the controller) to hide your code from controller to somewhere else and don't separate the logic into many classes because as the project grows you will have hundreds of classes and it would be much harder to debug.

Moving logic into multiple place is always pain in the ass So if you want to do it, then do it properly, write tests for your classes so that you can find out if there is any problem more easily(but still you will struggle) .

And lastly for me, most of the time I use laravel for building api only and all the logic goes into controller or some service/helper class and yeah no tests(in general).

rakeshthapa
Автор

I am new to laravel. What is good practice for backend + blade components?

gamerneversleep
Автор

nice video, could you please explain, why ... controllers should be short ?

leostereo
Автор

Thank you, I love your videos. Can you please do a video on how to use both actions and service?

john.godstime