我找不到太多关于在 yii 中将默认范围应用于模型的文档,我想知道是否有人可以解释或指出我正确的方向。
我问题的快速版本:
是否可以添加与默认范围的关系,或者默认情况下为模型上的每个AR搜索添加"with"条件?
我问题的长版本:
我的应用程序的快速摘要:
我有两个模型,provider
和item
。其中具有 m:1 关系,其中提供程序可以有多个项目,但每个项目只能有一个提供程序。
到目前为止,我有这些关系:
class Provider extends CActiveRecord
{
...
public function relations()
{
return array(
'items' => array(self::HAS_MANY, 'Item', 'id_provider', 'order'=>'rank DESC'),
);
}
...
}
class Item extends CActiveRecord
{
...
public function relations()
{
return array(
'provider' => array(self::BELONGS_TO, 'Provider', 'id_provider'),
);
}
...
}
在我的项目模型中,我已经有一个 defaultScope,它可以过滤掉所有离线项目(即仅显示设置为 offline = false
的项目):
public function defaultScope()
{
$alias = $this->getTableAlias(false,false);
return array(
'condition'=>"`$alias`.`offline` = false",
);
}
我现在要做的是过滤掉其提供程序设置为脱机的项目(即仅显示与当前item.offline = false
一起provider.offline = false
的项目)。
我尝试在默认范围内加入提供程序表:
public function defaultScope()
{
$alias = $this->getTableAlias(false,false);
return array(
'join'=>"JOIN `provider` AS `provider` ON `provider`.`id` = `$alias`.`id_provider`",
'condition'=>"`$alias`.`offline` = false AND `provider`.`offline` = false",
);
}
但是,JOIN 在 ON 语句之后应用,并导致错误 ( CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'provider.offline' in 'on clause'
)。
我还尝试在默认范围中添加一个带有条件:
public function defaultScope()
{
$alias = $this->getTableAlias(false,false);
return array(
'with'=>"provider",
'condition'=>"`$alias`.`offline` = false AND `provider`.`offline` = false",
);
}
但是我得到同样的错误:SQLSTATE[42S22]:找不到列:1054 "on 子句"中的未知列"提供程序.offline")。
有什么建议吗?
我会尝试以下几件事:
首先,更改您的条件以应用于整个事情(并且不要忘记,如果没有提供程序的项目,它将不会返回提供程序)
public function defaultScope()
{
return array(
'with'=> array("provider" => array(
'condition'=> "t.offline = false AND provider.offline = false",
)
);
}
其次,尝试向模型添加范围,然后在默认范围中引用它们,如下所示:
public function defaultScope()
{
return array(
'scopes'=> array('default'),
);
}
class Provider extends CActiveRecord
{
...
public function scopes()
{
...
}
...
}
class Item extends CActiveRecord
{
...
public function scopes()
{
...
}
...
}
刚刚遇到了类似的问题。虽然本杰明的第一个建议为我指明了正确的方向(非常感谢!),但我遇到了一个使用"条件"和"with"的意外问题,意识到这一点可能会有所帮助。
如果您要加入的表(示例中为"provider")具有自己的 defaultScope,则当您使用"with"时,它似乎会作为 SQL ON 子句的一部分应用,从而限制返回的行。
由于使用了外部联接,因此您仍然可以为主表("item")中的每一行返回一条记录,但如果提供程序的 defaultScope 阻止返回某些行,则"提供程序"字段可能为 null。
在您尝试应用涉及其中一个提供程序字段的"条件"之前,这不会导致问题。这是作为连接后处理的 WHERE 子句的一部分完成的,但由于该字段为 null,因此条件将失败,并且不会返回记录。
在某些情况下,这可能是您想要的行为,但在其他情况下,您可能希望使用 on 选项将"提供程序"字段上的测试移动到联接中:
public function defaultScope()
{
return array(
'with'=> array("provider" => array(
'condition'=> "t.offline = false",
'on'=>"provider.offline = false",
)
);
}