CodeIgniter Model
Introduction
In the previous tutorial, we created database migrations files and also seeded some dummy data into our database. This tutorial builds on the previous one and introduces you to models in CodeIgniter. If you have not yet read the previous tutorial then I recommend you read it.By the end of this tutorial, you will know who to work with models in CodeIgniter like a pro. You will also learn about best practices will make you write cleaner and concise code.
Topics to be covered
We will cover the following topics in this tutorial- Tutorial pre-requisites
- Skinny model skinny controller
- Model conventions
- CodeIgniter Model Example
- Extending CodeIgniter Model
- CodeIgniter Model Generator
- Load model in controller
- CodeIgniter Admin Panel Tutorial Project models
Tutorial Pre-requisites
This tutorial assumes you are familiar with;- PHP basics and Object-oriented programming
- CodeIgniter Basics
- You have a web server, PHP and MySQL already configured and running
- You have a cool IDE i.e. NetBeans IDE, Aptana Studio etc.
- You have access to a command line/terminal that you can use to run commands
- You have composer. Composer is a PHP dependencies manager.
Skinny model skinny controller
The common myth when working with MVC frameworks is to make your models skinny and your controllers skinny. This makes models God Objects and this is an anti-pattern. The rule of divide and conquer tells us all classes should be skinny.We will create a model base class that will extend CodeIgniter model and put all common functionality in the model base class. This will help us to write DRY (Don’t Repeat Yourself) code and make our models thin
Model conventions
One of the things that ruby on rails developers love about the framework is conventions over configurations. This means the framework has default conventions that it automatically applies and assumes you are following them. Other PHP frameworks such as Laravel have also embraced this concept.This approach has two main advantages
- You write less code which leads to rapid application development
- Sets industry standards that everyone follows.
- Model name should be singular while table name should be plural. If you have a model Cat, then the corresponding database table name should be cats. Since this is an agreed upon convention, you will not need to set the table name for your model. The framework will simply pluralize the model name. If you want to use a table name that cannot be pluralized, then you can specify the table name
- Each database table should have an auto increment primary key called id – all database interactions will assume id is the primary key and the framework that take care of that for you.
- Each database table will contain date created and date updated fields – this is for auditing purposes. Our tutorial series will use datecreated and dateupdated. The common convention that rails and Laravel use are createdat and updatedat. In my opinion, datecreated is more description than createdat. Feel free to go with whatever works for you.
- Each database table will contain createdfromip and updatedfromip fields – this is also for auditing purposes. The IP fields are not included in Rails and Laravel by default.
CodeIgniter Model Example
The following code shows an example of a typical model in CodeIgniter.<?php
class Blog_model extends CI_Model {
public $title;
public $content;
public $date;
public function __construct() {
parent::__construct();
}
public function get($id){
return $this->db->get_where('posts', array('id' => $id))->row();
}
public function get_all() {
$query = $this->db->get('posts');
return $query->result();
}
public function insert() {
$this->title = 'CodeIgniter 101';
$this->content = '<p>Say what you want about CI, it still rocks</p>';
$this->date = time();
$this->db->insert('posts', $this);
}
public function update($id) {
$this->title = 'CodeIgniter 101';
$this->content = '<p>Say what you want about CI, it still rocks</p>';
$this->date = time();
$this->db->update('posts', $this, array('id' => $id));
}
public function delete($id){
$this->db->delete('posts', array('id' => $id));
}
}
class Blog extends CI_Model {…}
defines a class Blog that extends CI_Modelpublic function __construct() {…}
defines the class constructor method that executes the parent class constructor methodpublic function get($id){…}
returns a single record based on the supplied primary key valuepublic function get_all() {…}
returns all recordspublic function insert() {…}
adds a new record to the tablepublic function update($id) {…}
updates an existing record based on the supplied idpublic function delete($id){…}
deletes an existing record based on the supplied id
Extending CodeIgniter Model
We don’t just want skinny controllers, we want skinny models too. We will create a base class that will have the following six (6) functions. We will apply the agreed upon conventions in this section.get($id)
returns single record based on the supplied idget($fields = '', $where = array())
returns records based on specified field names and criteriaget_all()
returns all the recordsinsert()
creates a new recordupdate($id)
updates an existing recorddelete($id)
deletes an existing record
/application/core
as MY_Model.php
Create a new file
/application/core/MY_Model.php
Add the following code
<?php (defined('BASEPATH')) OR exit('No direct script access allowed');
class MY_Model extends CI_Model {
protected $table_name = '';
protected $primary_key = 'id';
public function __construct() {
parent::__construct();
$this->load->database();
$this->load->helper('inflector');
if (!$this->table_name) {
$this->table_name = strtolower(plural(get_class($this)));
}
}
public function get($id) {
return $this->db->get_where($this->table_name, array($this->primary_key => $id))->row();
}
public function get_all($fields = '', $where = array(), $table = '', $limit = '', $order_by = '', $group_by = '') {
$data = array();
if ($fields != '') {
$this->db->select($fields);
}
if (count($where)) {
$this->db->where($where);
}
if ($table != '') {
$this->table_name = $table;
}
if ($limit != '') {
$this->db->limit($limit);
}
if ($order_by != '') {
$this->db->order_by($order_by);
}
if ($group_by != '') {
$this->db->group_by($group_by);
}
$Q = $this->db->get($this->table_name);
if ($Q->num_rows() > 0) {
foreach ($Q->result_array() as $row) {
$data[] = $row;
}
}
$Q->free_result();
return $data;
}
public function insert($data) {
$data['date_created'] = $data['date_updated'] = date('Y-m-d H:i:s');
$data['created_from_ip'] = $data['updated_from_ip'] = $this->input->ip_address();
$success = $this->db->insert($this->table_name, $data);
if ($success) {
return $this->db->insert_id();
} else {
return FALSE;
}
}
public function update($data, $id) {
$data['date_updated'] = date('Y-m-d H:i:s');
$data['updated_from_ip'] = $this->input->ip_address();
$this->db->where($this->primary_key, $id);
return $this->db->update($this->table_name, $data);
}
public function delete($id) {
$this->db->where($this->primary_key, $id);
return $this->db->delete($this->table_name);
}
}
protected $table_name = '';
defines class property for the table name and sets it to blank by defaultprotected $primary_key = 'id';
defines the class property for the primary key and sets it to id by default. This is a convention that we agreed uponpublic function __construct() {…}
is the class constructor method.parent::__construct();
executes the parent class constructor method.$this->load->database();
loads the database class.$this->load->helper('inflector');
loads the inflector helper. The inflector helper will help us pluralize the class name to guess the database table name.if (!$this->table_name) {…}
check if the class name is not set explicitly. If it is not set then we pluralize the class name and set it has the table name. If it is set, we go with the set table name- The rest of the code is self-explanatory. Feel free to use the comments section to ask for clarifications.
CodeIgniter Model Generator
One of the things that I love about programming is I AM ALLOWED TO BE LAZY. Why waste time writing boiler plate code when I can automate the process? In the previous tutorial, we created a command line tool that helped us generate models. We will add one more function to generating models boiler plate code. Open/application/controllers/tools.php
Add the following functions
public function model($name) {
$this->make_model_file($name);
}
protected function make_model_file($name) {
$path = APPPATH . "modules/admin/models/$name.php";
$my_model = fopen($path, "w") or die("Unable to create model file!");
$model_template = "<?php (defined('BASEPATH')) OR exit('No direct script access allowed');
class $name extends MY_Model {
public function __construct() {
parent::__construct();
}
}
";
fwrite($my_model, $model_template);
fclose($my_model);
echo "$path model has successfully been created." . PHP_EOL;
}
Open the command prompt / terminal
Run the following command to browser to the project root. Note: the project root should point to wherever you created the project
cd "C:\xampp\htdocs\ci-my-admin"
php index.php tools model "Brand"
You will get the following message
C:\xampp\htdocs\ci-my-admin\application\modules/admin/models/Brand.php model has successfully been created.
/application/modules/admin/models/brand.php
You will get the following
<?php (defined('BASEPATH')) OR exit('No direct script access allowed');
class Brand extends MY_Model {
public function __construct() {
parent::__construct();
}
}
class Brand extends MY_Model {…}
defines a class Brand that extends our base modelMY_Model
public function __construct() {…}
defines the class constructor that executes the parent constructor
Load model in controller
This section shows you how to load a model in CodeIgniter. In the previous tutorials, we created controllers for our brands, categories and products tables. Open/application/modules/admin/controllers/Brands.php
Modify the constructor method to the following
function __construct() {
parent::__construct();
$this->load->model(array('admin/brand'));
}
$data = $this->brand->get_all();
loads the brand model in the constructor method. This will make the model available to all methods in Brands controller.Add the following method
public function brands_list(){
$data = $this->brand->get_all();
print_r($data);
}
$data = $this->brand->get_all();
calls theget_all()
method of our brand controller.print_r($data);
dumps the contents of$data
in the browser
/application/config/routes.php
Add the following route for testing purposes
$route['brands'] = 'admin/brands/brands_list';
http://localhost/ci-my-admin/brands
We got the above results from the database with almost zero (0) coding on our part.
CodeIgniter Admin Panel Tutorial Project models
We already generated the model for Brand. Let’s now generate the models for Category and ProductRun the following commands. Make sure you are in the root of your project
php index.php tools model "Category"
php index.php tools model "Product"
Let’s now modify our controllers to pass the data to views
Brands.php
<?php
class Brands extends Admin_Controller {
function __construct() {
parent::__construct();
$this->load->model(array('admin/brand'));
}
public function index() {
$brands = $this->brand->get_all();
$data['brands'] = $brands;
$data['page'] = $this->config->item('ci_my_admin_template_dir_admin') . "brands_list";
$this->load->view($this->_container, $data);
}
public function create() {
if ($this->input->post('description')) {
$data['description'] = $this->input->post('description');
$this->brand->insert($data);
redirect('/admin/brands', 'refresh');
}
$data['page'] = $this->config->item('ci_my_admin_template_dir_admin') . "brands_create";
$this->load->view($this->_container, $data);
}
public function edit($id) {
if ($this->input->post('description')) {
$data['description'] = $this->input->post('description');
$this->brand->update($data, $id);
redirect('/admin/brands', 'refresh');
}
$brand = $this->brand->get($id);
$data['brand'] = $brand;
$data['page'] = $this->config->item('ci_my_admin_template_dir_admin') . "brands_edit";
$this->load->view($this->_container, $data);
}
public function delete($id){
$this->brand->delete($id);
redirect('/admin/brands', 'refresh');
}
}
<?php
class Categories extends Admin_Controller {
function __construct() {
parent::__construct();
$this->load->model(array('admin/category'));
}
public function index() {
$categories = $this->category->get_all();
$data['categories'] = $categories;
$data['page'] = $this->config->item('ci_my_admin_template_dir_admin') . "categories_list";
$this->load->view($this->_container, $data);
}
public function create() {
if ($this->input->post('description')) {
$data['description'] = $this->input->post('description');
$this->category->insert($data);
redirect('/admin/categories', 'refresh');
}
$data['page'] = $this->config->item('ci_my_admin_template_dir_admin') . "categories_create";
$this->load->view($this->_container, $data);
}
public function edit($id) {
if ($this->input->post('description')) {
$data['description'] = $this->input->post('description');
$this->category->update($data, $id);
redirect('/admin/categories', 'refresh');
}
$category = $this->category->get($id);
$data['category'] = $category;
$data['page'] = $this->config->item('ci_my_admin_template_dir_admin') . "categories_edit";
$this->load->view($this->_container, $data);
}
public function delete($id) {
$this->category->delete($id);
redirect('/admin/categories', 'refresh');
}
}
<?php
class Products extends Admin_Controller {
function __construct() {
parent::__construct();
$this->load->model(array('admin/brand'));
$this->load->model(array('admin/category'));
$this->load->model(array('admin/product'));
}
public function index() {
$products = $this->product->get_all();
$data['products'] = $products;
$data['page'] = $this->config->item('ci_my_admin_template_dir_admin') . "products_list";
$this->load->view($this->_container, $data);
}
public function create() {
if ($this->input->post('name')) {
$data['name'] = $this->input->post('name');
$data['price'] = $this->input->post('price');
$data['model'] = $this->input->post('model');
$data['brand_id'] = $this->input->post('brand_id');
$data['category_id'] = $this->input->post('category_id');
$data['tag_line'] = $this->input->post('tag_line');
$data['features'] = $this->input->post('features');
$this->product->insert($data);
redirect('/admin/products', 'refresh');
}
$brands = $this->brand->get_all();
$categories = $this->category->get_all();
$data['brands'] = $brands;
$data['categories'] = $categories;
$data['page'] = $this->config->item('ci_my_admin_template_dir_admin') . "products_create";
$this->load->view($this->_container, $data);
}
public function edit($id) {
if ($this->input->post('name')) {
$data['name'] = $this->input->post('name');
$data['price'] = $this->input->post('price');
$data['model'] = $this->input->post('model');
$data['brand_id'] = $this->input->post('brand_id');
$data['category_id'] = $this->input->post('category_id');
$data['tag_line'] = $this->input->post('tag_line');
$data['features'] = $this->input->post('features');
$this->product->update($data, $id);
redirect('/admin/products', 'refresh');
}
$product = $this->product->get($id);
$brands = $this->brand->get_all();
$categories = $this->category->get_all();
$data['brands'] = $brands;
$data['categories'] = $categories;
$data['product'] = $product;
$data['page'] = $this->config->item('ci_my_admin_template_dir_admin') . "products_edit";
$this->load->view($this->_container, $data);
}
public function delete($id) {
$this->product->delete($id);
redirect('/admin/products', 'refresh');
}
}