ar-linkmany

ActiveRecord behavior for saving many-to-many relations

Github星跟踪图

This extension provides support for ActiveRecord many-to-many relation saving.
For example: single "item" may belong to several "groups", each group may be linked with several items.
Unlike regular usage, this extension automatically checks references existence,
removes excluded references and provide support for web form composition.

For license information check the LICENSE-file.

Latest Stable Version
Total Downloads
Build Status

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist yii2tech/ar-linkmany

or add

"yii2tech/ar-linkmany": "*"

to the require section of your composer.json.

Usage

This extension provides support for ActiveRecord many-to-many relation saving.
This support is granted via ActiveRecord behavior. You'll need to attach
it to your ActiveRecord class and point the target "has-many" relation for it:

class Item extends ActiveRecord
{
    public function behaviors()
    {
        return [
            'linkGroupBehavior' => [
                'class' => LinkManyBehavior::className(),
                'relation' => 'groups', // relation, which will be handled
                'relationReferenceAttribute' => 'groupIds', // virtual attribute, which is used for related records specification
            ],
        ];
    }

    public static function tableName()
    {
        return 'Item';
    }

    public function getGroups()
    {
        return $this->hasMany(Group::className(), ['id' => 'groupId'])->viaTable('ItemGroup', ['itemId' => 'id']);
    }
}

Being attached adds a virtual proprty to the owner ActiveRecord, which
name is determined by . You will be able to
specify related models primary keys via this attribute:

// Pick up related model primary keys:
$groupIds = Group::find()
    ->select('id')
    ->where(['isActive' => true])
    ->column();

$item = new Item();
$item->groupIds = $groupIds; // setup related models references
$item->save(); // after main model is saved referred related models are linked

The above example is equal to the following code:

$groups = Group::find()
    ->where(['isActive' => true])
    ->all();

$item = new Item();
$item->save();

foreach ($groups as $group) {
    $item->link('groups', $group);
}

Attention: do NOT declare relationReferenceAttribute attribute in the owner ActiveRecord class. Make sure it does
not conflict with any existing owner field or virtual property.

Virtual property declared via relationReferenceAttribute serves not only for saving. It also contains existing references
for the relation:

$item = Item::findOne(15);
var_dump($item->groupIds); // outputs something like: array(2, 5, 11)

You may as well edit the references list for existing record, while saving linked records will be synchronized:

$item = Item::findOne(15);
$item->groupIds = array_merge($item->groupIds, [17, 21]);
$item->save(); // groups "17" and "21" will be added

$item->groupIds = [5];
$item->save(); // all groups except "5" will be removed

Note: if attribute declared by relationReferenceAttribute is never invoked for reading or writing,
it will not be processed on owner saving. Thus it will not affect pure owner saving.

Creating relation setup web interface

The main purpose of is support for creating
many-to-many setup web interface. All you need to do is declare a validation rule for this virtual property in
your ActiveRecord, so its value can be collected from the request:

class Item extends ActiveRecord
{
    public function rules()
    {
        return [
            ['groupIds', 'safe'] // ensure 'groupIds' value can be collected on `populate()`
            // ...
        ];
    }

    // ...
}

Inside the view file you should use relationReferenceAttribute property as an attribute name for the form input:

<?php
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\widgets\ActiveForm;

/* @var $model Item */
?>
<?php $form = ActiveForm::begin(); ?>

<?= $form->field($model, 'name'); ?>
<?= $form->field($model, 'price'); ?>

<?= $form->field($model, 'groupIds')->checkboxList(ArrayHelper::map(Group::find()->all(), 'id', 'name')); ?>

<div class="form-group">
    <?= Html::submitButton('Save', ['class' => 'btn btn-primary']) ?>
</div>

<?php ActiveForm::end(); ?>

Inside the controller you don't need any special code:

use yii\web\Controller;

class ItemController extends Controller
{
    public function actionCreate()
    {
        $model = new Item();

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->redirect(['view']);
        }

        return $this->render('create', [
            'model' => $model,
        ]);
    }

    // ...
}

概览

名称与所有者yii2tech/ar-linkmany
主编程语言PHP
编程语言PHP (语言数: 1)
平台
许可证Other
发布数4
最新版本名称1.0.3 (发布于 )
第一版名称1.0.0 (发布于 )
创建于2015-08-25 14:04:52
推送于2019-07-03 11:35:45
最后一次提交2019-07-03 14:35:36
星数86
关注者数9
派生数17
提交数23
已启用问题?
问题数13
打开的问题数0
拉请求数1
打开的拉请求数0
关闭的拉请求数1
已启用Wiki?
已存档?
是复刻?
已锁定?
是镜像?
是私有?
去到顶部