A CodeIgniter extension to work with database tables with an easy and intuitive Object Oriented / Entity Framework approach.
Download the files from this repository and place them into the corresponding folders in your CodeIgniter project.
The add-in consists of a solid MY_Model implementation and also redefines the CI_Loader::model method. If you already have a MY_Loader extension, just copy the MY_Loader::model extended method within your extended class.
Let's make some examples with a classic cars table.
- Table Schema
- Define a New Entity Object
- Load a Model
- Get All Records
- Get Some Records
- Get a Single Record
- Filter by ID or Public ID
- Add a New record
- Make Some Changes
- Lock a Record
- Automatic Join
- Manual Join
- CodeIgniter's Query Builder
- Pagination
- Count
- Automatically Get a Foreign Key Object
- Define Custom Methods
- Usege of the Defined Custom Methods
- Support for CodeIgniter Query Builder Caching System
- Delete
- Created/Modified Datetime
- Soft Delete Support
- Public ID (UUID) Support
The best practice is to name your table in plural form (eg. cars), and name the primary key column as id.
There's no particular preferences for other column names.
Mind that you can still use other naming conventions for your tables. In this case, it's necessary to set this names by manually set the value of table, id_field and row_type properties in the constructor of the entity model definition (see next paragraph).
In the Models folder, create a new Cars_model.php file defining the Cars_model extending MY_Model class (use the plural for the entire table) and the Car_object extending Model_object class (use the singular for the single record).
Here the code in Models/Cars_model.php:
<?php defined('BASEPATH') OR exit('No direct script access allowed');
class Cars_model extends MY_Model {
public function __construct()
{
// If you use standard naming convention, this code can be omitted.
/*$this->table = 'cars';
$this->id_field = 'id';
$this->row_type = 'Car_object';*/
parent::__construct();
}
}
class Car_object extends Model_object {
}$this->load->model('Cars');
// or autoload in CI's application/config/autoload.php like this: $autoload['model'] = array('Cars');$all_cars = $this->Cars->get_list();// Get some records (apply a filter in query)
$some_cars = $this->Cars->where('brand_id', 1)->get_list();$a_car = $this->Cars->get(1); // this is a "get by id"$a_car = $this->Cars->id(1)->get();
$a_car = $this->Cars->public_id('3f2b8c1e-7a4d-4e9b-9c1f-2d6e8a0b5c47')->get();$new_car = $this->Cars->new_row();
$new_car->name = "Powerful Car";
$new_car->brand_id = 1;
$id = $new_car->save(); // this produces the insert command$edit_car = $this->Cars->get($id);
$edit_car->name = "Change its name";
$edit_car->save(); // this produces the update command (only for the changed fields, the CI Powerful Model tracks object changes)Call changes() to get the changed fields before saving. By default it uses strict comparison: changes(FALSE) uses loose comparison instead (eg. '1' and 1 are considered equal).
get_lock() starts a transaction and reads the record with SELECT ... FOR UPDATE. If another connection holds the lock, it waits for it to be released (up to innodb_lock_wait_timeout).
$car = $this->Cars->get_lock($id);
$car->stock -= 1; // e.g. decrement availability without race conditions
$car->save();
$car->unlock(); // completes the transaction and releases the lock$all_cars = $this->Cars->autojoin()->get_list(); // automatic LEFT join with the brands table
// uses the CI's inflector helper to transform <entity>_id to <entities>$this->Cars->join('brands', 'cars.brand_id = brands.id', 'LEFT');
$all_cars = $this->Cars->get_list();You can use all the CodeIgniter's Query Builder methods, allowing method chaining.
$some_cars = $this->Cars->where_in('brand_id', array(1, 2, 3))->like('name', "%Something")->order_by('name')->get_list();// (page 1, with 10 cars per page)
$cars_page1 = $this->Cars->pagination(1, 10)->order_by('name')->get_list();Pass TRUE as third parameter of pagination() to fetch one extra row: if you get pagesize + 1 rows, there's a next page.
$brand1_cars_count = $this->Cars->where('brand_id', 1)->count();$this->load->model('Brands'); // just another CI Powerful Model object
$car = $this->Cars->get(1);
$brand = $car->get_brand(); // cars.brand_id => brands.id
// uses the CI inflector's helper to transform <entity>_id to <entities>.idHere the code in Models/Cars_model.php:
<?php defined('BASEPATH') OR exit('No direct script access allowed');
class Cars_model extends MY_Model {
public function has_brand()
{
$this->db->where('brand_id >', 0);
return $this; // remember to return $this for method chaining support
}
}
class Car_object extends Model_object {
public function brand_name()
{
$CI = get_instance();
$CI->load->model('Brands_model', 'Brands'); // just another CI Power Model object
$brand = $CI->Brands->get($this->brand_id);
if ($brand)
return $brand->name;
return '';
}
}$cars = $this->Cars->has_brand()->get_list();
foreach ($cars as $car)
{
echo 'Car: '.$car->name.', Brand: '.$car->brand_name().'<br>';
}$this->Cars->start_cache();
$this->Cars->where('brand_id', 1);
$this->Cars->order_by('name');
$this->Cars->stop_cache();
$current_page_cars = $this->Cars->pagination(1, 10)->order_by('name')->get_list();
$total_cars_to_show = $this->Cars->count(); // this maintains the filter defined between start_cache() and stop_cache()
$this->Cars->flush_cache();$to_delete = $this->Cars->get($id);
$to_delete->delete();If you add a created (datetime) and a modified (datetime) field in your table, CI Powerful Model automatically write the creation date and the last change date
If you add a deleted (datetime) field in your table, the delete function doesn't hard delete the record, but writes the delete datetime in this field.
In this case, to filter your queries excluding the logical deleted records, call the all method before. Example:
$all_cars = $this->Cars->all()->get_list();
$some_cars = $this->Cars->all()->where_in('brand_id', array(1, 2, 3))->get_list();If you add a public_id (char(36)) field in your table, CI Powerful Model automatically assigns a UUID v4 on insert. Use it to expose records without revealing the sequential id.
To use a different column name, set the public_id_field property in the model constructor.