CI Models – Tutorial

Why I Copy other People’s Writings

In the last section, we went over some basic concepts of the framework by writing a class that includes static pages. We cleaned up the URI by adding custom routing rules. Now it’s time to introduce dynamic content and start using a database.

Setting up your model

Instead of writing database operations right in the controller, queries should be placed in a model, so they can easily be reused later. Models are the place where you retrieve, insert, and update information in your database or other data stores. They represent your data.

Okay! Where is the author going with this. He has a controller for News with two methods—one for displaying all the news; and, one for displaying a single news item. The parameter is a slug for a news items. What purpose does this model code serve? It will retrieve the news data from the database. Then the data will be passed on as strings to the view.

Open up the application/models directory and create a new file called news_model.php and add the following code. Make sure you’ve configured your database properly as described in the User Guide.

<?php
class News_model extends CI_Model {

	public function __construct()
	{
		$this->load->database();
	}
}

I think load is a property (variable) of the model which points to an object. That later object is the same one pointed to by load in the controller.

This code looks similar to the controller code that was used earlier. It creates a new model by extending CI_Model and loads the database library. This will make the database class available through the $this->db object.

I think it creates some variables (which hold data from the database) and functions which end up being used by this->db.

Before querying the database, a database schema has to be created. Connect to your database and run the SQL command below. Also add some seed records.

CREATE TABLE news (
	id int(11) NOT NULL AUTO_INCREMENT,
	title varchar(128) NOT NULL,
	slug varchar(128) NOT NULL,
	text text NOT NULL,
	PRIMARY KEY (id),
	KEY slug (slug)
);

Now that the database and a model have been set up, you’ll need a method to get all of our posts from our database. To do this, the database abstraction layer that is included with CodeIgniter — Active Record — is used. This makes it possible to write your ‘queries’ once and make them work on all supported database systems. Add the following code to your model.

Read it’s description first.

public function get_news($slug = FALSE)
{
	if ($slug === FALSE)
	{
		$query = $this->db->get('news');
		return $query->result_array();
	}
	
	$query = $this->db->get_where('news', array('slug' => $slug));
	return $query->row_array();
}

Apparently the get() and get_where() methods return an object which is loaded with the query result (or handles the failure of the query.) On this object you can run a result_array() or row_array() method to capture the returned data set as an array.

With this code you can perform two different queries. You can get all news records, or get a news item by its slug. You might have noticed that the $slug variable wasn’t sanitized before running the query; Active Record does this for you.

Display the news

Now that the queries are written, the model should be tied to the views that are going to display the news items to the user. This could be done in our pages controller created earlier, but for the sake of clarity, a new “news” controller is defined. Create the new controller at application/controllers/news.php.

<?php
class News extends CI_Controller {

	public function __construct()
	{
		parent::__construct();
		$this->load->model('news_model');
	}

	public function index()
	{
		$data['news'] = $this->news_model->get_news();
	}

	public function view($slug)
	{
		$data['news'] = $this->news_model->get_news($slug);
	}
}

I’ve noticed that the load object has methods: view(), database() and model(). When load->database() is called then $this acquires a db property pointing to a db object. When load->model() is called then $this acquires a property with the same name as the parameter for model() method. When load->view() is called then output is sent to the user’s browser.

It is amazing that PHP can do this. I’d like to see how this stuff is coded in the framework to pull it off. The load object has methods which are able to add properties to other objects.

Looking at the code, you may see some similarity with the files we created earlier. First, the “__construct” method: it calls the constructor of its parent class (CI_Controller) and loads the model, so it can be used in all other methods in this controller.

Next, there are two methods to view all news items and one for a specific news item. You can see that the $slug variable is passed to the model’s method in the second method. The model is using this slug to identify the news item to be returned.

Now the data is retrieved by the controller through our model, but nothing is displayed yet. The next thing to do is passing this data to the views.

public function index()
{
	$data['news'] = $this->news_model->get_news();
	$data['title'] = 'News archive';

	$this->load->view('templates/header', $data);
	$this->load->view('news/index', $data);
	$this->load->view('templates/footer');
}

The code above gets all news records from the model and assigns it to a variable. The value for the title is also assigned to the $data['title'] element and all data is passed to the views. You now need to create a view to render the news items. Create application/views/news/index.php and add the next piece of code.

<?php foreach ($news as $news_item): ?>

    <h2><?php echo $news_item['title'] ?></h2>
    <div id="main">
        <?php echo $news_item['text'] ?>
    </div>
    <p><a href="news/<?php echo $news_item['slug'] ?>">View article</a></p>

<?php endforeach ?>

That is one weird piece of code! I’m not used to working with PHP mixed in with HTML; But, this seams to not follow the PHP rules which I’ve studied. I wonder if this code is being preprocessed by CI before it goes to the PHP interpreter. One weird thing is the flow of code execution. Another, is the syntax of foreach.


X-Reference: Syntax for Embedded PHP


Also, take note of the way the hyperlink’s relative URL was specified. It shows that—when relative URLs are used in the formation of a hyperlink—the browser prepends the URL of the current page (up to /index.php/) to the relative URI—because, this is perceived to be the path to the current directory: http://sameh-labibs-imac.local/CodeIgniter_2.1.0/index.php/news

Here, each news item is looped and displayed to the user. You can see we wrote our template in PHP mixed with HTML. If you prefer to use a template language, you can use CodeIgniter’s Template Parser class or a third party parser.

The news overview page is now done, but a page to display individual news items is still absent. The model created earlier is made in such way that it can easily be used for this functionality. You only need to add some code to the controller and create a new view. Go back to the news controller and add the following lines to the file.

public function view($slug)
{
	$data['news_item'] = $this->news_model->get_news($slug);

	if (empty($data['news_item']))
	{
		show_404();
	}

	$data['title'] = $data['news_item']['title'];

	$this->load->view('templates/header', $data);
	$this->load->view('news/view', $data);
	$this->load->view('templates/footer');
}

Instead of calling the get_news() method without a parameter, the $slug variable is passed, so it will return the specific news item. The only things left to do is create the corresponding view at application/views/news/view.php. Put the following code in this file.

<?php
echo '<h2>'.$news_item['title'].'</h2>';
echo $news_item['text'];

Routing

Because of the wildcard routing rule created earlier, you need need an extra route to view the controller that you just made. Modify your routing file (application/config/routes.php) so it looks as follows. This makes sure the requests reaches the news controller instead of going directly to the pages controller. The first line routes URI’s with a slug to the view method in the news controller.

$route['news/(:any)'] = 'news/view/$1';
$route['news'] = 'news';
$route['(:any)'] = 'pages/view/$1';
$route['default_controller'] = 'pages/view';

Point your browser to your document root, followed by index.php/news and watch your news page.

Wonderfull! This helps paint a better picture in my mind clarifying how routing works. Notice the key for $route[] is a regex used to match the portion of the user supplied URL which follows the name of the index page.

Also, notice how the routing rule $route[‘news’] = ‘news’; is not required to have a value (right side) of news/index. This means that—when no method is specified in the URI—CI assumes the method name index.

Advertisements

About samehramzylabib

See About on https://samehramzylabib.wordpress.com
This entry was posted in CodeIgniter. Bookmark the permalink.

Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s