Skip to content

Instantly share code, notes, and snippets.

@toopay
Created November 4, 2011 09:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save toopay/1339003 to your computer and use it in GitHub Desktop.
Save toopay/1339003 to your computer and use it in GitHub Desktop.
Gas ORM - Convention and Examples
<?php
// By default, if you use User as your model name,
// you may should named this file user_gas.php within your models directories
// You can change '_gas' suffix in gas.php under config
class User extends Gas {
// If your table name different with your model name, specify it
// otherwise, you didnt need to declare this property
public $table = 'person';
// If your primary key isn't 'id', specify it
// otherwise, you didnt need to declare this property
public $primary_key = 'person_id';
// Here you can define your table relationship
// otherwise, you didnt need to declare this property
public $relations = array(
// Gas support 3 types relationship, one-to-one, one-to-many and many-to-many
// In this example, user have one wife, many kids and many (and belongs to) jobs
// If you define a relationship, your corresponding table, should have one too,
// which represent your tables relationship.
// eg : by bellow seting, your 'wife' and 'kid' tables should have 'belongs_to'
// while your 'job' table should have 'has_and_belongs_to'
// means each user record have one record in 'wife' table,
// identified with foreign key in 'wife' table
'has_one' => array('wife' => array(
// By default, Gas will assume that your foreign key is 'user_id'
// otherwise, you should define it on 'foreign_key'
'foreign_key' => 'person_id'
// NOTE : Make sure your 'wife' table also have this foreign key
)),
// means each user record have many records in 'kid' table,
// identified with foreign key in 'kid' table
'has_many' => array('kid' => array(
// By default, Gas will assume that your foreign key is 'user_id'
// otherwise, you should define it on 'foreign_key'
'foreign_key' => 'person_id'
// NOTE : Make sure your 'wife' table also have this foreign key
),
'role' => array(
// If you try to connecting three (or more) tables via intermediate
// table, which also have its own id and other values, use this
// option. Notice that while you use this, it refer to a gas model,
// so in this case, you should create 'user_role' model
'through' => 'user_role',
// By default, Gas will assume that your foreign key is 'user_id'
// otherwise, you should define it on 'foreign_key'
'foreign_key' => 'u_id',
)),
// means each user have many records in 'job' table,
// identified with foreign key in pivot table which should be : 'job_user' table
'has_and_belongs_to' => array('job' => array(
// By default, Gas will assume that your foreign key is 'user_id'
// otherwise, you should define it on 'foreign_key'
'foreign_key' => 'person_id',
// NOTE : Make sure you set up foreign key in 'job' table as well,
// but, because this is many-to-many, 'job' table foreign key
// should represent job FK in the pivot table, eg : 'jobs_id', 'j_id' // and so on
// By default, Gas will assume that your pivot table is 'job_user'
// otherwise, you should define it on 'foreign_table'
'foreign_table' => 'j_u',
// NOTE : Make sure your 'job' table also have this foreign table
)),
);
// _init is works like constructor, so if you need to declare/set some properties,
// or loading some library/config or anything else, which you may used later in your methods,
// do it here
// If you decide to perform validation before insert/update a record
// you can define each field rules here
// otherwise, you didnt need to declare this method and _field property
function _init()
{
// Here you can define your fields types and validation rules
$this->_fields = array(
// By default, Gas support 4 common datatypes : auto, char, int, email
// auto : for autoincrement field
// char : for CHAR or VARCHAR field
// int : for integer/numerical field
// email : same with valid_email rule at CI validation rule
// And field() method support maxlength short hand,
// all you have to do is put some maxlength number inside a brackets []
'id' => Gas::field('auto[3]'),
'name' => Gas::field('char[40]'),
'email' => Gas::field('email'),
// If you need to implement some standard CI validation rules,
// somethinf like : required, matches, decimal and so on
// put in an array as second parameter.
'username' => Gas::field('char[10]', array('callback_username_check')),
);
}
// callback which will execute, before going to validation process
function _before_check() {}
// callback which will execute, after validation process
function _after_check() {}
// callback which will execute, before going to write (INSERT or UPDATE) process
function _before_save() {}
// callback which will execute, after write (INSERT or UPDATE) process
function _after_save() {}
// callback which will execute, before going to DELETE process
function _before_delete() {}
// callback which will execute, after DELETE process
function _after_delete() {}
// If you have some custom callback function in your validation rules
// your callback function should follow this pattern
// FIRST : it has to expected two parameter, the first parameter
// will automatically populated by Gas
// The second parameter is the value to check
public function username_check($field, $val)
{
// in this case, username cannot contain 'me' as its value
if($val == 'me')
{
// SECOND : this is slightly different way, to set your validation message
// Gas using static method set_message() to replace the original set_message,
// from CI validation class, but it actually work with the same way,
// except, you should put $field as third parameter.
self::set_message('username_check', 'The %s field cannot fill by "me"', $field);
return FALSE;
}
return TRUE;
}
// If you need extra logic in your controller
// and it is potentially will make your controller fat
// avoid, by create your own custom finder function
public function all_admin()
{
// Here you can use factory method to find some specific record(s)
return Gas::factory($this->model())->join_role('role.id = user.role')
->where('role', 1)
->or_where('role', 2)
->order_by('id', 'asc')
->all();
}
// Then in any controller, anytime you need to retrieve it
// $admins = Gas::factory('user')->all_admin();
}
<?php
// This is an examples, how you can use finder method,
// from your Gas model, in your controller.
class Gas_finder extends CI_Controller {
public function index()
{
// You can instantly using some Gas model
// without instantiate it, by using factory method
$users = Gas::factory('user')->all();
// To reduce keystroke, just instantiate user model once
$user = new User;
// Then you can implement all finder method
// Get the first record, based by primary key
// You can specify some column, eg : $user->first('email')
$firstuser = $user->first();
// Gas have to_array() and to_json()
// as a helper method, while you want to output
// your record
var_dump($firsuser->to_array());
// Get the last record, based by primary key
// You can specify some column, eg : $user->last('name')
$lastuser = $user->last();
// Get max for primary key
// In all aggregator method : max, min, avg, sum
// You can specify some column, eg : $user->max('money')
$max = $user->max();
$min = $user->min();
// Like CI AR, Gas inherit aliasing column name as well
$avg = $user->avg('id', 'average_id');
$sum = $user->sum('id', 'sum_of_id');
// Get a record, based by primary key
$someuser = $user->find(1);
// Get a set of records, based by primary key
$someusers = $user->find(1, 2, 3);
// Get a set of records, based by other column
// eg : you have email, name, username at your user table
// then, you can use find_by_name or find_by_username too
$someusers = $user->find_by_email('johndoe@yahoo.com');
// find_by will always result an array. If you want Gas to return
// a first matched record, directly as an object, pass limit number as second parameter
$someuser = $user->find_by_username('administrator', 1);
// The huge advantages, by using Gas you can fully utilize CI AR as well :
// almost all CI active record method, can chained with Gas finder method.
// Beside all(), find() and find_by_column()
// Gas have find_where() and find_where_in(), eg :
//
// $someusers = $user->where_in(array('role' => array(1,2)))->find_where(array('active' => 1));
//
// $someusers = $user->where('active', 1)->find_where_in(array('role' => array(1,2)));
$someusers = $user->group_by('email')->min('money');
$someusers = $user->like('email', 'yahoo.com')->all();
$somejoinedusers = $user->left_join_job('job.id = user.id')->all();
}
}
<?php
// This is miscellaneous method which supported by Gas.
// most of them actually inherit CI AR, with shorter keystroke
// or common logic combination
class Gas_misc extends CI_Controller {
public function index()
{
// Sometime, you are forgot all of existed coloumn in a table
// use list_fields
var_dump(Gas::factory('user')->list_fields());
// Suppose you are about save a record
$_POST = array(
'id' => null,
'name' => 'Mr. Foo',
'email' => 'foo@world.com',
'username' => 'foo'
);
$new_user = new User;
// this will mapped $_POST data with fields rules
// you define in _init method in user model respectively
$new_user->fill($_POST);
// to see all data which has already set
// use filled_fields
var_dump($new_user->filled_fields());
// If everything seems ok, you can continue to save the record
$new_user->save();
// to get the last executed query, use last_sql()
var_dump($new_user->last_sql());
// Often, you need to know the last id created by INSERT operation
// use last_id()
$last_created_id = $new_user->last_id();
// I'm not a huge fan of JOIN operation : ITS EXPENSIVE!
// but for you, who love it, Gas provide easier shorthand
// so you can craft your JOIN statement easier
// Gas inherit from CI AR, so available shorthand were :
// 'left', 'right', 'outer', 'inner', 'left outer' and 'right outer'
// you can JOIN-ed some table/model as follow :
$someusers = Gas::factory('user')->left_join_phone('phone.user_id = user.id')->all();
$someusers = Gas::factory('user')->left_outer_join_sandals('sandals.id = user.sandal_id')->all();
// to get all executed query, use all_sql()
var_dump(Gas::factory('user')->all_sql());
// Gas support multiple connection, so you can switch to other database
// by default, Gas will use 'default' group, specified in your database.php under config folder
// Switching to other database just need a dsn string or group connection name (which you specified
// in database.php under config directory)
// You can specify the dsn string
Gas::connect('mysql://root:password@localhost/my_db');
// This will search from user table at 'my_db' database
var_dump(Gas::factory('user')->find(1));
// You can specify the connection group name
Gas::connect('develop');
// This will search from user table at database
// specified by your 'develop' group configuration
var_dump(Gas::factory('user')->find(1));
}
}
<?php
// This is an examples, how you can utilize your table relationship
// from your Gas model, in your controller.
// You may put some part/fraction of this code,
// to your model as custom function instead write it in your controller
// this is just an example, how you would utilize table relationship in Gas ORM
class Gas_relationship extends CI_Controller {
public function index()
{
// One-To-One : Will return an object of wife, which have user_id = 1
$somewife = Gas::factory('user')->find(1)->wife;
// Each child Gas instance which retrieved, can be directly process
// with write operation, eg : update
$somewife->hair_colour = 'Brunette';
$somewife->save();
// One-To-Many : Will return an array of kid object, which have user_id = 1
$somekids = Gas::factory('user')->find(1)->kid;
// for one-to-many or many-to-many relationship
// Gas will always return an array, so you proceed it as follow
foreach ($somekids as $kid)
{
// Here you can do whatever you want to do with 'kid' instance
echo $kid->name;
if (strpbrk($kid->name, 'Doe'))
{
// you can do write operation as well
$kid->name = 'John Doe\'s son(s)'
$kid->save();
}
}
// Many-To-Many : Will return an array of job object,
// based by pivot table (job_user), which have user_id = 4
$somejobs = Gas::factory('user')->find(4)->job;
// Eager Loading : Will return an array of user object,
// alongside with each relational table with WHERE IN(N+1)
$allinone = Gas::factory('user')->with('wife', 'kid', 'job')->all();
}
}
<?php
// This is an examples, how you perform transaction,
// at your Gas model.
class User extends Gas {
function _init()
{
$this->_fields = array(
'id' => Gas::field('auto[3]'),
'name' => Gas::field('char[40]')
);
}
public function dummy_trans()
{
// notice that $this->model() will return
// your table/model name automatically,
// so you doesn't need to write 'user'
// inside factory method, whithin your model
$user = Gas::factory($this->model());
// This is transaction pointer, everyting below this
// will treated as transactional query(s)
$user->trans_start();
// Here you can have some queries executed using query() method
for($i = 5;$i < 10;$i++)
{
$user->query('INSERT INTO `'.$this->model().'` (`id`, `name`) VALUES ('.$i.', \'user_'.$i.'\')');
}
for($i = 5;$i < 10;$i++)
{
// Here i just show you, how Gas can support AR pattern in transaction blocks
$new_user = Gas::factory($user->model())->find($i);
$new_user->fill(array('name' => 'person_'.$i))->save();
}
// If something goes wrong
if ($user->trans_status() === FALSE)
{
// will produce SQL : "ROLLBACK"
$user->trans_rollback();
}
else
{
// If everything ok
// will produce SQL : "COMMIT"
$user->trans_commit();
}
// If above transaction works fine, then this will find one result
$user9 = Gas::factory('user')->find(9);
// Should be echoing 'person_9'
echo $user9->name;
}
}
// To call this, from your controller, you only need 1 line :
// Gas::factory('user')->dummy_trans();
// That should echoing 'person_9', for example.
<?php
// This is an examples, how you can use write method,
// from your Gas model, in your controller.
// You better put this write operation block, to your model,
// as custom function instead write it in your controller,
// this is just an example, how you would doing some inserting data process in Gas ORM.
class Gas_write extends CI_Controller {
public function index()
{
// Suppose you have this data from some form, to create new user
$_POST = array(
'id' => null,
'name' => 'Mr. Foo',
'email' => 'foo@world.com',
'username' => 'foo'
);
$new_user = new User;
// this will mapped $_POST data with fields rules
// you define in _init method in user model respectively
$new_user->fill($_POST);
// By default, Gas not enforce you to use validation process
// so if you want to invoke and perform validation process
// based by rule you specified in your model, pass TRUE in save()
if ( ! $new_user->save(TRUE))
{
$insert_result = $new_user->errors();
}
else
{
$insert_result = '<p>New user succesfuly created.</p>';
}
echo $insert_result;
// From last created record, using 'last_id' method,
// eg : will return '1', because above is first record
$new_id = $new_user->last_id();
// Create new user instance with last created record
$recent_user = Gas::factory('user')->find($new_id);
// Suppose you have this array as data
$update_data = array(
'name' => 'Mr. Bar',
'email' => 'bar@world.com'
);
// you can use fill, to set your model data
// and set those array as $_POST, by pass TRUE
// as second parameter
$recent_user->fill($update_data, TRUE);
// or directly set it like bellow
$recent_user->username = 'bar';
if ( ! $recent_user->save(TRUE))
{
// Like CI AR, you could use prefix and suffix to wrap errors string
// generated by validation process
$update_result = $new_user->errors('<p class="error">', '</p>');
}
else
{
$update_result = '<p>New user succesfuly created.</p>';
}
echo $update_result;
// To delete something, you can directly assign id, or 'delete' will see through your recorded logic, eg :
$now_user = Gas::factory('user')->find($new_id);
// Just ensure that data has been updated
if ($now_user->username != 'bar')
{
// This will delete user 1
$now_user->delete();
}
// You can delete several records, based by their primary key too
Gas::factory('user')->delete(1, 2, 3);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment