In our example domain, a blog entry "belongs to" an author (many-to-one). Similarly, a summary "belongs to" a blog (one-to-one). These are reciprocal relationships where the native model is subordinate to the foreign model (in the "has-one" and "has-many" relationships, the native model is superior to the foreign one). To set up this kind of reciprocal relationship for a model, the code looks like this:
<?php
class Acme_Model_Blogs extends Acme_Sql_Model
{
protected function _setup()
{
$this->_belongsTo('author');
}
}
Singular vs. Plural | |
---|---|
The model system assumes all tables (and as a result all model classes) are named in the plural. To facilitate some amount of intuitive naming, the name of the belongs-to related is assumed to be singular, and is inflected to plural when looking for the associated catalog entry. You can change this behavior using the relationship definition keys described below. |
The above code creates a pseudo-property on each blog record called
$author
that gets lazy-loaded by a fetch from
the authors
entry in the model catalog. That is,
each time you ask for a $blog_record->author
, the model
system will fetch the related author record from the database
and place it in $author
for you. The SQL for
the lazy-load looks similar to this:
SELECT author.*
FROM authors AS author
WHERE author.id = {$blog_record->author_id}
LIMIT 1
Lazy vs. Eager Loading | |
---|---|
Beware the dreaded N+1 problem! If you fetch a collection of
10 blog records and loop through them, displaying the
|
In a belongs-to relationship, the foreign key exists in the native model/table. (In all other related types, the foreign key exists in the foreign model/table.) In our example domain, this means the foreign key for the related author is on the blogs table, and maps to the primary key on the authors table.
Foreign Column Naming | |
---|---|
Each model defines for itself what it expects its foreign column name to be when it is used as a foreign model in a relationship. Native models then ask the foreign model what the foreign model expects to use as a foreign column name.
By default, models define their expected foreign column name
as a singular form of their table name, appended with their
primary key. For example, if the model/table name is
"authors", and the primary key on the authors table is "id",
the authors model will default to saying its foreign column
should be called "author_id". You can change that value by
editing the foreign model setup to add
|
Although the Solar model system makes some assumptions about how
tables and foreign keys are named, these assumptions are not
hard-coded. You can define every aspect of the foreign
relationship using an array of key-value pairs passed to the
_belongsTo()
method.
<?php
$this->_belongsTo('name', array(
'option' => 'value',
// ...
));
-
string
foreign_name
-
Normally, the model system expects the foreign model to be in the catalog uner the plural form of the related name. E.g.,
{native} _belongsTo('foreign')
means the catalog name 'foreigns', which will map to some model class.Use the
foreign_name
option to specify a different catalog name for the foreign model. This allows you to name the relationship "foo" (and thereby the record property for the foreign) but use the catalog name "bar" to do the work. (Theforeign_class
option takes precedence overforeign_name
.) -
string
foreign_key
-
Normally, the model system expects the foreign key on the native table to be the same as the one defined by the foreign model's
foreign_col
value.Use the
foreign_key
option to specify a different column in the native table. (This option will be ignored if a specificnative_col
orforeign_col
option is set.) -
array
cols
-
Fetch these columns for the related records.
-
array
conditions
-
Additional conditions on the foreign table when fetching related records. These will be used as WHERE conditions, or as JOIN ON conditions, as appropriate for the kind of fetch being performed (e.g. lazy vs. eager fetch).
-
array
order
-
Additional ORDER clauses when fetching related records.
Note | |
---|---|
The following are some less common, but more advanced and more finely grained, options for defining relationships: |
-
string
foreign_class
-
The class name of the foreign model. Default is the first matching class for the relationship name, as loaded from the parent class stack.
-
string
foreign_alias
-
Aliases the foreign table using this name. Default is the relationship name.
-
string
foreign_col
-
The name of the column to join with in the foreign table, matching against some column in the native table. This forms the foreign half of the relationship condition.
-
string
native_col
-
The name of column to join with in the native table, matching against some column in the foreign table. This forms the native half of the relationship condition.
-
string
native_by
-
The strategy to be used for connecting to native records when eager-fetching: 'wherein', meaning a "WHERE IN (...)" a list of native IDs, or 'select', meaning a join against a sub-SELECT.
-
int
wherein_max
-
When picking a native-by strategy, use 'wherein' for up to this many records in the native result; after this point, use a 'select' strategy.
-
string
merge
-
Indicates the strategy to use for merging joined foreign rows; 'server' means the database will do it via a single SELECT combined into the native fetch (only possible with to-one relationships), whereas 'client' means PHP will do it, using one additional SELECT for the relationship (always for to-many relationships, optionally for to-one relationships) and then merging the rows in a PHP loop.