| Status | Draft |
|---|---|
| Todo | Fill in missing stuff, Missing methods, __get properties, relationships |
Object Relational Mapping (ORM) provides a way create objects that represent rows from a database. It also provides a way to define and retrieve rows that are related by foreign keys. By creating relationships between models that follow convention over configuration, much of the repetition of writing queries to create, read, update and delete information from the database can be reduced or entirely removed.
It is highly recommended to use a Relational Database that supports true Foreign Keys. See Choosing A Database for further information on this topic.
To use ORM, you must first create a Model that extends ORM. Each model represents the database table, and each object created by the model represents one or more rows from that table:
class User_Model extends ORM {}
Once a model has been defined, a row can loaded from the database:
// Load the user with "id = 1" $user = ORM::factory('user', 1); // Show the user's email address echo $user->email;
Loaded objects can also be modified and saved:
// Change the user's email address $user->email = 'user@example.com'; // Show the new email address echo $user->email; // Save the change $user->save();
There are two ways to load models:
// Creating a new object $user = new User_Model(1); // Using the factory method $user = ORM::factory('user', 1);
Both work exactly the same, but the factory method is chainable, so it is preferred.
The find method can also be used to select a different row on a loaded object:
// Load the user with "id = 2" $user->find(2);
All of the default public and protected methods of ORM are listed here.
Static method used to load ORM objects:
$object = ORM::factory($model_name, $row_id = NULL);
Find executes the database query, gets one row and sets the current object to the result.
$object = ORM::factory('article'); $object->find(1); echo $object->title;
Find_all executes a database query and returns the multiple records using the ORM_Iterator
$articles = ORM::factory('article')->find_all(); foreach($articles as $article) { echo $article->title; }
Save the current object into the database. If the object has no 'id' set it will insert a new record, else it will update.
$object = ORM::factory('article'); $object->find(1); $object->title='New title'; $object->save();
Delete deletes current object or object with the given id.
$article = ORM::factory('article',1); $article->delete(); //OR ORM::factory('article')->delete(1); //Only uses one query instead of two
Returns the current object in array format.
$article = ORM::factory('article',1); $article=$article->as_array(); if(is_array($article)) { echo $article['title']; }
Boolean for seeing whether the current object is loaded
$article = ORM::factory('article',1); if($article->loaded==true) { echo 'loaded'; }
Boolean for seeing whether the current object is saved
$article = ORM::factory('article',1); if($article->saved==false) { echo 'not saved'; } $article->save(); if($article->saved==true) { echo 'saved'; }
| Status | Draft |
|---|
When using relationships and you want related rows, you can pull them up by accessing the relationship as a field example:
$users = $role->users;
or
$roles = $user->roles;
Kohana currently supports three databases that allow for true foreign keys: PostgreSQL, MySQL (using InnoDB tables), and MSSQL. By using one of these databases, relationship integrity is enforced at the the database level.
For example, you can create a table that will automatically delete rows when a foreign key is deleted:
-- roles_users joining table (MySQL) CREATE TABLE roles_users ( user_id smallint(5) UNSIGNED NOT NULL, role_id tinyint(3) UNSIGNED NOT NULL, PRIMARY KEY (user_id,role_id), KEY fk_role_id (role_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ALTER TABLE `roles_users` ADD CONSTRAINT roles_users_ibfk_1 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE, ADD CONSTRAINT roles_users_ibfk_2 FOREIGN KEY (role_id) REFERENCES roles (id) ON DELETE CASCADE;
Use constraints like this will automatically delete the relationship between the user or role objects when either is deleted.
By default, ORM will load using the id column as the identifier for the unique row within the database. However it is possible to allow ORM to load the object from other unique keys. ORM uses a method called unique_key to load data and this method can be overloaded within your ORM model to allow other columns to be used.
The example demonstrates the use of unique_key within an ORM model. The id is checked for data type. If the datatype is not a digit and is a string, the column shortname will be used to load the model.
public function unique_key($id = NULL) { if ( !empty($id) && is_string($id) && !ctype_digit($id) ) { return 'shortname'; } return parent::unique_key($id); }
If you intend to you use custom unique keys within your application, it is a good idea to ensure you correctly index all columns being used as a unique identifier. This will ensure that as your application scales, performance is not adversely effected.
Assuming the homepage record has an ID of 1, including the unique_key method within your ORM model allows the following constructor methods in your code.
// Using the ORM::factory method $my_page = ORM::factory( 'Page', 'homepage' ); // Using the standard constructor $my_other_page = new Page_Model( 'homepage' ); $my_old_method = new Page_Model( 1 );
$my_page, $my_other_page and $my_old_method will all contain the same record.