Just wanted to share a couple of methods, which I use in my models all the time. One is for saving and updating, while the other is for retrieving data, both of the methods rely on active record class.
When saving data from web forms, I normally validate and XSS filter all of the necessary elements of the $_POST array and then simply pass it to a model method. The problem is that often, in the $_POST array, there are extra fields that do not exist in the target table (fields used for controller logic - navigation etc). Obviously, trying to insert a field that does not exist in a table will trigger an error. One way around that is to manually unset all of the unnecessary elements in the $_POST array. That solution, however, does not scale at all and the code looks ugly. For that reason, I’ve written a method that will compare input array keys to the target table field names and unset all of the elements that do not match. Additionally, the input array can be passed through the XSS filter; that functionality is turned off by default. Here is the sample code:
Model methods
/**
* Make sure that the incoming array does not contain any
* fields which are not in the target table.
* Additionally, input can be XSS filtered.
*
* @access protected
* @param string
* @param array
* @param boolean
* @return array
*
*/
protected function filterInputArray($table, $data, $xss_clean = false){
$fields = $this->db->list_fields($table);
foreach ($data as $k => $v) {
if(in_array($k, $fields) == false){
unset($data[$k]);
} else {
if($xss_clean === true) $data[$k] = $this->input->xss_clean($v);
}
}
return $data;
}
//a typical update method
public function updateMethod($id, $data = array()){
$data = $this->filterInputArray('users', $data);
$this->db->where('id', $id);
$this->db->update('users', $data);
return $this->db->affected_rows();
}
//a typical insert method
public function insertMethod($data = array()){
$data = $this->filterInputArray('users', $data);
$this->db->insert('users', $data);
return $this->db->insert_id();
}
How you would call it from a Controller
public function someMethod(){
//load and configure validation
$this->load->library('validation');
//run validation
if ($this->validation->run() == true){
//load the model
$this->load->model('User_model', 'users');
//call the insert method
$user_id = $this->users->insertMethod($_POST);
//call the update method
$this->users->updateMethod($user_id, $_POST);
}
}
This method is used for generating query results - it always returns an array, even if it’s an empty one. It is built upon active record’s ‘get’ method. Essentially it eliminates the need to check if query has produced any result, as well as the need to call result_array() method. Additionally, by default, the keys in the resulting array will be set to the value of ‘id’ - this can be quite handy when working with arrays generated from dependent tables. Take a look at the code:
Model methods
/**
* Similar to active record's get method.
* Will always return an array, even if the query did not yield any results.
* By default, the reulting array's keys are equal to 'id'. That feature may
* be disabled by passing false as an optional parameter.
*
* @access protected
* @param boolean
* @return array
*
*/
protected function getArray($use_id_as_key = true){
$res = $this->db->get();
$items = array();
if ($res->num_rows() > 0) {
foreach ($res->result_array() as $k => $v) {
foreach ($v as $kk => $vv) {
if($use_id_as_key === true) $items[$v['id']][$kk] = $vv;
else $items[$k][$kk] = $vv;
}
}
}
return $items;
}
//a typical select method
//can't get much easier that this (except for ORM of course :))
public function selectMethod($id){
$this->db->from('users')->where('id', $id);
return $this->getArray();
}
How you would call it from a Controller
public function someMethod($user_id){
//load the model
$this->load->model('User_model', 'users');
//get user by id
$user = $this->users->selectMethod($user_id);
}
The above methods save me a lot of the time and headache, so I hope you find them useful. If you decide to use those in your code, the best place for them would be in a parent model.
CodeIgniter Framework :: TermiT's Blog says:
[…] CodeIgniter model productivity methods […]
louis says:
Great post. I am in the progress of designing by first CI app and this should come in useful.
louis w says:
Noticed two typos. Both times you have :
public function someMethod(){}
should be:
public function someMethod(){
you are closing your function before anything happens.
Alex says:
Louis, glad you found this helpful. Also check out this article - it really makes working with views a lot easier.
Typos corrected - thanks :)
Some CodeIgniter Tutorial links « Afruj’s Weblog says:
[…] CodeIgniter model productivity methods […]
links for 2008-05-19 | the sweetview blog says:
[…] CodeIgniter model productivity methods (tags: codeigniter php tips) […]
CodeIgniter Tutorial Links « Brandontruong’s Weblog says:
[…] CodeIgniter model productivity methods […]
Ruben Zevallos Jr. says:
Well… nice post… your blog is giving me a lot of new ideas and clues about CI… thanks
gillbates says:
Thanks for posting this. I have a question about the following:
If you decide to use those in your code, the best place for them would be in a parent model.
How do I implement this?
Alex says:
Gill, I really don’t know why CodeIgniter does not allow to extend the core model… Anyway, you can just create MY_Model class and drop it into your application/libraries folder. Basically it should look something like this:
<?php if (!defined('BASEPATH')) exit('No direct script access allowed'); class MY_Model extends Model { public function __construct(){ parent::Model(); } //add your own methods here } ?>Once you’ve done that, read this article - essentially it’s a simple, yet very flexible way to load external resources (works only with PHP5).
Well, that’s about it - I hope that helps :)
gillbates says:
hmm… so in my case, if I have a file named MyModel.php in system/application/libraries with the following:
and after adding the autoload function in config, I should then define my models this way:
<?php
if (!defined('BASEPATH')) exit('No direct script access allowed');
class Tourmodel extends MyModel {
function Tourmodel(){
parent::__construct();
}
}
Is this correct?
gillbates says:
gah! I keep losing my code. Oh well. As you can probably guess, what I meant to say was I created a class named MyModel that extends Model in MyModel.php. Then Tourmodel extends MyModel. Is this the correct implementation?
Alex says:
Did you encode that piece of code into HTML entities?
Yes, models should be created/written just as you suggested and then loaded in the standard CI way.
gillbates says:
I wrapped the code in
andtags. That doesn’t work, I suppose.Still had a few snags when I was trying to make it work last night (until they dragged me away from the computer). I’ll try to make it work today.
gillbates says:
Bit of a problem with this… it’s also trying to autoload Codeigniter’s ‘Model’. I suspect (and I have read of it somewhere) that the Model class does not start with CI. Maybe I should make my own prefix and only autoload files that begin with my prefix?
gillbates says:
and.. it works. Awesome!
So I modified the autoloader to only autoload classes with the prefix GILL_
function __autoload($class) {
//only autoload classes containing GILL_
if(stristr($class, ‘GILL_’)){
require_once(PATH_TO_LIBRARIES."$class.php");
}
}
Then I created GILL_MyModel.php in application/libraries containing the following class:
class GILL_MyModel extends Model
Then my models are defined as such:
class Tourmodel extends GILL_MyModel {
class Subareamodel extends GILL_MyModel
Alex says:
That’s the nice thing about __autoload - you can create your own loading rules based upon class names. Anyway, I’m glad you finally got it working :)
Spir says:
that’s awesome, thanks for sharing this!
CodeIgniter Tutorial Collection says:
[…] Model productivity methods (http://pr0digy.com/codeigniter/model-productivity-methods/) […]
Yesdi says:
Great tip ! I’m a newbie to CI though I’ve worked with other MVC frameworks. My question - can I have variables in my model class that are not meant to be stored the db ? For example, in the code above - I’ld like to have a member variable called var $dbname=’users’ so that I dont have to put in the db name in each method. How can I do that - just make it a private member var ?
Alex says:
Yesdi, CI doesn’t use ORM at all, so you can have any attributes or methods in your models. Instead of ORM, CI uses ActiveRecord, which essentially is a query builder.
If you are more comfortable with ORM, then you might want to take a look at Kohana.
Руководства, статьи и заметки says:
[…] CodeIgniter model productivity methods […]
Some Important CodeIgniter Tutorial links « Shamim Ahmed says:
[…] CodeIgniter model productivity methods […]