I have seen this being mentioned and that in several tuts, Jeffery Way talks about it on Laracasts, but I Must say. This is the best explanation and demo of this in action, with the comprehensive demo, it makes it easier to understand. Hat off to you Adam, another great explination :-)
Adam, just come back and watched this again, sometimes when you are live coding I find you get way too detailed, but this was really educational and gave me things to work on. I have been trying to do resource controllers for a little while but someof your refactoring was good incite and way to revisit things too, thank you.
As someone on stackoverflow once told me... "Don't forget the single responsibility principle. Each function needs a single responsibility, the same can be extended to views, routes etc. For example, you have a controller responsible for submissions and a function responsible for editing said submissions." en.wikipedia.org/wiki/Single-responsibility_principle
Thank you very much to make this talk available here. When I read about REST and about endpoints and all about that API driven design stuff I always end up banging my head thinking about how nested resources will work, what methods do I need, exactly like you pointed out. This way of thinking that everything is CRUD really makes sense to me and I will try to apply this in a project I have and yes it is a nightmare right now. The way you explain and show how it is done seems very easy to apply and I like the concept of changing the pivot table's name too. That I already do as it makes a lot more sense but I never thought about creating a separate Eloquent model, so thanks for that.
A very interesting talk and it also opens up so many possibilities as well. Like for instance - currently the subscription controller only has two methods - store and destroy. What if you want to see a list of podcasts you subscribe to. Then you can create a list in the subscription controller as well (maybe). And - so - much - more ...
before I watch this, I thought this is going to be repeated code and just a man who try the best for SOLID and some hell with the best practice but damn! this is gold, this is a killer design, especially the pivot naming xD
Great talk. Tip1: Nested Controller? New Controller. Tip2: Edited independently: New Controller => (Updating profile image separately). Tip3: Touches pivot records? New controller and probably a new model => Subscription/Unsubscription Tip4: Transitions state? New Controller => Publish/UnPublish
Great talk, I like that you're showing a lot of common scenarios. 1. How would you model a restore method for soft deletes as CRUD? 2. Let's say you're building a proposal software, how would you model sending a proposal as CRUD? (considering you can send it more than once, unlike publishing)
My guesses / what I would do after watching the talk: 1. DeletedPostsController with an update = restore, delete = permaDelete 2. Probably something like a ProposalDeliveryController with a create. The nice thing about this is that you could easily make a model associated and store records in the db of send times and destinations if you wanted to as well.
1. Soft deleting a record means that you have _updated_ a certain flag to hide the record from a particular scope. So use _update_ for soft deletes and _delete_ for permanent deletes. 2. If every time you send a proposal out, you _create a new record,_ it means that you will have to call a _create()_ on your controller. You can have _SendProposalController_ (or even _EmailProposalController_ which makes more sense if you are emailing them out).
Hi Adam. Great Video. I have a question, If you want to have the option to download the cover image of a podcast. Should I add the action in the PodcastCoverImageController? What should it be the name of that action? action "show"? thanks so much.
what if for example i want a function that downloads a pdf ? that's not exactly a create function, i would just create a FilesController and create a download function to be honest.
Perhaps it would be: Post: /pseudo-resource => PsuedoResourceBulkController Now you’ve set the scene for create update and delete pertaining to multiple records.
I always come back to this talk. I've built my apps using this technique and it works perfectly. Thank you for this. @adam if you ever read this, do you still use this technique?
but what if we submit the cover with the form data when we create a podcast, hmm how do we separate it to update route, when podcast hasn't been created yet, still so vague and u didn't mention it
you can do that by a separate Ajax call on your front end, uploading the image, returning its path, and then submitting it to the store route of your podcast .
Adam, do you think that the trick where you set an object as attribute should be part of Eloquent core? Or would it over complicate things? And nice presentation, as usually.
Great video. Did a lot of refactoring to my apps using your tips. But I was wondering, where do Single Action Controllers (invokable controllers) come into place?
Very interesting ! What if i have a "filter" method in a "PostController" ? Should i extract it to a "FilteredPostController" and rename it "index" in this logic ?
Most of the times, you should be able to add the filters as part of the index action. If it’s mandatory to have a separate endpoint for some reason, then yeah a FilteredPostController with an index method is a good way to go imo
@@BenGearig once I'm not delivering food, I will. I still deploy all my Laravel apps on Forge and purchased the TailwindUi package to support the man even on my limited budget. Does that count?
fine line and a little subjective - but - patch is partial update, put is replacing the whole object - so you could argue that since his 'resource' is a PodcastCoverImage, he is replacing the whole object and therefore a PUT should be used
Thanks for awesome talk. What if I want to call an api to check if current name of a user has been taken in the DB. What would be the best naming for that api end point? Is '/user/{name}/has-duplicate-name' ok?
in my mind this begs the question why not Route::get('/resource/create', CreateResource::class) and let the invoke take care of the create action and just have actions as classes... with one public method and whatever you need for private helpers... Why even have a "resource" controller? I like this talk and the ideas in it... it certainly cleans things up but why not just take it to the extreme and make everything super-specialized...
Nice talk, even so I would disagree with the subscriptions and published podcasts resources. For me it would be /podcasts/{id}/subscription and /podcasts/{id}/publication and I don't have to pass the podcast id via the request body. I moves related stuff a lot more together.
This talk is legendary, I come back once in a while to experience it again
Literally went to the comments to say the exact same thing.
Literally I am doing the same right now
I have seen this being mentioned and that in several tuts, Jeffery Way talks about it on Laracasts, but I Must say.
This is the best explanation and demo of this in action, with the comprehensive demo, it makes it easier to understand. Hat off to you Adam, another great explination :-)
I dont even do Laravel, but this is so important
16:35 "it doesn't matter, because we're not gonna run this code" - 😂
That is the one technical knowledge sharing session about design patterns that worth priceless value.
Amazing talk man! You totally inspired me to instantly get out of bed and go refactor! :)
Adam, just come back and watched this again, sometimes when you are live coding I find you get way too detailed, but this was really educational and gave me things to work on. I have been trying to do resource controllers for a little while but someof your refactoring was good incite and way to revisit things too, thank you.
Yooo... that mutator trick in the pivot model is pure gold! 😳😃
Simple, clean, and consistent. Excellent talk!
Amazing presentation. api.php, here I come. Some housekeeping is in order.
Nice and simple approach! Will use "cruddy by design" in future projects.
Among all other things, I learned that you can use spotlight search as a calculator directly. 😀. Great talk. Going to try this.
2:51 "Building Interfaces with Utility-First CSS"
Quite the foreshadowing here
Awesome talk, as always! Love your job and is really inspirational. Greetings from Chile, Adam!
As someone on stackoverflow once told me...
"Don't forget the single responsibility principle. Each function needs a single responsibility, the same can be extended to views, routes etc. For example, you have a controller responsible for submissions and a function responsible for editing said submissions."
en.wikipedia.org/wiki/Single-responsibility_principle
FInally!
Was waiting patiently for this.
Thanks Adam
Thank you very much to make this talk available here.
When I read about REST and about endpoints and all about that API driven design stuff I always end up banging my head thinking about how nested resources will work, what methods do I need, exactly like you pointed out.
This way of thinking that everything is CRUD really makes sense to me and I will try to apply this in a project I have and yes it is a nightmare right now.
The way you explain and show how it is done seems very easy to apply and I like the concept of changing the pivot table's name too. That I already do as it makes a lot more sense but I never thought about creating a separate Eloquent model, so thanks for that.
A very interesting talk and it also opens up so many possibilities as well. Like for instance - currently the subscription controller only has two methods - store and destroy. What if you want to see a list of podcasts you subscribe to. Then you can create a list in the subscription controller as well (maybe). And - so - much - more ...
The ever best inspiration to create more controllers as it costs nothing.
This presentation is amazing!!
before I watch this, I thought this is going to be repeated code and just a man who try the best for SOLID and some hell with the best practice but damn!
this is gold, this is a killer design, especially the pivot naming xD
1. Nested Resource? 00:00 - 12:53
2. Edited Independently? 12:54 - 17:10
3. Touches Pivot Record? Eg.: "What do I have now that I didn’t have before?" 17:11 - 24:49
4. Transitions State? 24:50 - 36:21
thanks much. Your comment should be pinned on top so that people can easily navigate through the video.
Great talk.
Tip1: Nested Controller? New Controller.
Tip2: Edited independently: New Controller => (Updating profile image separately).
Tip3: Touches pivot records? New controller and probably a new model => Subscription/Unsubscription
Tip4: Transitions state? New Controller => Publish/UnPublish
Thank you Adam, you are always teaching me new lessons
Brilliant work. Thanks for this!
Such a great presentation!
Great work Adam
I needed to see this! Awesome
Man, I need to either switch to Sublime or step up my shortcut game.
and as a Vim user, watching this makes me so glad I don't use Sublime. It's hard to watch somebody stumbling around so inefficiently...
@@jackiemulsons What
@@jackiemulsons ja precies. 😂
Great Talk! Makes so much sense!
Great talk, I like that you're showing a lot of common scenarios.
1. How would you model a restore method for soft deletes as CRUD?
2. Let's say you're building a proposal software, how would you model sending a proposal as CRUD? (considering you can send it more than once, unlike publishing)
My guesses / what I would do after watching the talk:
1. DeletedPostsController with an update = restore, delete = permaDelete
2. Probably something like a ProposalDeliveryController with a create. The nice thing about this is that you could easily make a model associated and store records in the db of send times and destinations if you wanted to as well.
1. Soft deleting a record means that you have _updated_ a certain flag to hide the record from a particular scope. So use _update_ for soft deletes and _delete_ for permanent deletes.
2. If every time you send a proposal out, you _create a new record,_ it means that you will have to call a _create()_ on your controller. You can have _SendProposalController_ (or even _EmailProposalController_ which makes more sense if you are emailing them out).
Funny how there's a manhole in the middle of the stage
What is the cruddy way to store / update / destroy multiple records at once?
I was wondering the same thing
Is there a Laravel/PHP equivalent to the rails stats that DHH uses to grab the Controller count? I was trying to find something to run on my code.
twitter.com/adamwathan/status/917082844001964039
Awesome presentation. Learnt something valuable :)
Excellent talk! Thank you!
Hi Adam. Great Video. I have a question, If you want to have the option to download the cover image of a podcast. Should I add the action in the PodcastCoverImageController? What should it be the name of that action? action "show"? thanks so much.
I actually downloaded and stored this because I'm afraid it's gonna be taken out of internet one day and I won't be able to go back to it and re watch
what if for example i want a function that downloads a pdf ? that's not exactly a create function, i would just create a FilesController and create a download function to be honest.
Amazing, i've learnt a lot
any suggestions on what the 'pseudo' resource and request urls could be for bulk actions?
Perhaps it would be:
Post: /pseudo-resource => PsuedoResourceBulkController
Now you’ve set the scene for create update and delete pertaining to multiple records.
wow, that was great explaination
What if I need to generate multiple tickets for a concert? Where does it go? Also, what if I need to validate a voucher validity?
@TheGkmasta And what is the controller method for voucher validity?
Hi, Thank you for this video. I just want to ask how are you going to group these controllers? is it by modules?
I always come back to this talk. I've built my apps using this technique and it works perfectly. Thank you for this.
@adam if you ever read this, do you still use this technique?
That's awesome, glad to hear that! I definitely do, it's really nice to have a system for thinking about routes and controllers.
Thank you! Keep up the great work.
PS. Tailwind is awesome too!
This is a light bulb moment for me 🙏
Re-watching again in 2021
Same here.
Great talk!
but what if we submit the cover with the form data when we create a podcast, hmm how do we separate it to update route, when podcast hasn't been created yet, still so vague and u didn't mention it
you can do that by a separate Ajax call on your front end, uploading the image, returning its path, and then submitting it to
the store route of your podcast
.
if you have the logic for an action button like clear cache,
where, if not the controller, do you put it?
I learned a lot!
thanks a lot, give me a different world
Adam, do you think that the trick where you set an object as attribute should be part of Eloquent core? Or would it over complicate things? And nice presentation, as usually.
Great video. Did a lot of refactoring to my apps using your tips. But I was wondering, where do Single Action Controllers (invokable controllers) come into place?
Invokable controllers needs no refactor
LEGEND
Great talk. Thanks.
Valuable .... content..
Looks great, but I'm wondering if this is still valid in 2024?
This makes so much sense
Eres un genio! ;)
Very interesting ! What if i have a "filter" method in a "PostController" ? Should i extract it to a "FilteredPostController" and rename it "index" in this logic ?
Most of the times, you should be able to add the filters as part of the index action. If it’s mandatory to have a separate endpoint for some reason, then yeah a FilteredPostController with an index method is a good way to go imo
Just Wow!!
Great explanation
This! No more 10-20 action controllers!
great talk. How would you design an endpoint for search a resource though?
passing get parameters on the /index method should be fine, shouldn't it?
Very interesting
This was worth $1000
@@BenGearig once I'm not delivering food, I will. I still deploy all my Laravel apps on Forge and purchased the TailwindUi package to support the man even on my limited budget. Does that count?
Holy line-height batman
6*
An controller with 1 action only shouldn't have just __invoke()? @Adam
why would it? by using invoke, you let nobody know what the intention of said method is. Destroy? store?
@@Jossnaz now I don't remember my use case for this question :/
👍👍
It should be use PATCH instead of PUT method when update cover image.
what's the difference between PUT and PATCH?
fine line and a little subjective - but - patch is partial update, put is replacing the whole object - so you could argue that since his 'resource' is a PodcastCoverImage, he is replacing the whole object and therefore a PUT should be used
@@rizaldywirawan PUT when updating the whole object, PATCH when updating only parts of it, like "upddated_at" or "status", etc..
Thanks for awesome talk.
What if I want to call an api to check if current name of a user has been taken in the DB.
What would be the best naming for that api end point?
Is '/user/{name}/has-duplicate-name' ok?
in my mind this begs the question why not Route::get('/resource/create', CreateResource::class) and let the invoke take care of the create action and just have actions as classes... with one public method and whatever you need for private helpers... Why even have a "resource" controller? I like this talk and the ideas in it... it certainly cleans things up but why not just take it to the extreme and make everything super-specialized...
This guy gives me some Joe Rogan vibes, great presentation
NWA
Nice talk, even so I would disagree with the subscriptions and published podcasts resources. For me it would be /podcasts/{id}/subscription and /podcasts/{id}/publication and I don't have to pass the podcast id via the request body. I moves related stuff a lot more together.