Laravel Controller: Move Logic to Action or Service Class

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello guys today i will give you an example of refactoring the api controller into some other layer to make the controller shorter and there are different ways how to separate that into what structure into what class a popular way is to create a service class another popular way is to create a job but pretty recently it became popular to create the action class action is almost the same as the job with kind of philosophical difference that job may be put into queue and this is often used directly for the queue so queueable jobs an action is just a one-time thing without any queue it's just a separate class that can be type hinted here in the controller so in this video let's do exactly that and this is partially based on a pull request on this api challenge that i did pretty recently and lars brinkman suggested his own version with store voice action class so i will link to that pull request in the description below but i didn't take exactly that because it seemed over complicated to me with a lot of actions that were not really mentioned in this task so i will just do another version of the same refactoring to actions so our goal is to shorten this controller it's a 30 lines of code or something like that which has a lot of logic and in theory controller should not have a lot of logic it should be moved somewhere else and controller should be just the bridge between like routes and logic and views right and there are quite a lot of things happening here so we post the voice or vote to the question we check if the question is not from the same user then we try to create the vote or the voice then we check if it was created or not if it's not created then it may be updated but then we check if it's the same value then we don't allow to update otherwise we do update and return response json with status 201 in reality it should be something like this so let's imagine we have a class of action some action class then we call some method of handle which does all the job for us and we just passed the request so this one and then based on that action for example that action should return the voice the result of that vote or voice and then based on that return voice for example if the voice was successfully created was recently created then we return one thing otherwise we return another thing so controller is only responsible for the returning of the result so if it was recently created the eloquent model then we return this with status 200 otherwise if it was updated we return this one so only this part is left in the controller the returning of the result and everything else is offloaded to this action class which we haven't created yet but i will do that in a minute and that action class will take care of all the validation of all the abort happenings if there is some kind of exception and if it returns successful result then we will return the result from our api so now let's create that action class there is no command of php autism make class or make action so we need to do that manually in my php storm i do new file actions which will create a subfolder store voice action for example php it's an empty file so php then namespace of app actions and then class store voice action with one method handle public function handle with the parameter of store voice request request it's automatically added by my php storm and it should return the voice object so model of the voice cool it's empty for now so no content and let's type hinted into the controller so in addition to the request we add store voice action action and laravel will automatically resolve that and we'll call that class and now as you can see that action isn't underlined anymore by my php storm and it calls that handle function now let's fill it in with the details and our details should come from the controller so we basically copy and paste or cut and paste everything from here so this will be just our controller with a few lines of code and we paste everything here import the model that phpstorm suggests and we basically do the same thing so we have the same request parameter and we do all of those actions except that we don't need to return these so we don't need to return this or return that so this return is totally irrelevant and here we return voice and in here if voice was recently created we also return voice and how we test if it all works i have a suite of automated tests so voices test testing all the cases of that controller if you want more details on that one i will link to the previous video where i discuss all that solution in this video i just want to show refactoring two actions with not changing the code or almost not changing the code and let's just undo and try to run the suite of tests before that change right so we comment this out for now and we'll leave the old code for now store voice action is not really getting in our way so we can leave it here and if we run php autism test php autism test those tests should be green so i have six tests for various situations in that controller and now if we undo this one and comment that one or actually delete that one let's rerun the tests and it's all still green so it didn't really break anything it's all happening inside of the action if something goes wrong within the action it aborts with 500 or with whatever status code and the controller is just responsible of successfully returning the result now of course there are multiple ways how you can do that differently so for example in the action instead of doing a board you could throw an exception and then in the controller you can do try catch and catch all of the possible exceptions but then it kind of beats the purpose of shortening the controller because then the try catch thing would be as long as putting the same logic in the controller so i'm not sure about that particularly in this case also as i mentioned it's not only action that you can do you can do that as a service so as an example as a quick experiment let's just file save as the same action class to app services with store or actually voice a service let's call it voices service class and we will rename that class to voices service with different name space of app services and now we can call from the controller voices service voices service service for example and then instead of action handle you would have service handle request in most typical case the service is around some kind of entity like voices so it wouldn't be just handle it would be more like store voice or voice store something like that and then there will be more methods inside of one service so action is mostly one method action like a job with handle method or whatever you call that and for the service you just have multiple methods and even more than that with the request you probably pass the exact parameters to the service method so service wouldn't know anything about requests service is kind of like a black box to perform the action so what we have instead of parameters instead of request we have question id i see we have value request post value actually two things only so question id and value and then inside of that post service so request question id and request value or sorry i've deleted unintentionally so question id and value and then in the service we just remove those request calls and let's see where else okay request post question id so quick experiment post value so value should be here and also here request post value should be value and also finally here and we will relaunch the tests to see if we didn't break anything so instead of action we are now calling the service and our tests we refresh them and it's still green it's all successful so this is a quick way how you can use services it's almost the same as action it's mostly again a philosophical difference action is one time class with one method with quick execution service is for if i have more methods around voices like update voice or check something there would be service around that and one of the method would be service store what do you think about these examples maybe i missed something again there are multiple ways how you can do in web development almost anything so shoot the comments below if you have anything to add or to fix me and if you want more videos like this one subscribe to the channel and also support my channel financially to allow me to shoot these daily videos on youtube by purchasing one of the three products that you can see on the screen right now that's it for this time and see you guys in other videos
Info
Channel: Laravel Daily
Views: 34,710
Rating: undefined out of 5
Keywords:
Id: 8DBMRByJUmU
Channel Id: undefined
Length: 10min 5sec (605 seconds)
Published: Wed Aug 04 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.