PHPackages                             industi/yii2-many-to-many - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Validation &amp; Sanitization](/categories/validation)
4. /
5. industi/yii2-many-to-many

ActiveYii2-extension[Validation &amp; Sanitization](/categories/validation)

industi/yii2-many-to-many
=========================

Many-to-many ActiveRecord relation for Yii 2 framework

0.2.1(10y ago)116BSD-3-ClausePHP

Since Apr 12Pushed 7y ago1 watchersCompare

[ Source](https://github.com/industi/yii2-many-to-many)[ Packagist](https://packagist.org/packages/industi/yii2-many-to-many)[ Docs](https://github.com/arogachev/yii2-many-to-many)[ RSS](/packages/industi-yii2-many-to-many/feed)WikiDiscussions master Synced yesterday

READMEChangelogDependencies (3)Versions (4)Used By (0)

Yii 2 Many-to-many
==================

[](#yii-2-many-to-many)

Implementation of [Many-to-many relationship](http://en.wikipedia.org/wiki/Many-to-many_%28data_model%29)for Yii 2 framework.

[![Latest Stable Version](https://camo.githubusercontent.com/3929f3b15b0d0b2957cbb0269bd83bc2a87445c30e9602a028071ac4286f247c/68747470733a2f2f706f7365722e707567782e6f72672f61726f6761636865762f796969322d6d616e792d746f2d6d616e792f762f737461626c65)](https://packagist.org/packages/arogachev/yii2-many-to-many)[![Total Downloads](https://camo.githubusercontent.com/88152847870cdc27a5c2a32a38f945df310c346b3ee18dd70b3f680e12390833/68747470733a2f2f706f7365722e707567782e6f72672f61726f6761636865762f796969322d6d616e792d746f2d6d616e792f646f776e6c6f616473)](https://packagist.org/packages/arogachev/yii2-many-to-many)[![Latest Unstable Version](https://camo.githubusercontent.com/1415ce77eb67258672a2ae22c7586a9c06d9f20c6e077485c63321c0bd8fbe42/68747470733a2f2f706f7365722e707567782e6f72672f61726f6761636865762f796969322d6d616e792d746f2d6d616e792f762f756e737461626c65)](https://packagist.org/packages/arogachev/yii2-many-to-many)[![License](https://camo.githubusercontent.com/3e8bc43fc1458392598fe87f48f8f7202c6b424437e2c895cdf9986439e3049c/68747470733a2f2f706f7365722e707567782e6f72672f61726f6761636865762f796969322d6d616e792d746f2d6d616e792f6c6963656e7365)](https://packagist.org/packages/arogachev/yii2-many-to-many)

- [Installation](#installation)
- [Features](#features)
- [Creating editable attribute](#creating-editable-attribute)
- [Attaching and configuring behavior](#attaching-and-configuring-behavior)
- [Filling relations](#filling-relations)
- [Saving relations without massive assignment](#saving-relations-without-massive-assignment)
- [Adding attribute as safe](#adding-attribute-as-safe)
- [Adding control to view](#adding-control-to-view)
- [Relation features](#relation-features)
- [Running tests](#running-tests)

Installation
------------

[](#installation)

The preferred way to install this extension is through [composer](http://getcomposer.org/download/).

Either run

```
php composer.phar require --prefer-dist arogachev/yii2-many-to-many

```

or add

```
"arogachev/yii2-many-to-many": "0.2.*"

```

to the require section of your `composer.json` file.

Features
--------

[](#features)

- Configuring using existing `hasMany` relations
- Multiple relations
- No extra queries. For example, if initially model has 100 related records, after adding just one, exactly one row will be inserted. If nothing was changed, no queries will be executed.
- Auto filling of editable attribute
- Validator for checking if the received list is valid

Creating editable attribute
---------------------------

[](#creating-editable-attribute)

Simply add public property to your `ActiveRecord` model like this:

```
/**
 * @var array
 */
public $editableUsers = [];
```

It will store primary keys of related records during update.

Attaching and configuring behavior
----------------------------------

[](#attaching-and-configuring-behavior)

First way is to explicitly specify all parameters:

```
use arogachev\ManyToMany\behaviors\ManyToManyBehavior;

/**
 * @inheritdoc
 */
public function behaviors()
{
    return [
        [
            'class' => ManyToManyBehavior::className(),
            'relations' => [
                [
                    'editableAttribute' => 'editableUsers', // Editable attribute name
                    'table' => 'tests_to_users', // Name of the junction table
                    'ownAttribute' => 'test_id', // Name of the column in junction table that represents current model
                    'relatedModel' => User::className(), // Related model class
                    'relatedAttribute' => 'user_id', // Name of the column in junction table that represents related model
                ],
            ],
        ],
    ];
}
```

But more often we also need to display related models, so it's better to define relation for that and use it for both display and behavior configuration. Both ways (`via` and `viaTable`) are considered valid:

Using `viaTable`:

```
/**
 * @return \yii\db\ActiveQuery
 */
public function getUsers()
{
    return $this->hasMany(User::className(), ['id' => 'user_id'])
        ->viaTable('tests_to_users', ['test_id' => 'id'])
        ->orderBy('name');
}
```

Using `via` (requires additional model for junction table):

```
/**
 * @return \yii\db\ActiveQuery
 */
public function getTestUsers()
{
    return $this->hasMany(TestUser::className(), ['test_id' => 'id']);
}

/**
 * @return \yii\db\ActiveQuery
 */
public function getUsers()
{
    return $this->hasMany(User::className(), ['id' => 'user_id'])
        ->via('testUsers')
        ->orderBy('name');
}
```

Order is not required.

Then just pass the name of this relation and all other parameters will be fetched automatically.

```
/**
 * @inheritdoc
 */
public function behaviors()
{
    return [
        [
            'class' => ManyToManyBehavior::className(),
            'relations' => [
                [
                    'name' => 'users',
                    // This is the same as in previous example
                    'editableAttribute' => 'editableUsers',
                ],
            ],
        ],
    ];
}
```

Additional many-to-many relations can be added exactly the same. Note that even for one relation you should declare it as a part of `relations` section.

Filling relations
-----------------

[](#filling-relations)

By default, `editableAttribute` of each found model will be populated with ids of related models (eager loading is used). If you want more manual control, prevent extra queries, disable `autoFill` option:

```
'autoFill' => false,
```

and fill it only when it's needed, for example in `update` action of controller. This is recommended way of using.

```
public function actionUpdate($id)
{
    $model = $this->findModel($id);
    $model->getManyToManyRelation('users')->fill();
    // ...
}
```

Alternatively you can specify conditions of filling in closure:

```
'autoFill' => function ($model) {
    return $model->scenario == Test::SCENARIO_UPDATE; // boolean value
}
```

Even it's possible to do something like this:

```
'autoFill' => function ($model) {
    return Yii::$app->controller->route == 'tests/default/update';
}
```

but it's not recommended for usage because model is not appropriate place for handling routes.

Saving relations without massive assignment
-------------------------------------------

[](#saving-relations-without-massive-assignment)

When creating model:

```
$model = new Test;
$model->editableUsers = [1, 2];
$model->save();
```

When updating model (`'autoFill' => true`):

```
$model = new Test;
$model->editableUsers = [1, 2];
$model->save();
```

When updating model (`'autoFill' => false`, manual filling):

```
$model = new Test;
$model->getManyToManyRelation('users')->fill();
var_dump($model->editableUsers) // [1, 2]
$model->editableUsers = [1, 2, 3];
$model->save();
```

When updating model (`'autoFill' => false`, without manual filling):

```
$model = new Test;
var_dump($model->editableUsers) // empty array
$model->save();
```

In this case many-to-many relations will stay untouched.

Adding attribute as safe
------------------------

[](#adding-attribute-as-safe)

Add editable attribute to model rules for massive assignment.

Either mark it as safe at least:

```
public function rules()
{
    ['editableUsers', 'safe'],
}
```

Or use custom validator:

```
use arogachev\ManyToMany\validators\ManyToManyValidator;

public function rules()
{
    ['editableUsers', ManyToManyValidator::className()],
}
```

Validator checks list for being array and containing only primary keys presented in related model. It can not be used without attaching `ManyToManyBehavior`.

Adding control to view
----------------------

[](#adding-control-to-view)

Add control to view for managing related list. Without extensions it can be done with multiple select:

```
