Conventions are patterns we or others have established as generally good ways of doing things. We save a lot of time when we reduce the amount of decisions we have to make and thought put into things by using conventions.
I stumbled upon Laravel early in my software career and every convention was better than what I was doing. And years later, those conventions still serve me well. Laravel was first to introduce me to the 7 resourceful routes convention.
If you're not familiar, this pattern is 7 endpoints you generally code for a "resource" to Create, Read, Update and Delete. Here is a table to illustrate a "Post" resource and the HTTP verbs following this convention:
Verb | URI | Action | Description |
---|---|---|---|
GET | /posts |
index | show list of posts |
GET | /posts/create |
create | show create form |
POST | /posts |
store | process create form |
GET | /posts/{id} |
show | display single post |
GET | /posts/{id}/edit |
edit | show edit form |
PUT/PATCH | /posts/{id} |
update | process edit form |
DELETE | /posts/{id} |
destroy | process delete request |
Following this convention has saved me so much time. Naming and structuring things can be a huge time eater. If the "resource" doesn't fit 100% into that convention, I usually can break out a new resource and continue the CRUD convention. Adam Wathan gave a great talk about this in Laracon 2017.
The Problem
The problem is DELETE. Every app I work on I spend time thinking of confirmations when allowing users to delete things. Each app has had slightly different UI approaches which can be a time eater because design is very subjective. So I wanted to explore this because again.. conventions save us time and I'm feeling some friction without a standardized approach.
The Missing Endpoint
What I have come to think is that maybe there is a missing endpoint in this convention and adding one might be the answer. What if the destroy action had a GET endpoint which could be used to display a confirmation page, accept a password confirmation, retrieve data related to the delete etc
Verb | URI | Action | Description |
---|---|---|---|
GET | /posts/{id}/delete |
remove | show delete confirmation |
DELETE | /posts/{id}/delete |
destroy | process delete request |
edit
-> update
| create
-> store
| remove
-> destroy
For such a small change, it really creates a positive impact. I have implemented this in a few projects and noticed the friction not only gone, but it cleans up my code quite a bit. Here are the benefits I noticed:
Benefits
- Link to the delete route from anywhere within or outside the codebase
- A dedicated endpoint if any data is needed to populate confirmation message: "you're about to delete 1,253 related records"
More thought
Both the store
and update
actions, (the other 2 endpoints that affect change in the database) have a corresponding GET route before performing the actions. This makes sense because they need an endpoint to accept inputs. But for sensitive data, so does destroy
.. a password confirmation.
Conclusion
Not every convention is going to work for everything, including this one. I think this idea has some benefits, but it really just depends about your project. I wrote this to just share an idea incase others share in my experience and want another convention to consider.
Let's connect on Twitter, I mostly tweet Laravel stuff.
Top comments (2)
Two thoughts on this. If you're going to do this, how about just using a delete endpoint and if a confirmation key isn't passed, you send back the message and a confirmation key, that way keeping the logic within a single endpoint.
Other thought though, is that this is properly the responsibility of the frontend. The api should assume an authorised client is doing what they want to to do. Otherwise, you might also want a confirmation on update, because that is deleting data as well. With frontend components, adding a confirmation dialog isn't laborious, can be done cleanly, and keeps your CRUD in line with standards.
Thanks for your opinions. Here are some thoughts.
edit
andcreate
aren't apart of API standards, so we are talking about slightly different things. Thestore
endpoint doesn't have aninputs
key to avoid acreate
endpoint and its main responsibility is returning a view / frontend. When presenting validation errors.. we do so oncreate
andedit
, so presenting a password mismatch error wouldn't make sense ondestroy
. It is common to have a password confirmation for destructive actions.. Amazon, Github, many apps do it. I do think this more closely matches the CRUD standards hence the presenting of my opinion :)