dfware/ar-linkmany

为Yii2 ActiveRecord中的多对多关系保存提供支持

资助包维护!
klimov-paul
Patreon

安装: 49

依赖: 0

建议者: 0

安全: 0

星标: 0

关注者: 0

分支: 17

开放问题: 0

类型:yii2-extension

1.0.0 2023-09-27 17:50 UTC

This package is auto-updated.

Last update: 2024-09-27 19:55:32 UTC


README

安装此扩展的首选方式是通过composer

运行

composer require dfware/ar-linkmany

或添加

"dfware/ar-linkmany": "*"

到您的composer.json文件的require部分。

使用方法

此扩展为ActiveRecord的多对多关系保存提供支持。这种支持是通过[[\yii2tech\ar\linkmany\LinkManyBehavior]] ActiveRecord行为提供的。您需要将其附加到您的ActiveRecord类上,并指定目标"has-many"关系

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']);
    }
}

附加[[\yii2tech\ar\linkmany\LinkManyBehavior]]会在所有者ActiveRecord中添加一个虚拟属性,其名称由[[\yii2tech\ar\linkmany\LinkManyBehavior::$relationReferenceAttribute]]确定。您可以通过此属性指定相关模型的主键

// 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

上面的示例等同于以下代码

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

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

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

注意:不要在所有者ActiveRecord类中声明relationReferenceAttribute属性。确保它不会与任何现有所有者字段或虚拟属性冲突。

通过relationReferenceAttribute声明的虚拟属性不仅用于保存,它还包含现有关系的引用

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

您还可以在保存链接记录的同时编辑现有记录的引用列表

$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

注意:如果通过relationReferenceAttribute声明的属性从未被用于读取或写入,则它不会在所有者保存时被处理。因此,它不会影响纯粹的所有者保存。

创建关系设置Web界面

[[\yii2tech\ar\linkmany\LinkManyBehavior::$relationReferenceAttribute]]的主要目的是支持创建多对多设置Web界面。您需要做的只是声明ActiveRecord中的此虚拟属性的验证规则,以便可以从请求中收集其值

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

    // ...
}

在视图文件中,您应使用relationReferenceAttribute属性作为表单输入的属性名

<?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(); ?>

在控制器中,您不需要任何特殊代码

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,
        ]);
    }

    // ...
}