Dessert #1 - The 7 crucials of CRUD
Posted by Felix Geisendörfer, on Sep 14, 2006 - in PHP & CakePHP » Controllers, Components & Shells
Deprecated post
The authors of this post have marked it as deprecated. This means the information displayed is most likely outdated, inaccurate, boring or a combination of all three.
Policy: We never delete deprecated posts, but they are not listed in our categories or show up in the search anymore.
Comments: You can continue to leave comments on this post, but please consult Google or our search first if you want to get an answer ; ).
Update: I changed the functions new_one and create to create and save based on Daniel's suggestion in the comments. However I still would love the ability to use new & create but since new can't be used (it's a php keyword), this seems like a good workaround.
When you've worked with CakePHP you might have heard about CRUD before (Create, Read, Update, Delete) which is a pattern used in the database world which translates well into controller actions. Now so usally you would use 5 functions (create, edit, view, delete, + index). And while this isn't a bad idea, you always end up with a couple if statements where you check whether the user already posted some data to Posts::create() or whether he just requests it via GET in order to start writing a new Post.
For that reason, a nice simplification can be achieved by using 7 functions instead of 5. The example below shows you how those additional actions could look like and what should be done inside of them.
-
class PostsController extends AppController
-
{
-
var $name = "Posts";
-
-
function index() // GET
-
{
-
// Prepare the overview of all posts,
-
// Usally you'll do something like: $this->set('posts', $this->Post->findAll());
-
}
-
-
function create() // GET
-
{
-
// Here goes everything you need to prepare an empty form for you Post
-
// to be filled out
-
-
// If you don't want to write the template for editing a post twice (for create
-
// and edit), just put a $this->render('edit'); at the end of this function.
-
}
-
-
function save() // POST
-
{
-
// This function interacts with your Model ( $this->Posts ) in order to bring
-
// $this->data['Post'] into your database
-
-
// After it you can call $this->edit($this->Post->getLastInsertID()) in order to
-
// display the edit box again if you want the User to continue editing
-
}
-
-
function show($id) // GET
-
{
-
// This function shows a Post with a given $id
-
}
-
-
function edit($id) // GET
-
{
-
// This function reads the Post with $id from your database and prepares all
-
// data for the View to display an edit form for it.
-
}
-
-
function update() // POST
-
{
-
// This function takes care of updating the post contained in $this->data['Post']
-
// in the database.
-
-
// Like with create, you can call $this->edit($this->data['Post']['id']); at the
-
// end of this function to let the user continue editing the Post.
-
}
-
-
function destroy($id) // GET
-
{
-
// This function destroys the Post a given $id
-
}
-
}
Alright, I might end up posting two desserts today. Since I've been getting up at 5 am every morning I am actually able to post on here before I go to school. Ok, I didn't write something insanly exiting, but it's a start ; ).
--Felix Geisendörfer aka the_undefined
7 Comments
I've always used:
add => create
edit => update
delete => destroy
It makes for code which is easier to read and maintain.
Your "new_one" function sounds a bit ugly. I would name it "create" and rename the function you named "create" to "save". What do you think about it?
You can actually combine several of those with a simple if (!empty($this->data)) { ...
For example:
function edit ($id) {
if (!empty($this->data)) {
$this->Model->id = $id;
if ($this->Model->save($this->data)) {
// Redirect with flash message
}
} else {
$this->data = $this->Model->read(null, $id);
}
}
could replace edit and update. Likewise for create and new_one.
Great post!
To follow up on what Nate said, you could also combine add and edit (or new_one and edit) into the same function like this:
function edit($id=null)
{
if (isset($id))
{
// Get data from model
// render edit
}
else
{
// render add
}
}
I think Felix already explained why he uses 7 functions instead of 5, he does that to eliminate the if statements. I think this approach is very usefull when it comes to build some API or when you have to create an web wizard.
Daniel Hofstetter: I think that's a good idea. I went almost nuts this morning trying to find a replacment for "new". This sounds like a reasonable workaround.
Lucian: Yes, that's what I was talking about. The if statements are nice and everything, however, this approach is useful if all those actions use different views since a 1:1 relationship between actions and views takes away some complexity. And of course for things like building API's just like you said.



So you suggest having a form which redirect the user from /new_one to /create or so? That approach is really nice I think, but nevertheless the method name "new_one" doesn't sound that great in my opinion.
But whatever, it's only an example, so getting the idea is no problem now and it might be useful.