Simple CRUD With CodeIgniter
Last week we took a look at an introduction to the CodeIgniter PHP framework. In that example we saw the basics of how CodeIgniter works and the basics of the MVC pattern. But we didn't really do much with models. Today we will look at the power of models in CodeIgniter to make CRUD functions easy.
CRUD stands for create, read, update and delete, which are some of the most basic functions that can be done with data storage. In this tutorial we will be applying CRUD to a MySQL database. We will take a look at the database libraries included in CodeIgniter to ease work with databases, and other included libraries to help out with development as well.
If you haven't yet, you may want to read through An Introduction to CodeIgniter first, so that you at least know the basics of CodeIgniter.
Getting Started
The first thing you should do is setup a database on your server. For the purposes of this tutorial, I will be calling mine "ci". Once that is created, execute the following SQL query to create a simple table.
CREATE TABLE posts ( id INTEGER AUTO_INCREMENT PRIMARY KEY, title TEXT, content TEXT );
Next, we need to do a bit of configuration. Open up config/database.php in your favourite text editor and change the following values to match your database configuration.
$db['default']['hostname'] = "localhost"; $db['default']['username'] = "MySQL Username"; $db['default']['password'] = "MySQL Password"; $db['default']['database'] = "ci";
Next open up config/autoload.php. This file contains the systems to be loaded by default. Change the autoloaded libraries (around line 42) to this:
$autoload['libraries'] = array('database');
We are autoloading the database library because we will be using it a lot throughout this tutorial.
Create
Let's get started by creating new records. First, create a new controller called crud.php. Inside of that file, type in the following code.
class Crud extends Controller { function index() { // Check if form is submitted if ($this->input->post('submit')) { $title = $this->input->xss_clean($this->input->post('title')); $content = $this->input->xss_clean($this->input->post('content')); // Add the post $this->posts_model->addPost($title, $content); } $this->load->view('crud_view'); } }
When the index function of our crud controller is called, it first checks if the form, which we will create, has been submitted. Next the input is run through an XSS filter for security purposes, and then added to the database through a function we will create.
Finally, a view will be loaded to display the form, and later, the posts.
The Model
Models are used in the MVC pattern for working with data. In CodeIgniter they are located in the models directory. Create a new model called posts_model.php. Type the following code inside it.
class Posts_model extends Model { function addPost($title, $content) { $data = array( 'title' => $title, 'content' => $content ); $this->db->insert('posts', $data); } }
This is a very simple example. Our model class, called Posts_model contains a function called addPost, which can be used with two parameters for the title and the content of the post. An array called $data is created which stores the values. Finally the data is inserted into the database using a function included in the database library, which we automatically loaded.
Creating The Form
For our form will be using a view. Create a new view called crud_view.php.
To build the form, we will use the form helper, which is a library included in CodeIgniter to help make building forms easier. Using the form helper, here is the code to create our form.
<?php $this->load->helper('form'); ?> <?php echo form_open('crud'); ?> <p> <?php echo form_input('title'); ?> </p> <p> <?php echo form_textarea('content'); ?> </p> <p> <?php echo form_submit('submit', 'Submit'); ?> </p> <?php echo form_close(); ?>
Now you can test it out. Point your browser to index.php/crud/ and try filling out the form. Check the database in phpMyAdmin (or whatever you use). If everything went well, there should be some new rows in the table. If it works, we can continue to the next part!
Read
Reading from the database is still very simple in CodeIgniter, but a bit more complicated than inserting. Inside of our model, add in this new function:
function getPosts() { $query = $this->db->get('posts'); $posts = array(); foreach ($query->result() as $row) { $posts[] = array( 'id' => $row->id, 'title' => $row->title, 'content' => $row->content ); } return $posts; }
This function first creates a query that gets all of the rows from the posts table of the database. Using a foreach statement, it loops through all of the rows to create an array. When that is finished, the function returns an array of all the posts.
Next, inside our controller, inside the index function, delete the line that loads the view, and add in the following lines of code in its place.
$data = array(); $data['posts'] = $this->posts_model->getPosts(); $this->load->view('crud_view', $data);
The variable $data is declared as an array. Then an array inside of $data contains all of our posts, using our getPosts function. And then it loads the view again, this time passing in the $data variable, now containing all of our posts.
Next we are going to display all of the posts to the user. Because we passed them in to the view, we just need to add a few lines to the view, below the form, to get it to display the posts.
<?php if (isset($posts)): foreach ($posts as $p): ?> <h2><?php echo $p['title']; ?></h2> <?php echo $p['content']; ?> <?php endforeach; else: ?> <h2>No posts found</h2> <?php endif; ?>
This first checks if there are any posts to display. If there are, it simply loops through each of them, displaying the title and the content for each of them. If there are no posts to show the user, it shows them a very informative message.
Update
To update data in the database, first add a new function to our model.
function updatePost($id, $title, $content) { $data = array( 'title' => $title, 'content' => $content ); $this->db->where('id', $id); $this->db->update('posts', $data); }
Our new function, updatePost, accepts three parameters, for the id of the post to update, the new title of the post, and the updated content.
$data is an array that stores the title and content. Next a function included in CodeIgniter's database library tells the next SQL query where the row should be updated. In this case it is where the id field of the table is equal to $id. And lastly, the update function is called, which updates the posts database table with the information supplied.
A new form needs to be created to be able to update the post. Create a new view called updateform.php and type in the following code which makes use of CodeIgniter's form helper.
<?php $this->load->helper('form'); ?> <h1>CodeIgniter CRUD Tutorial Example</h1> <?php echo form_open('crud/update/'.$id); ?> <p> <?php echo form_input('title'); ?> </p> <p> <?php echo form_textarea('content'); ?> </p> <p> <?php echo form_submit('submit', 'Submit'); ?> </p> <?php echo form_close(); ?>
A new function also needs to be added to the controller for this to work.
function update() { $id = $this->uri->segment(3); if ($this->input->post('submit')) { $title = $this->input->xss_clean($this->input->post('title')); $content = $this->input->xss_clean($this->input->post('content')); $this->posts_model->updatePost($id, $title, $content); $data['posts'] = $this->posts_model->getPosts(); $this->load->view('crud_view', $data); } else { $data = array('id' => $id); $this->load->view('updateform', $data); } }
As you can probably tell, this function is very similar to the one to add posts. However this one deals with URI segments. A segment is just a part of a URI, which contains a certain value. Here we use the third segment of the URI, which contains the ID of the post to update.
If the form has been submitted, the title and content are run through an XSS filter again, and the post is updated. It also retrieves all of the posts and passes them into the crud_view view, which is loaded after a post has been updated.
If the form has not been submitted, the form is loaded, with the ID of the post passed in, as it is used in the form.
To test this out, point your browser to index.php/crud/update/YourID, replacing YourID with the ID of the post you would like to update.
Delete
We will finish off this tutorial with Delete, which uses some very simple functions. Create one last function inside of our model.
function deletePost($id) { $this->db->where('id', $id); $this->db->delete('posts'); }
That's really all there is to it. The where function is used just like in the "update" function, to indicate which rows will be affected. And then the next statement which simply deletes that row.
Another simple function must be added to our controller, this one called delete.
function delete() { $id = $this->uri->segment(3); $this->posts_model->deletePost($id); $data['posts'] = $this->posts_model->getPosts(); $this->load->view('crud_view', $data); }
This, again, gets the ID of the post to delete from the third segment of the URI. The our deletePost function is called to delete the post with that ID. All of the posts are then retrieved, and displayed to the user through the crud_view view.
To do simple CRUD functions with CodeIgniter, it is really a very simple task. If you have any questions, or if somehow, something doesn't work for you, be sure to leave a comment and I will do my best to help you out.
Also, be sure to subscribe to the RSS feed or for email updates, because now that we know the basics of CodeIgniter, I will start posting a series of posts on something more useful, creating a simple website using CodeIgniter.
cool, I LOVE CodeIgniter, but all of us who are really developing in it are using Smarty, so feel free to show us some Smarty implementation while you're there ;)
cheers,
dootzky
[duneprog]
Why use smarty when php based templates are even better!? Your code should not be mixed with your presentation layer and although smarty is very powerful php is by far much better. Please don't get me wrong. I worked with Smarty for about 2 years under xoops and found it a great help at times but most of the times was useless. PHP gives a flexibility that smarty cannot reach yet.
In your readPosts why did you duplicate the data. You could of just returned $query->result() instead of running it through a foreach in the model? You are basically running two loops for one set of data.
You're right, I probably could have returned $query->result(), and then used the objects to display the results.
I actually only just discovered the result_array() function which would automatically generate an array, so that we wouldn't have to update the view. So in the following tutorials, I'm going to have to make sure to use either one or the other.
I actually prefer to use objects over an array. Its what a lot of other programming languages do.
I agree, would be one less function call. Also, objects are just as easy to enumerate over.
Nice Tut, keep'em coming!
TY
I have a similar delete() function in one of my controllers. I have a link to it in my view and JS hooked up to it to display a confirm dialog. However, if the function is called directly by typing the URL into the browser, the record deletes without warning. Is there some way to write the function in the controller or model to prevent this?
You can add a form with only a submit button that adds a POST value once submitted, and make it so that the page is only deleted once the button has been clicked.
You can check in the controller action if any post data has been sent or in the action is being called through Ajax.That way you don't get direct access to the action. I believe CI disables $_GET so don't bother to check for it.
When I tried the example I got an error saying posts_model was null... I was able to work around it by adding the following:
$retval = $this->load->model('Posts_model');Am I missing something here?
Got the same problem, but haven't solved it yet.. can anyone tell me what's missing? Can add that I'm really new to CI.
Very good tutorial. I wish I could have found this when I was learning CI. Keep in mind that the Database class for CI has tons of features that's always good to keep in handy, this was my best mate in my old days: http://codeigniter.com/user_guide/general/quick_reference.html
Thanks for linking to that. It looks like it would make a very useful reference!
Just a small suggestion, you can pass variables through XSS clean, just by passing TRUE into the input get method:
$title = $this->input->post('title', TRUE); // this will be XSS cleaned
That's a great idea! Thanks for the suggestion.
You could have done something like:
$this->input->post('title',TRUE);
It runs XSS filter over the field, which is the same as:
$title = $this->input->xss_clean($this->input->post('title'));
=)
That's a great idea! Thanks for the suggestion. (Like the comment above you, but you couldn't have seen that :))
Why use smarty when php based templates are even better!? Your code should not be mixed with your presentation layer and although smarty is very powerful php is by far much better. Please don't get me wrong. I worked with Smarty for about 2 years under xoops and found it a great help at times but most of the times was useless. PHP gives a flexibility that smarty cannot reach yet.
In Crud controller why not do:
$p = $this->input->post;
foreach($p as $k=>$v) ${$k} = $p($k, true);
$this->posts_model->addPost($title, $content);
Every CRUD app I look at, makes me want to CRAP. If you have 20 or 30 posted fields, please don't tell me you write it all out a la:
$blah = $this->input->xss_clean($this->input->post('blah'));
Same goes for validation, Rails, Django, CI, Cake, etc., all tons of typing.
If only Drupal were PHP 5.3 OO I would actually break away from my framework; at least you can crank out content at a ridiculous pace in Drupal (customizing, another matter)
Apologies if coming down on CI, have heard/read good things, just my search for the barebones ORM-FormGenerator/Validator-CRUD framework has been for naught thus far...
Hello any body guide me for code igniter frame work,I because i am in some error using the frame work...error is Call to a member function updatePost() on a non-object
Well I might not be able to say exactly what is causing your problem, but by the looks of the error message, you're trying to do something like
$something->updatePost(), where either $something's class doesn't contain a function called updatePost(), or where $something isn't even an object.Given the error message, it's most likely the latter. Like I said, I don't know where exactly the error could come from, but this should help you to start your search to find the bug :)
Very good article however, on the update form if you put the submission URL to something like 'posts/update/$id', form_validation won't work as you expect.
I've run into problems with this before - as form_validation links to the form by the form_open('posts/update'); function, so if it ended up being form_open('posts/update/1'), for example, form validation would fail.
The solution to this would be to use form_hidden('update_id', $id) to have a hidden form element with the ID to update.
Hope this makes sense. :)
Very good article! It worked properly. Thanks!