Relating Models
Usage
The Orm allows for both eager and lazy-loading of relationships. Eager loading means that some (or all)
relations are fetched in the original query. Lazy loading means that the relations aren't fetched until
you request them.
// eager loading, using joins:
$post = Model_Post::find('all', array('related' => array('comments')));
// or
$post = Model_Post::find()->related('comments')->get();
// $post->comments is available without any further querying after this
// or use lazy loading, it won't use joins but query a relation once requested
// first get a "post", 1 query without join
$post = Model_Post::find('first');
// now request the comments (not yet loaded), which will do another query without join automaticly
$comments = $post->comments;
Basic config
$_has_many = array('comments');
This example, if specified in Model_Article, enables fetching of an array of
Model_Comment objects which have the field article_id matching the primary key of
a given Article instance through the property comments.
Fully configured
$_has_many = array('comments' => array(
'model_to' => 'Model_Fancy_Comment',
'key_from' => 'article_id',
'key_to' => 'parent_article_id',
'cascade_save' => true,
'cascade_delete' => false,
// there are some more options for specific relation types
));
In the basic example, Orm automatically assumes the model name and field mapping. This example
explicitly specifies the class name of the target model, the fields used to relate them, and whether
actions performed on the current object should be cascaded to the target. It will return an array of
Model_Fancy_Comment object where the comment's parent_article_id field
corresponds to the current object's article_id. When saving an object the operation is
also performed on its loaded relations, deleting isn't cascaded by default but can be if you switch
this on.
Configuration Options
All of the configurations are optional when using the most common naming conventions.
model_to |
Calculated from alias |
If specified, must the the full class name of the target model (ex. Model_Comment).
By default, this value is formed by prepending 'Model_' to the singular form of the alias
(ex. 'comments' becomes 'Model_Comment'), it is also expected to be in the same namespace as
the current model. |
key_from |
The key used for the relation in the current model (Usually id) |
Allows mapping the target model to an arbitrary field in the current model's table |
key_to |
Calculated from the current model name |
By default, a relationship from a Model_Article to many Model_Comments
would use the field article_id in the comments table |
cascade_save |
bool true |
You can override these options at runtime by passing true as the first
argument when calling save() or delete() on the originating model. |
cascade_delete |
bool false |
Relation types
The Orm supports the following relationship types natively:
- Belongs To
Has the primary key of the relation keps in its table, belongs to 1 related object.
- Has One
Has its primary key saved in one other row of another table (which belongs to this), has 1
related object.
- Has Many
Has its primary key saved in many other rows of another table (which belong to this one), has
many related objects.
- Many to Many
Have their primary keys saved in a table in between which keeps pairs of primary keys from both
tables. Have and belong to many objects.
- Many Through
Same as "Many to Many" but have a model relating them to each other instead of just a 2-column
table.
Belongs To
To be written.
Full config example with defaults as values
// in a Model_Comment which belong to a post
$_belongs_to = array(
'post' => array(
'key_from' => 'comment_id',
'model_to' => 'Model_Post',
'key_to' => 'id',
'cascade_save' => true,
'cascade_delete' => false,
)
);
Has One
Specifies a one-to-one relationship to another model. The target model must include a "Belongs To"
reference to the current model to allow the inverse relationship.
Full config example with defaults as values
// in a Model_User which has one profile
$_has_one = array(
'profile' => array(
'key_from' => 'id',
'model_to' => 'Model_Profile',
'key_to' => 'user_id',
'cascade_save' => true,
'cascade_delete' => false,
)
);
Has Many
Specifies a one-to-many relationship to another model. The target model must include a "Belongs To"
reference to the current model to allow the inverse relationship.
Full config example with defaults as values
// in a Model_Post which has many comments
$_has_many = array(
'comments' => array(
'key_from' => 'id',
'model_to' => 'Model_Comment',
'key_to' => 'post_id',
'cascade_save' => true,
'cascade_delete' => false,
)
);
Many to Many
To be written.
Full config example with defaults as values
// in a Model_Post which has and belongs to many Users
// = multiple posts per user and multiple users (authors) per post
$_many_many = array(
'users' => array(
'key_from' => 'id',
'key_through_from' => 'post_id', // column 1 from the table in between, should match a posts.id
'table_through' => 'posts_users', // both models plural without prefix in alphabetical order
'key_through_to' => 'user_id', // column 2 from the table in between, should match a users.id
'model_to' => 'Model_User',
'key_to' => 'id',
'cascade_save' => true,
'cascade_delete' => false,
)
);
Many Through
To be written.
Saving/deleting these are not yet supported directly, need to be done through the
model connecting them.
Full config example with defaults as values
// in a Model_Post which has and belongs to many Users with a model in between
// = multiple posts per user and multiple users (authors) per post
$_many_through = array(
'users' => array(
'key_from' => 'id',
'key_through_from' => 'post_id', // column 1 from the table in between, should match a posts.id
'model_through' => 'Model_Posts_Users', // both models plural without prefix in alphabetical order
'key_through_to' => 'user_id', // column 2 from the table in between, should match a users.id
'model_to' => 'Model_User',
'key_to' => 'id',
'cascade_save' => true,
'cascade_delete' => false,
)
);