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?
已存檔?
是復刻?
已鎖定?
是鏡像?
是私有?
去到頂部