Skip to content
lonnieezell edited this page Sep 12, 2012 · 2 revisions

1 Model Overviews

Keeping with the MVC spirit, Bonfire uses Models to allow you interact with your database in a simple, consistent manner. By using the BF_Model as the base class for all of your models, you can very quickly setup a simple model capable of finding records, creating new and editing existing records, deleting records, checking if a key/value is unique in this table, counting the results, and more.

BF_Model acts as a middleman layer to between your models and CodeIgniter's standard Model class, working hand-in-hand with ActiveRecord query builder. If you don't need any special queries, your can have a working model in just a handful of lines.

1.1 Is it an ORM?

BF_Model is not an ORM. While ORM's have their place, Bonfire does not ship with one included.

2 A Skeleton Model

To get started with a new model, you can use the following skeleton file:

	class X_model extends BF_Model {
	
		protected $table			= 'table_name';
		protected $key			= 'id';
		protected $soft_deletes	= false;
		protected $date_format	= 'datetime';
		protected $set_created	= true;
		protected $set_modified	= false;
	
	}

2.1 $table

The var $table should be set to the name of the table in your database. If you database is set to use a prefix (Bonfire defaults to a bf_ prefix), you should leave the prefix off. So a table named bf_users should be entered as users.

2.2 $key

The var $key should be the name of the primary key for your table. BF_Model requires that your table has primary key. If it doesn't you should extend Model and will need to write your own methods to interface with the database. The $key is expected to be linked to an INT field.

2.3 $soft_deletes

Bonfire uses the concept of soft deletes that will set a flag that an item has been deleted instead of actually deleting the item. This allows you to later restore the user in case the deletion was accidental, or to keep a permanent record of any sensitive information, like transaction records.

To use soft_deletes, your table must have a deleted field that is a TINYINT (1). A value of 0 means the record has not been deleted, while a value of 1 shows that the item has been deleted.

If $soft_deletes == TRUE, Bonfire will automatically update the record to set deleted to a value of 1.

If $soft_deletes == FALSE, the record will be permanently deleted from the database.

2.4 $date_format

The $date_format class var specifies the types of fields that created_on and modified_on fields are expected to be. The allowed values are int, datetime, or date. If you are using UNIX timestamps then you should use the int fieldtype.

2.5 $set_created

Bonfire can automatically set your created on dates and times for you, in the format specified through $date_format. To use this, your table must have a created_on field of the proper type.

If $set_created == TRUE, Bonfire will set the created_on field value for you at the time of an insert() call.

2.6 $set_modified

Bonfire can automatically set your modified on dates and times for you, in the format specified through $date_format. To use this, your table must have a modified_on field of the proper type.

If $set_created == TRUE, Bonfire will set the created_on field value for you at the time of an insert() call.

3 Provided Methods

By using the skeleton file, you get a number of methods ready to use on your model. All of these methods can be overriden in your own model if you need to customize them by joining other tables, processing the results before handing off to the controller, etc.

3.1 find()

The find() method is used to locate a single record based on it's id.

$user = $this->user_model->find($id);

echo $user->username;

Returns an object with the results if found, or FALSE if not found.

3.2 find_by()

A convenience method that combines the where() and find() methods. Expects to return a single result, so you should search on a field that will have unique values.

$this->user_model->find_by('email', '[email protected]');

This method can also be called with only a single associative array as the first parameter. This allows you set multiple criteria to search by.

$user = $this->user_model->find( array('email'=>'[email protected]', 'deleted'=>0) );

# SQL: SELECT * FROM `bf_users` WHERE email='[email protected]' AND deleted='0'

This defaults to combining all criteria as "AND" but can be modified by passing the the type into the third parameter:

$user = $this->user_model->find( array('email'=>'[email protected]', 'deleted'=>0), null, 'OR' );

# SQL: SELECT * FROM `bf_users` WHERE email='[email protected]' OR deleted='0'

3.3 find_all()

Locates all records in the table.

$this->user_model->find_all();

If you need to modify the search criteria you can use any of the chainable methods.

$users = $this->user_model->where('deleted', 1)
						  ->limit(25)
						  ->find_all();
				
foreach ($users as $user)
{
	echo $user->username;
}

Returns an array of objects where each object holds the results of a single record.

3.4 find_all_by()

Locates all records matching certain criteria. This is a convenience method for using a where() and a find_all() in one command.

$this->user_model->find_all_by('deleted', 1);

Any of the standard options available to a CodeIgniter where() method may be used here.

$this->user_model->find_all_by('deleted', 1);
$this->user_model->find_all_by('deleted !=', 0);
$this->user_model->find_all_by( array('email'=>'[email protected]', 'deleted'=>0) );

Returns an array of objects where each object holds the results of a single record.

3.5 insert()

Creates a new record. Will set the created_on field if the model is setup to allow that. The first parameter should be an associative array of field/values to insert.

$user = array(
	'email'		=> '[email protected]',
	'username'	=> 'darth.vader'
);
$this->user_model->insert($user);

# SQL: INSERT INTO `bf_users` (email, username, created_on) VALUES ('[email protected]', 'darth.vader', 1321645674);

Returns an INT ID of the new record on success, or FALSE on failure.

3.6 update()

Updates an existing record in the database by ID. Will set the correct time for the modified_on field, if the model requires it.

$user = array(
	'email'		=> '[email protected]',
	'username'	=> 'darth.vader'
);
$this->user_model->update($user_id, $user);

# SQL: UPDATE `bf_users` SET email='[email protected]', username='darth.vader', modified_on=1321645674 WHERE id=1;

Returns a boolean TRUE/FALSE on success/failure.

3.7 update_where()

Updates a single record in the database by a key/value pair. Will set the correct time for the modified_on field, if the model requires it.

$user = array(
	'email'		=> '[email protected]',
	'username'	=> 'darth.vader'
);
$this->user_model->update('is_father', 1, $user);

# SQL: UPDATE `bf_users` SET email='[email protected]', username='darth.vader', modified_on=1321645674 WHERE is_father=1;

3.8 delete()

Deletes a single record from the database. If $soft_deletes are on, then will just set the deleted field to 1. Otherwise, will permanently delete the record from the database.

$this->user_model->delete($user_id);

# SQL w/ soft deletes: UPDATE bf_users SET deleted=1 WHERE id=$user_id;
# SQL w/out soft deletes: DELETE FROM bf_users WHERE id=$user_id;  

Returns a boolean TRUE/FALSE on success/failure.

3.9 is_unique()

Checks to see if a given field/value combination would be unique in the table.

$this->user_model->is_unique('email', '[email protected]');

3.10 count_all()

Counts all records in the table.

$this->user_model->count_all();

Returns an INT containing the number of results, or FALSE.

3.11 count_by()

Counts the number of elements that match the field/value pair.

$this->user_model->count_by('delete', 1);

Returns an INT containing the number of results, or FALSE.

3.12 get_field()

A convenience method to return only a single field of the specified row. The first parameter is the ID of the row to search in. The second parameter is the column to return the value of.

$this->user_model->get_field($user_id, 'email');

Returns the value of the row's field, or FALSE.

4 Chainable Methods

Thanks to CodeIgniter's ActiveRecord library, it is very simply to modify the BF_Model's methods. This can be done through either chainable methods or by extending methods.

Chainable methods are a feature of PHP 5 and higher that allow you to return the results of one function into another, and to keep this 'chain' of events continuing through several functions. Bonfire duplicates several of the stock ActiveRecord methods in BF_Model to make it simple and elegant to customize your queries.

4.1 where()

Modifies the query to a specific where condition. Can be used with any of the read-type queries (find, find_all, etc).

The first parameter is the field to match against. The second parameter is the value of the field to find.

Accepts any of the standard CodeIgniter ActiveRecord where statements.

$this->user_model->where('email', '[email protected]');
$this->user_model->where('email !=', '[email protected]');
$this->user_model->where( array('email' => '[email protected]') );

$this->user_model->where('email', '[email protected]')
				 ->find_all();

4.2 select()

Sets the select portion of the query in a chainable format. Can be used with any read-type queries (find, find_all, etc).

The only parameter is a string with the columns to return from each record.

$this->user_model->select('id, email, username')
				 ->find_all();

4.3 limit()

Sets the limit portion of the query in a chainable format. Can be used with any read-type queries (find, find_all, etc).

The first parameters is the number of items to limit results to. The second (optional) parameter is the number of records to offset the result by.

$this->user_model->limit(20, 0)
				 ->find_all();

4.4 order_by()

Inserts a chainable order_by method from either a string or an array of field/order combinations. Can be used with any read-type queries (find, find_all, etc).

If the $field value is an array, it should look like:

	 array(
	 	'field1' => 'asc',
	 	'field2' => 'desc'
	 );
$this->user_model->order_by('email', 'asc')
				 ->find_all();
				 
$this->user_model->order_by( array(
								'email' 	=> 'asc',
								'username'	=> 'desc'
							) )
				 ->find_all();

Combining the Chains

Any or all of the chainable methods can be used in any order within a call.

$this->user_model->select('id, email, 'username')
				 ->where('deleted', 0)
				 ->limit(20, 0)
				 ->order_by('created_on', 'asc')
				 ->find_all();

5 Extending Methods

While it is possible to modify the query via the chainable methods any time you need results in your controller, it is highly recommended to extend the model's methods to bring you the results you need. This keeps all of your changes to queries in a single place.

Sometimes, you might want to do some additional processing to the database results before passing it on to the controller. This is another perfect example of when to extend the model's method.

To extend an existing method, you simply create a new method in your model that accepts the same parameters as the original BF_Model method.

// Extend the existing functionality.
public function find($id=null)
{
	$result = parent::find($id);
	
	if ($result)
	{
		$result->display_name = $this->format_name($result);
	}
	
	return $result;
}

6 Modify Query in Controller

You can modify a query in your model for a single use by using CodeIgniter's ActiveRecord commands in your controllers. Since BF_Model uses the ActiveRecord commands, the changes in your controller will affect the results of the next query in your model.

// In your controller.

$this->db->join('other_table', 'link_field = users.id', 'left');
$user = $this->user_model->find($user_id);
Clone this wiki locally