notamedia/yii2-relation

在 Yii2 中保存相关数据

安装次数: 5,140

依赖: 0

建议者: 0

安全: 0

星标: 9

关注者: 5

分支: 4

开放问题: 2

类型:yii2-extension

1.0.0 2017-08-24 14:16 UTC

This package is auto-updated.

Last update: 2024-09-19 20:53:49 UTC


README

Build Status Latest Stable Version Total Downloads License

支持关系数据管理的行为。

  • 从 POST 数组中插入相关模型。
  • 通过回调函数对新模型进行预处理。
  • 从数据库中删除不存在于 POST 数组中的相关模型。
  • 跳过在数据库中已存在且具有相同属性的关联模型。
  • 如果关系模型保存/删除发生错误,则回滚数据库更改。
  • 支持一对一和一对多关系。

通过预处理,您可以在创建相关模型之前设置额外的逻辑。例如,在多对多关系中向连接表中添加额外的列数据。

此行为使用所有者模型中关系属性的获取器,这些获取器必须返回 ActiveQuery 对象。如果您在 ActiveQuery 对象的 ON 条件中使用字符串值,则此行为将抛出异常。

安装

composer require notamedia/yii2-relation

用法

要使此行为工作,您需要

  • 将所有关联属性添加到规则中作为安全属性。
  • 声明关系属性的获取器。
  • 将属性或带有回调的属性放入行为的关系属性中。
  • 所有使用的模型都需要只有一个主键列。

一对一关系

<?php

class News extends \yii\db\ActiveRecord
{
    public function rules()
    {
        return [
            [['file'], 'safe']
        ];
    }
    
    public function getFile()
    {
        return $this->hasOne(File::class, ['id' => 'file_id']);
    }
    
    public function behaviors()
    {
        return [
            [
                'class' => \notamedia\relation\RelationBehavior::class,
                'relations' => ['file']
            ]
        ];
    }
    
    public function transactions()
    {
        return [
            $this->getScenario() => static::OP_ALL
        ];
    }
}

一对多关系

<?php

class News extends \yii\db\ActiveRecord
{
    public function rules()
    {
        return [
            [['images'], 'safe']
        ];
    }
    
    public function getImages()
    {
        return $this->hasMany(Image::class, 
            ['news_id' => 'id']);
    }
    
    public function behaviors()
    {
        return [
            [
                'class' => \notamedia\relation\RelationBehavior::class,
                'relations' => ['images']
            ]
        ];
    }
    
    public function transactions()
    {
        return [
            $this->getScenario() => static::OP_ALL
        ];
    }
}

多对多关系

使用 via

<?php

class News extends \yii\db\ActiveRecord
{
    public function rules()
    {
        return [
            [['categories'], 'safe']
        ];
    }
       
    public function getNewsHasCategories()
    {
        return $this->hasMany(NewsHasCategory::class, ['news_id' => 'id']);
    }

    public function getCategories()
    {
        return $this->hasMany(Category::class, ['id' => 'category_id'])
            ->via('newsHasCategories');
    }
    
    public function behaviors()
    {
        return [
            [
                'class' => \notamedia\relation\RelationBehavior::class,
                'relations' => ['categories']
            ]
        ];
    }
    
    public function transactions()
    {
        return [
            $this->getScenario() => static::OP_ALL
        ];
    }
}

使用 viaTable

<?php

class News extends \yii\db\ActiveRecord
{
    public function rules()
    {
        return [
            [['categories', 'categories_type_archive'], 'safe']
        ];
    }

    public function getCategories()
    {
        return $this->hasMany(Category::class, ['id' => 'category_id'])
            ->viaTable('news_has_categories', ['news_id' => 'id']);
    }
    
    // with onCondition
    public function getCategories_type_archive()
    {
        return $this->hasMany(Category::class, ['id' => 'category_id'])
            ->viaTable('news_has_categories', ['news_id' => 'id'], function($query) {
                 return $query->onCondition(['type' => 'archive']);
            });
    }
    
    public function behaviors()
    {
        return [
            [
                'class' => \notamedia\relation\RelationBehavior::class,
                'relations' => ['categories', 'categories_type_archive']
            ]
        ];
    }
    
    public function transactions()
    {
        return [
            $this->getScenario() => static::OP_ALL
        ];
    }
}

排序数据关系

<?php

class News extends \yii\db\ActiveRecord
{
    public function rules()
    {
        return [
            [['categories'], 'safe']
        ];
    }
       
    public function getNewsHasCategories()
    {
        return $this->hasMany(NewsHasCategory::class, ['news_id' => 'id']);
    }
    
    public function getCategories()
    {
        return $this->hasMany(Category::class, ['id' => 'category_id'])
            ->via('newsHasCategories');
    }
    
    public function behaviors()
    {
        $sortIndex = 1;
        
        return [
            [
                'class' => \notamedia\relation\RelationBehavior::class,
                'relations' => [
                    'categories' => function (NewsHasCategory $model) use (&$sortIndex) {
                        $model->sort = $sortIndex++;
    
                        return $model;
                    }
                ]
            ]
        ];
    }
    
    public function transactions()
    {
        return [
            $this->getScenario() => static::OP_ALL
        ];
    }
}