首页 文章

Yii2 activerecord自定义属性

提问于
浏览
4

我正在尝试在扩展 db\activerecord 的模型类中使用自定义属性 .

我已经尝试声明 public $categories = [] ,然后直接通过 $model->categories = [1,2,3] 或在我的模型类 public function setCategories($ids) {... 中使用setter方法为其分配值,然后再通过 $model->categories = [1,2,3] 进行分配 .

我也尝试用 $model->setAttribute('categories', [1,2,3]) 更新属性 .

在所有情况下都没有填充 $model->categories .

我的最终目标是为模型分配类别,然后使用 afterSave()beforeSave() 更新数据库关系/表

可以这样做,还是应该从 db\model 扩展我的模型类?如果我这样做,我将失去什么功能?

Edit 我可能误会了我的问题 .

我有一个表单,用户可以选择特定模型的类别(即“产品”) . 所有类别都是预先存在的,产品通过具有一对多关系的联结表product_category('product_id','category_id')分配给类别(一个产品有许多类别) .

现在在's handling the view, I' m接收类别ID列表的控制器中,我想将它们分配给属性,以便我可以处理它们,即删除或添加(通过 link() )product_category表中特定产品的条目 .

2 回答

  • 2

    它看起来像你在手动尝试表之间的关系?为什么不使用内置功能并为您服务?

    为此(多对多),您需要一个链接activerecord或表,指示哪些模型链接到哪些类别(我假设您有 ActiveRecord ,名为 ModelCategory ,并且 model_idcategory_id

    public function getProductCategories() 
    { 
       return $this->hasMany(ProductCategory::className(), ['product_id' => 'id']);
    }
    
    public function getCategories()
    {
        return $this->hasMany(Category::className(), ['id' => 'category_id'])
            ->via('productCategories');
    }
    

    (您也可以使用 viaTable() 而不是 via() 并避免使用额外的方法,这是您的选择 . )

    这意味着您可以像这样访问它们:

    $product->categories
    

    (总是使用关系的神奇功能,它是实际进行数据库查询的__get()函数) .

    对于分配关系,没有自动方法 . Yii虽然有一些辅助功能:

    $category = new Category();
    // Assign attributes
    $category->save();
    
    $product = new Product();
    // Assign attributes
    $product->save();
    
    $product->link('categories', $category);
    

    查看link-function了解更多详情 . 显然还有其他方法,但这取决于您的需求 .

    根据您的额外信息:

    public function actionAssignCategories($product, $categories) 
    {
       $product = Product::findOne($product);
    
       $existingCategories = \yii\base\ArrayHelper::getColumn($product->categories, 'category_id');
       $removeCategories = array_diff($existingCategories, $categories); 
       $addCategories = array_diff($categories, $existingCategories);             
    
       foreach ($addCategories as $category) { 
          $category = Category::findOne($category);
          $product->link('categories', $category);
       }
    
       foreach ($removeCategories as $category) { 
          $category = Category::findOne($category);
          $product->unlink('categories', $category);
       }
    }
    

    未经测试,但这应该让你知道如何解决这个问题 .

  • 2
    class ClassName extends \yii\db\ActiveRecord
    {
    
       public $addition;   //what attribute you want
    
        /* your code */
    
       public function fields()
       {
            $fields = parent::fields();
            $fields[] = 'addition';      //the value must be the same as the new attribute
    
            /* your code */
    
            $this->addition = 'done'
            return $fields
       }
    }
    

相关问题