Yii2-1:M关系的Where子句
我有两张桌子: 产品选项组Yii2-1:M关系的Where子句,yii2,Yii2,我有两张桌子: 产品选项组 产品选项列表 产品期权组模型 产品选项列表模型 产品选项组控制器 更新视图 打印的预期输出($model->optList): 实际产量: { [id] => 1 [optgrp_id] => 1 [list_name] => 25 [active_flag] => 0 }, { [id] => 2 [optgrp_id] => 1 [list_name] =>
产品选项列表
产品期权组模型
产品选项列表模型
产品选项组控制器
更新视图 打印的预期输出($model->optList):
实际产量:
{
[id] => 1
[optgrp_id] => 1
[list_name] => 25
[active_flag] => 0
},
{
[id] => 2
[optgrp_id] => 1
[list_name] => 50
[active_flag] => 1
},
{
[id] => 3
[optgrp_id] => 1
[list_name] => 75
[active_flag] => 0
},
{
[id] => 4
[optgrp_id] => 1
[optList_name] => 100
[active_flag] => 0
}
Yii2调试器显示正确的查询,但输出仍然包含所有4个元素。
如果有任何错误,请提出建议,提前谢谢:)您也可以这样做: //控制器
protected function findModel($id)
{
if (($model = ProdOptgrp::findOne($id)) !== null && $model->isActive()) {
return $model;
}
throw new NotFoundHttpException('The requested page does not exist.');
}
//模型
/*
*Check if model is active
*/
public function isActive(){
return ($this->active_flag == 0) ? true: false;
}
public function getOptList()
{
return $this->hasMany(ProdOptlist::className(),['optgrp_id'=>'id'])->where([ProdOptgrp::tableName().'.active_flag'=>0]);
}
//看法
foreach($model->optList as optItem): // you get filtered result
即使使用
joinWith()
方法调用的$model=ProdOptgrp::find()…
部分的where()
,代码也只会限制由one()
方法调用执行的查询返回的结果。它不会影响为关系加载的内容
如果要限制为关系加载的内容,可以执行以下操作:
1)通过修改现有关系
这就是你找到的解决方案。您可以将where条件直接添加到ProdOptgrp
模型的getOptList()
方法中。如果这样做,$model->optList
将始终返回筛选的关系。视情况而定,这可能是有利的,也可能是不利的
2)通过添加第二个关系
您可以在ProdOptgrp
模型中创建另一个方法,该方法将定义过滤的关系,同时保持原始getOptList()
未过滤。
例如:
类ProdOptgrp扩展\yii\db\ActiveRecord
{
公共函数getOptList()
{
返回$this->hasMany(ProdOptlist::className(),['optgrp_id'=>'id']);
}
公共函数getFilteredOptList()
{
返回$this->getOptList()->其中([
ProdOptlist::tableName()。。活动_标志'=>0
]);
}
}
在这种情况下,$model->optList
仍将包含未筛选的optList,$model->filteredOptList
将包含筛选的optList。当您需要在应用程序的不同位置同时使用两者时,此解决方案是很好的
3)在joinWith()或with()中使用回调语法
如果只想在一种特定情况下过滤关系,则无需修改模型。您可以修改与在加载数据之前调用的回调的关系
$model=ProdOptgrp::find()
->加入([
'optList'=>函数(\yii\db\ActiveQuery$query){
$query->where([
ProdOptlist::tableName()。。活动_标志'=>0
]);
}
])->在哪里([
ProdOptgrp::tableName().'.id'=>$id,
ProdOptgrp::tableName()。。活动_标志'=>0,
ProdOptlist::tableName()。。活动_标志'=>0,
])->一个();
where()
中的最后一个条件将导致$model在optgrp表中的active_标志为0,但在optlist表中的所有相关记录中为1时为null。我不确定这是否是故意的行为。谢谢你的帮助!不幸的是,由于SQLSTATE[42S22]的错误,我仍然无法正确执行:未找到列:“where子句”中的1054未知列“prod\u optgrp.active\u flag”正在执行的SQL是:SELECT*FROMprod\u optlist
where(prod\u optgrp
active\u flag
=0)和(optgrp\u id
=1)。此错误似乎来自公共函数getOptList()。我通过对函数getOptList()进行一个小的更改,编辑$this->hasMany(ProdOptlist::className(),['optgrp\u id'=>'id'])->where([ProdOptlist::tableName()。.active\u标志'=>0])的返回值来解决此问题。它现在很有魅力!谢谢你Serghei;)非常感谢你详细的回答,迈克尔!我从你的回答中学到了很多:祝你今天愉快,保持精神状态;D
public function actionUpdate($id)
{
$model = $this->findModel($id);
if($model->load(Yii::$app->request->post()) && $model->validate())
{
...
}
else
return $this->render('update', ['model'=>$model]);
}
protected function findModel($id)
{
if (($model = ProdOptgrp::find()
->joinWith('optList')
->where([ProdOptgrp::tableName().'.id'=>$id,
ProdOptgrp::tableName().'.active_flag'=>0,
ProdOptlist::tableName().'.active_flag'=>0])
->one()) !== null) {
return $model;
}
throw new NotFoundHttpException('The requested page does not exist.');
}
{
[id] => 1
[optgrp_id] => 1
[list_name] => 25
[active_flag] => 0
},
{
[id] => 3
[optgrp_id] => 1
[list_name] => 75
[active_flag] => 0
},
{
[id] => 4
[optgrp_id] => 1
[optList_name] => 100
[active_flag] => 0
}
{
[id] => 1
[optgrp_id] => 1
[list_name] => 25
[active_flag] => 0
},
{
[id] => 2
[optgrp_id] => 1
[list_name] => 50
[active_flag] => 1
},
{
[id] => 3
[optgrp_id] => 1
[list_name] => 75
[active_flag] => 0
},
{
[id] => 4
[optgrp_id] => 1
[optList_name] => 100
[active_flag] => 0
}
protected function findModel($id)
{
if (($model = ProdOptgrp::findOne($id)) !== null && $model->isActive()) {
return $model;
}
throw new NotFoundHttpException('The requested page does not exist.');
}
/*
*Check if model is active
*/
public function isActive(){
return ($this->active_flag == 0) ? true: false;
}
public function getOptList()
{
return $this->hasMany(ProdOptlist::className(),['optgrp_id'=>'id'])->where([ProdOptgrp::tableName().'.active_flag'=>0]);
}
foreach($model->optList as optItem): // you get filtered result