In Doctrine all record relations are being set with {{hasMany}}, {{hasOne}} methods. Doctrine supports almost any kind of database relation from simple one-to-one foreign key relations to join table self-referencing relations.
2007-06-14 18:59:49 +04:00
++ Relation aliases
Doctrine supports relation aliases through {{as}} keyword.
$this->hasOne('Forum_Board as Board', array('local' => 'board_id',
'foreign' => 'id');
2007-06-14 18:59:49 +04:00
}
}
$board = new Board();
$board->Threads[0]->updated = time();
</code>
++ Foreign key associations
+++ One-To-One
Binding One-To-One foreign key associations is done with {{Doctrine_Record::ownsOne()}} and {{Doctrine_Record::hasOne()}} methods. In the following example user owns one email and has one address. So the relationship between user and email is one-to-one composite. The relationship between user and address is one-to-one aggregate.
The {{Email}} component here is mapped to {{User}} component's column {{email_id}} hence their relation is called LOCALKEY relation. On the other hand the {{Address}} component is mapped to {{User}} by it's {{user_id}} column hence the relation between {{User}} and {{Address}} is called FOREIGNKEY relation.
If you are coming from relational database background it may be familiar to you how many-to-many associations are handled: an additional association table is needed.
In many-to-many relations the relation between the two components is always an aggregate relation and the association table is owned by both ends. For example in the case of users and groups when user is being deleted the groups it belongs to are not being deleted and the associations between this user and the groups it belongs to are being deleted.
Sometimes you may not want that association table rows are being deleted when user / group is being deleted. You can override this behoviour by setting the relations to association component (in this case {{Groupuser}}) explicitly.
In the following example we have Groups and Users of which relation is defined as many-to-many. In this case we also need to define an additional class called {{Groupuser}}.
When it comes to handling inheritance Doctrine is very smart. In the following example we have one database table called {{entity}}. Users and groups are both entities and they share the same database table. The only thing we have to make is 3 records ({{Entity}}, {{Group}} and {{User}}).
Doctrine is smart enough to know that the inheritance type here is one-table-many-classes.
One-table-one-class inheritance is the only inheritance type that allows additional fields for inherited classes. As shown in the example above adding additional columns is very easy:
<code type="php">
class TextItem extends Doctrine_Record
{
public function setTableDefinition()
{
$this->hasColumn('topic', 'string', 100);
}
}
class Comment extends TextItem
{
public function setTableDefinition()
{
parent::setTableDefinition();
$this->hasColumn('content', 'string', 300);
}
}
</code>
In one-table-one-class inheritance you don't necessarily have to define additional columns, but in order to make Doctrine create separate tables for each class you'll have to make iterative setTableDefinition() calls.
2007-06-14 18:59:49 +04:00
In the following example we have three database tables called {{entity}}, {{user}} and {{group}}. Users and groups are both entities. The only thing we have to do is write 3 classes ({{Entity}}, {{Group}} and {{User}}) and make iterative {{setTableDefinition}} method calls.
In the following example we have one database table called {{entity}}. Users and groups are both entities and they share the same database table.
The entity table has a column called {{type}} which tells whether an entity is a group or a user. Then we decide that users are type 1 and groups type 2.
A foreign key constraint specifies that the values in a column (or a group of columns) must match the values appearing in some row of another table. In other words foreign key constraints maintain the referential integrity between two related tables.
Say you have the product table with the following definition:
Let's also assume you have a table storing orders of those products. We want to ensure that the order table only contains orders of products that actually exist. So we define a foreign key constraint in the orders table that references the products table:
When exported the class {{Order}} would execute the following SQL:
<code type="sql">
CREATE TABLE orders (
order_id integer PRIMARY KEY,
product_id integer REFERENCES products (id),
quantity integer,
INDEX product_id_idx (product_id)
)
</code>
Now it is impossible to create orders with product_no entries that do not appear in the products table.
We say that in this situation the orders table is the referencing table and the products table is the referenced table. Similarly, there are referencing and referenced columns.
Delete or update the row from the parent table and automatically delete or update the matching rows in the child table. Both ON DELETE CASCADE and ON UPDATE CASCADE are supported. Between two tables, you should not define several ON UPDATE CASCADE clauses that act on the same column in the parent table or in the child table.
//SET NULL// :
Delete or update the row from the parent table and set the foreign key column or columns in the child table to NULL. This is valid only if the foreign key columns do not have the NOT NULL qualifier specified. Both ON DELETE SET NULL and ON UPDATE SET NULL clauses are supported.
//NO ACTION// :
In standard SQL, NO ACTION means no action in the sense that an attempt to delete or update a primary key value is not allowed to proceed if there is a related foreign key value in the referenced table.
//RESTRICT// :
Rejects the delete or update operation for the parent table. NO ACTION and RESTRICT are the same as omitting the ON DELETE or ON UPDATE clause.
In the following example we define two classes, User and Phonenumber with their relation being one-to-many. We also add a foreign key constraint with onDelete cascade action. This means that everytime a users is being deleted its associated phonenumbers will also be deleted.