Understanding Relation Models in Yii
The core of any database driven website is its ability to handle table relations (if that sentence didn’t mean anything to you, you should first do some reading about relational databases, database design, and normalising data: an introduction aimed at textual editors can be found in my article “What digital editors can learn from
print editorial practice.” Literary and Linguistic Computing 24 (2009): 113-125)
One of the really useful things about the Yii MVC framework is the extent to which it allows you to systematise and automate the process of establishing these relations.
The relations()
method
The most important part of this system is in the Yii model classes. When you first scaffold a new website in Yii (see the Yii website for the extremely easy to implement details of how this is done), the gii
utility will build a series of standard model classes, each of which corresponds to a table in your database. A core method, included in every one of these models by default, is relations()
(note: the following is how an empty relation method looks):
/**
* @return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
);
}
To indicate that the table represented by this model is related to other tables in your database, you construct a number of relation key => value pairs using a series of pre-defined terms (see these sections of the Yii Blog Tutorial and of the Yii documentation for details).
You can do this quite easily by hand. But if your database is designed using an engine that supports explicit information about relations (such as MySQL’s InnoDB engine [but not the default MYISAM]), Yii’s scaffolding utility gii
will do much of the work in populating this method automatically.
Here’s an example of a relationset, built for a table in one of my databases (the model is called Journal
and describes a table containing information about journals in a publishing workflow):
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'articles' => array(self::HAS_MANY, 'Article', 'journal_id'),
'editorialInstances' => array(self::HAS_MANY, 'EditorialInstance', 'journal_id'),
);
}
In human terms, this is what the method is indicating:
- the
journal
table is directly related to two other tables in my database:article
andeditorialInstance
(in my database, tables are named using camelCase starting with an initial lowercase letter; Yii’s naming convention is that Model Classes [i.e. the models that describe tables] begin with a capital letter: soArticle
is the model for the database tablearticle
). - the relationship between
journal
and these two tables is- parent to child (
journal
HASarticle
andeditorialInstance
) - one to many (
journal
HASMANY_ article
andeditorialInstance
- parent to child (
- the key names in the relations array
article
*s* andeditorialInstance
*s* are themselves arrays of all the possible values in these child tables - both the child tables contain
journal_id
as a foreign key (FK)
How the relations()
method makes your life easier
The great thing about this relations()
method is that it turns relations into attributes of the model itself. That is to say, attributes of the related tables can be access directly from the model in which they are declared.
This is easiest to see with the BELONGS_TO
(many-to-one child-to-parent) relation, which isn’t instanced above. Here’s an example from the EditorialInstance model, however: i.e. one of the children of Journal in my database:
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'journal' => array(self::BELONGS_TO, 'Journal', 'journal_id'),
'person' => array(self::BELONGS_TO, 'Person', 'person_id'),
);
In this case, you can see tat EditorialInstance is the child of two databases (that is to say it BELONGS_TO
them).
When a BELONGS_TO
relationship is declared in a model, the attributes of the parent table are treated exactly like the attributes of the child table in the declaring model. I.e. let’s say the editorialInstance
table has an attribute called type
and we are referencing it like this in an editorialInstanceView: $data->type
; we can also access all the attributes of the parent tables as well through this same model using language: so the lastName
attribute on person
would be referenced in this same context $data->person->lastName
Relational queries
- A thorough discussion of how to invoke with a good example http://www.yiiframework.com/doc/guide/1.1/en/database.arr#relational-query-options
- relational query with THROUGH
Commenting is closed for this article.