Relationships

  1. Introduction
  2. One to one
  3. One to many
  4. Many to many

Introduction

The relationships between tables can be described by adding methods to your model class and utilize the hasOne, hasMany, belongsTo and belongsToMany, inside those methods, to define the type of the relationship between two models.

The related models can be then retrieved from a model instance by getting the value of the property that has the same name as the relationship method.

class User extends BaseModel
{
    // Define a relationship 
    public function articles()
    {
        return $this->hasMany('Article');
    }
}

// ...

$user = User::find(1);

// Get the related models
foreach($user->articles as $article)
{
    echo $article->title, PHP_EOL;
}

One to one

A one-to-one relationship is a relation where each record of a table has a single related record into another table. For example a User might be associated with a Profile. Defining the relationship between User and Profile can be done by placing a profile method on the User model. The profile method must return the result of calling the hasOne method.

class Profile extends BaseModel
{
    // ...
}

class User extends BaseModel
{
    public function profile()
    {
        return $this->hasOne('Profile');
    }
}

// ...

$user = User::find(1);

echo $user->profile->description;

The first argument passed to the hasOne method must be the class name of the related model. If the model class is under a namespace, then the namespace must be included as well.

return $this->hasOne('\My\Namespace\Profile');

Opis Database ORM assumes that the foreign key of the relationship is based on the related model’s name. In this particular case, the Profile model is assumed to have a user_id foreign key. If the related model has a differently named foreign key, you can specify this by passing the foreign key’s name as a second argument to the hasOne method.

return $this->hasOne('Profile', 'foreign_key');

The inverse of the relation

Defining the inverse of a one-to-one relationship is done by using the belongsTo method.

class Profile extends BaseModel
{
    public function user()
    {
        return $this->belongsTo('User');
    }
}

class User extends BaseModel
{
    public function profile()
    {
        return $this->hasOne('Profile');
    }
}

// ...

$profile = Profile::find(1);

echo $profile->user->name;

The first argument passed to the belongsTo method must be the class name of the parent model. If the model class is under a namespace, then the namespace must be included as well.

return $this->belongsTo('\My\Namespace\User');

If the model foreign key’s name is different from the name assumed by Opis Database (parent table name + _id suffix), than you can specify the foreign key’s name by passing it as the second argument to the belongsTo method.

return $this->belongsTo('User', 'foreign_key');

One to many

A one-to-many relationship is a relation where each record of a table might have multiple related records into another table. For example, a User might be associated with multiple Articles. Defining the relationship between User and Article can be done by placing an articles method on the User model. The articles method must return the result of calling the hasMany method.

class Article extends BaseModel
{
    // ...
}

class User extends BaseModel
{
    public function articles()
    {
        return $this->hasMany('Article');
    }
}

// ...

$user = User::find(1);

foreach($user->articles as $article)
{
    echo $article->title, PHP_EOL;
}

The first argument passed to the hasMany method must be the class name of the related model. If the model class is under a namespace, then the namespace must be included as well.

return $this->hasMany('\My\Namespace\Article');

If the related model’s foreign key doesn’t follow the Opis Database naming convention (parent table name + _id suffix), you may specify the foreign key’s name by passing it as the second argument to the hasMany method.

return $this->hasMany('Article', 'foreign_key');

The inverse of the relation

As in the case of the one-to-one relationships, the inverse of a one-to-many relationship can be defined by using the belongsTo method.

class Article extends BaseModel
{
    public function author()
    {
        return $this->belongsTo('User');
    }
}

class User extends BaseModel
{
    public function articles()
    {
        return $this->hasMany('Article');
    }
}

// ...

$article = Article::find(1);

echo $article->author->name;

Many to many

A many-to-many relationship is a relation where a record from a table might share with other records from the same table, multiple related records that are stored into another table.

An example of such a relationship is a user with many roles whom also might be shared by other users. In order to define such a relationship, there must be a junction table between the two related tables.

Defining a many-to-many relationship is done by using the belongsToMany method. The method takes as an argument the full class name(including the namespace) of the related model.

class User extends BaseModel
{
    public function roles()
    {
        return $this->belongsToMany('Role');
    }
}

class Role extends BaseModel
{
    public function users()
    {
        return $this->belongsToMany('User');
    }
}

// ...

$user = User::find(1);

foreach($user->roles as $role)
{
    echo $role->name, PHP_EOL:
}

$role = Role::find(1);

foreach($role->users as $user)
{
    echo $user->name, PHP_EOL;
}

Naming conventions

The junction table name is assumed to be formed from the names of the related tables taken in alphabetical order and separated by an underscore. So, if we have two related tables named foo and bar, the junction table will be bar_foo. If the name of your junction table doesn’t follow this naming convention, then you must pass the name of your junction table as the third argument to the belongsToMany method.

return $this->belongsToMany('Role', null, 'junction_table');

The junction table must define two columns containing foreign keys to the related tables. If we have to related tables foo and bar, the column names must be foo_id and bar_id.

If the foreign key that points from the junction table back to the model doesn’t follow the naming convention, you must pass the name of the foreign key as the second argument to the belongsToMany method.

return $this->belongsToMany('Role', 'fk_user');

If the foreign key that points from the junction table to the related model doesn’t follow the naming convention, you must pass the name of the foreign key as the fourth argument to the belongsToMany method.

return $this->belongsToMany('Role', null, null, 'fk_role');