You are currently reading the 1.2 documentation. Switch to 2.2  2.1  2.0 

Introduction

In Doctrine all record relations are being set with Doctrine_Record::hasMany, Doctrine_Record::hasOne methods. Doctrine supports almost all kinds of database relations from simple one-to-one foreign key relations to join table self-referencing relations.

Unlike the column definitions the Doctrine_Record::hasMany and Doctrine_Record::hasOne methods are placed within a method called setUp(). Both methods take two arguments: the first argument is a string containing the name of the class and optional alias, the second argument is an array consisting of relation options. The option array contains the following keys:

Name Optional Description
local No The local field of the relation. Local field is the linked field in the defining class.
foreign No The foreign field of the relation. Foreign field is the linked field in the linked class.
refClass Yes The name of the association class. This is only needed for many-to-many associations.
owningSide Yes Set to boolean true to indicate the owning side of the relation. The owning side is the side that owns the foreign key. There can only be one owning side in an association between two classes. Note that this option is required if Doctrine can't guess the owning side or it's guess is wrong. An example where this is the case is when both 'local' and 'foreign' are part of the identifier (primary key). It never hurts to specify the owning side in this way.
onDelete Yes The onDelete integrity action that is applied on the foreign key constraint when the tables are created by Doctrine.
onUpdate Yes The onUpdate integrity action that is applied on the foreign key constraint when the tables are created by Doctrine.
cascade Yes Specify application level cascading operations. Currently only delete is supported

So lets take our first example, say we have two classes Forum_Board and Forum_Thread. Here Forum_Board has many Forum_Threads, hence their relation is one-to-many. We don't want to write Forum_ when accessing relations, so we use relation aliases and use the alias Threads.

First lets take a look at the Forum_Board class. It has three columns: name, description and since we didn't specify any primary key, Doctrine auto-creates an id column for it.

We define the relation to the Forum_Thread class by using the hasMany() method. Here the local field is the primary key of the board class whereas the foreign field is the board_id field of the Forum_Thread class.

// models/Forum_Board.php

class Forum_Board extends Doctrine_Record
{
    public function setTableDefinition()
    {
        $this->hasColumn('name', 'string', 100);
        $this->hasColumn('description', 'string', 5000);
    }

    public function setUp()
    {
        $this->hasMany('Forum_Thread as Threads', array(
                'local' => 'id',
                'foreign' => 'board_id'
            )
        );
    }
}

Notice the as keyword being used above. This means that the Forum_Board has a many relationship defined to Forum_Thread but is aliased as Threads.

Here is the same example in YAML format. You can read more about YAML in the YAML Schema Files chapter:

---
# schema.yml

# ...
Forum_Board:
  columns:
    name: string(100)
    description: string(5000)

Then lets have a peek at the Forum_Thread class. The columns here are irrelevant, but pay attention to how we define the relation. Since each Thread can have only one Board we are using the hasOne() method. Also notice how we once again use aliases and how the local column here is board_id while the foreign column is the id column.

// models/Forum_Thread.php

class Forum_Thread extends Doctrine_Record
{
    public function setTableDefinition()
    {
        $this->hasColumn('user_id', 'integer');
        $this->hasColumn('board_id', 'integer');
        $this->hasColumn('title', 'string', 200);
        $this->hasColumn('updated', 'integer', 10);
        $this->hasColumn('closed', 'integer', 1);
    }

    public function setUp()
    {
        $this->hasOne('Forum_Board as Board', array(
                'local' => 'board_id',
                'foreign' => 'id'
            )
        );

        $this->hasOne('User', array(
                'local' => 'user_id',
                'foreign' => 'id'
            )
        );
    }
}

Here is the same example in YAML format. You can read more about YAML in the YAML Schema Files chapter:

---
# schema.yml

# ...
Forum_Thread:
  columns:
    user_id: integer
    board_id: integer
    title: string(200)
    updated: integer(10)
    closed: integer(1)
  relations:
    User:
      local: user_id
      foreign: id
      foreignAlias: Threads
    Board:
      class: Forum_Board
      local: board_id
      foreign: id
      foreignAlias: Threads

Now we can start using these classes. The same accessors that you've already used for properties are all available for relations.

First lets create a new board:

// test.php

// ...
$board = new Forum_Board();
$board->name = 'Some board';

Now lets create a new thread under the board:

// test.php

// ...
$board->Threads[0]->title = 'new thread 1';
$board->Threads[1]->title = 'new thread 2';

Each Thread needs to be associated to a user so lets create a new User and associate it to each Thread:

$user = new User();
$user->username = 'jwage';
$board->Threads[0]->User = $user;
$board->Threads[1]->User = $user;

Now we can save all the changes with one call. It will save the new board as well as its threads:

// test.php

// ...
$board->save();

Lets do a little inspecting and see the data structure that is created when you use the code from above. Add some code to test.php to output an array of the object graph we've just populated:

print_r($board->toArray(true));

The Doctrine_Record::toArray() takes all the data of a Doctrine_Record instance and converts it to an array so you can easily inspect the data of a record. It accepts an argument named $deep telling it whether or not to include relationships. In this example we have specified {[true]} because we want to include the Threads data.

Now when you execute test.php with PHP from your terminal you should see the following:

$ php test.php
Array
(
    [id] => 2
    [name] => Some board
    [description] =>
    [Threads] => Array
        (
            [0] => Array
                (
                    [id] => 3
                    [user_id] => 1
                    [board_id] => 2
                    [title] => new thread 1
                    [updated] =>
                    [closed] =>
                    [User] => Array
                        (
                            [id] => 1
                            [is_active] => 1
                            [is_super_admin] => 0
                            [first_name] =>
                            [last_name] =>
                            [username] => jwage
                            [password] =>
                            [type] =>
                            [created_at] => 2009-01-20 16:41:57
                            [updated_at] => 2009-01-20 16:41:57
                        )

                )

            [1] => Array
                (
                    [id] => 4
                    [user_id] => 1
                    [board_id] => 2
                    [title] => new thread 2
                    [updated] =>
                    [closed] =>
                    [User] => Array
                        (
                            [id] => 1
                            [is_active] => 1
                            [is_super_admin] => 0
                            [first_name] =>
                            [last_name] =>
                            [username] => jwage
                            [password] =>
                            [type] =>
                            [created_at] => 2009-01-20 16:41:57
                            [updated_at] => 2009-01-20 16:41:57
                        )

                )

        )

)

Notice how the auto increment primary key and foreign keys are automatically set by Doctrine internally. You don't have to worry about the setting of primary keys and foreign keys at all!


Questions and Feedback

If you find a problem with the documentation or have a suggestion, please register and open a ticket.

If you need support or have a technical question, you can post to the user mailing-list.