Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 62 additions & 73 deletions en/orm/associations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,52 +30,54 @@ association in our ArticlesTable::

class ArticlesTable extends Table
{

public function initialize(array $config)
{
$this->belongsTo('Authors');
}

}

The simplest form of any association setup takes the table alias you want to
associate with. By default all of the details of an association will use the
CakePHP conventions. If you want to customize how your associations are handled
you can do so with the second parameter::
you can modify them with setters::

class ArticlesTable extends Table
{

public function initialize(array $config)
{
$this->belongsTo('Authors', [
'className' => 'Publishing.Authors',
'foreignKey' => 'authorid',
'propertyName' => 'person'
]);
$this->belongsTo('Authors')
->setName('Publishing.Authors')
->setForeignKey('authorid')
->setProperty('person');
}

}

You can also use arrays to customize your associations::
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs should note that this is deprecated and not recommended.

"For the sake of backwards compatibility you can also use..."

Copy link
Member Author

@dereuromark dereuromark Nov 2, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It kind of does below it. As of right now it is not deprecated by the way, only less recommended.
And it probably won't either as long as mass assignment as documented on the same page still is around :)

Copy link
Contributor

@inoas inoas Nov 2, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd start the block with that info so that it is clear what you are reading is about out-of-date interfaces.

And why wouldn't it be deprecated? Are there 4 states now: recommended, non-recommended, deprecated, removed? Or can we cut it down to default, deprecated, removed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is more a personal preference at this point.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So won't the array interface be deprecated for 4.0?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can decide on that at a later point in time IMO.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I'd prefer to keep the array config style. I know I'm an outlier in that preference though.


$this->belongsTo('Authors', [
'className' => 'Publishing.Authors',
'foreignKey' => 'authorid',
'propertyName' => 'person'
]);

Arrays however do not offer the typehinting and autocomplete benefit the fluent interface does.

The same table can be used multiple times to define different types of
associations. For example consider a case where you want to separate
approved comments and those that have not been moderated yet::

class ArticlesTable extends Table
{

public function initialize(array $config)
{
$this->hasMany('Comments', [
'className' => 'Comments',
'conditions' => ['approved' => true]
]);

$this->hasMany('UnapprovedComments', [
'className' => 'Comments',
'conditions' => ['approved' => false],
'propertyName' => 'unapproved_comments'
]);
$this->hasMany('Comments')
->setName('Comments')
->setConditions(['approved' => true]);

$this->hasMany('UnapprovedComments')
->setName('Comments')
->setConditions(['approved' => false])
->setProperty('unapproved_comments');
}
}

Expand All @@ -85,16 +87,13 @@ self-associated tables to create parent-child relationships::

class CategoriesTable extends Table
{

public function initialize(array $config)
{
$this->hasMany('SubCategories', [
'className' => 'Categories',
]);
$this->hasMany('SubCategories')
->setName('Categories');

$this->belongsTo('ParentCategories', [
'className' => 'Categories',
]);
$this->belongsTo('ParentCategories')
->setName('Categories')
}
}

Expand All @@ -104,18 +103,16 @@ table names indexed by association type as an argument::

class PostsTable extends Table
{

public function initialize(array $config)
{
$this->addAssociations([
'belongsTo' => [
'Users' => ['className' => 'App\Model\Table\UsersTable']
],
'hasMany' => ['Comments'],
'belongsToMany' => ['Tags']
]);
}

public function initialize(array $config)
{
$this->addAssociations([
'belongsTo' => [
'Users' => ['className' => 'App\Model\Table\UsersTable']
],
'hasMany' => ['Comments'],
'belongsToMany' => ['Tags']
]);
}
}

Each association type accepts multiple associations where the keys are the
Expand Down Expand Up @@ -168,11 +165,10 @@ records::
{
public function initialize(array $config)
{
$this->hasOne('Addresses', [
'className' => 'Addresses',
'conditions' => ['Addresses.primary' => '1'],
'dependent' => true
]);
$this->hasOne('Addresses')
->setName('Addresses')
->setConditions(['Addresses.primary' => '1'])
->setDependent(true);
}
}

Expand Down Expand Up @@ -264,10 +260,9 @@ syntax::

public function initialize(array $config)
{
$this->belongsTo('Users', [
'foreignKey' => 'user_id',
'joinType' => 'INNER',
]);
$this->belongsTo('Users')
->setForeignKey('user_id')
->setJoinType('INNER');
}
}

Expand Down Expand Up @@ -347,40 +342,37 @@ We can also define a more specific relationship using array syntax::

public function initialize(array $config)
{
$this->hasMany('Comments', [
'foreignKey' => 'article_id',
'dependent' => true,
]);
$this->hasMany('Comments')
->setForeignKey('article_id')
->setDependent(true);
}
}

Sometimes you may want to configure composite keys in your associations::

// Within ArticlesTable::initialize() call
$this->hasMany('Reviews', [
'foreignKey' => [
$this->hasMany('Reviews')
->setForeignKey([
'article_id',
'article_hash'
]
]);
]);

Relying on the example above, we have passed an array containing the desired
composite keys to ``foreignKey``. By default the ``bindingKey`` would be
composite keys to ``setForeignKey()``. By default the ``bindingKey`` would be
automatically defined as ``id`` and ``hash`` respectively, but let's assume that
you need to specify different binding fields than the defaults, you can setup it
manually in your ``bindingKeys`` array::
manually with ``setBindingKey()``::

// Within ArticlesTable::initialize() call
$this->hasMany('Reviews', [
'foreignKey' => [
$this->hasMany('Reviews')
->setForeignKey([
'article_id',
'article_hash'
],
'bindingKey' => [
])
->setBindingKey([
'whatever_id',
'whatever_hash'
]
]);
]);

It is important to note that ``foreignKey`` values refers to the **reviews**
table and ``bindingKey`` values refers to the **articles** table.
Expand Down Expand Up @@ -505,9 +497,8 @@ syntax::

public function initialize(array $config)
{
$this->belongsToMany('Tags', [
'joinTable' => 'articles_tags',
]);
$this->belongsToMany('Tags')
->setJoinTable('articles_tags');
}
}

Expand Down Expand Up @@ -621,9 +612,8 @@ following models. ::
{
public function initialize(array $config)
{
$this->belongsToMany('Courses', [
'through' => 'CourseMemberships',
]);
$this->belongsToMany('Courses')
->setThrough('CourseMemberships');
}
}

Expand All @@ -632,8 +622,7 @@ following models. ::
public function initialize(array $config)
{
$this->belongsToMany('Students', [
'through' => 'CourseMemberships',
]);
->setThrough('CourseMemberships');
}
}

Expand Down