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*FROM
prod\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