jim*_*mmy 5 php activerecord yii2
我正在尝试在扩展的模型类中使用自定义属性db\activerecord
。
我试过声明public $categories = []
,然后直接通过$model->categories = [1,2,3]
或在我的模型类中使用 setter 方法为其public function setCategories($ids) {...
赋值,然后再次通过$model->categories = [1,2,3]
.
我也试过用$model->setAttribute('categories', [1,2,3])
.
在所有情况下$model->categories
都不填充。
我的最终目标是为模型分配类别,然后使用afterSave()
和更新数据库关系/表beforeSave()
这可以完成还是我应该从 扩展我的模型类db\model
?如果我这样做了,我会失去什么功能?
编辑 我可能误报了我的问题。
我有一个表单,用户可以在其中为特定模型(即“产品”)选择类别。所有类别都是预先存在的,并且产品通过具有一对多关系的连接表 product_category('product_id', 'category_id') 分配给类别(一个产品有多个类别)。
现在在处理视图的控制器中,我收到了一个类别 ID 列表,我想将它们分配给一个属性,以便我可以处理它们,即删除或添加(通过link()
)特定产品的 product_category 表中的条目。
在我看来,您似乎正在手动尝试建立表之间的关系?为什么不使用内置功能并让其为您处理呢?
对于这个(多对多),您需要一个链接 activerecord 或表来指示哪些模型链接到哪些类别(我在这里假设您有一个ActiveRecord
被称为ModelCategory
并且有 amodel_id
和 a 的category_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');
}
Run Code Online (Sandbox Code Playgroud)
(您也可以使用viaTable()
替代via()
和避免额外的方法,这是您的选择。)
这意味着您可以像这样访问它们:
$product->categories
Run Code Online (Sandbox Code Playgroud)
(始终使用关系的神奇功能,实际上是 __get() 函数执行数据库查询)。
对于分配关系,没有自动方法。Yii 为此提供了一些辅助功能:
$category = new Category();
// Assign attributes
$category->save();
$product = new Product();
// Assign attributes
$product->save();
$product->link('categories', $category);
Run Code Online (Sandbox Code Playgroud)
查看 -link
函数以获取更多详细信息。显然还有其他方法,但这取决于您的需求。
根据您的额外信息:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
未经测试,但这应该能让您了解如何解决这个问题。