引用 yii 中的关系应用默认范围

Posted

技术标签:

【中文标题】引用 yii 中的关系应用默认范围【英文标题】:applying a default scope with reference to a relation in yii 【发布时间】:2012-08-11 18:37:35 【问题描述】:

我找不到太多关于在 yii 中将默认范围应用于模型的文档,我想知道是否有人可以解释或指出正确的方向。

我的问题的快速版本:

是否可以将关系添加到默认范围,或者默认为模型上的每个 AR 搜索添加“with”条件?

我的问题的长版本:

我的应用程序的简要总结:

我有两个模型,provideritem。它具有 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",
    );

我现在想要做的,也是过滤掉他们的提供者设置为离线的项目(即只显示provider.offline = false 旁边的当前item.offline = false 的项目)。

我已经尝试在 defaultScope 中加入 providers 表:

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')。

我还尝试向 defaultScope 添加一个 with 条件:

public function defaultScope()

    $alias = $this->getTableAlias(false,false);
    return array(
        'with'=>"provider",
        'condition'=>"`$alias`.`offline` = false AND `provider`.`offline` = false",
    );

但我得到同样的错误:SQLSTATE[42S22]: Column not found: 1054 Unknown column 'provider.offline' in 'on clause'`)。

有什么建议吗?

【问题讨论】:

【参考方案1】:

有几件事我会尝试:

首先,改变你的条件以适用于整个事情(不要忘记,如果没有提供者的项目,它不会返回提供者)

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()
    
        ...
    
    ...

【讨论】:

当然!我将条件放在主要的“条件”语句中,而不是在“与”中。您的第一个建议非常有效,谢谢!【参考方案2】:

刚刚遇到了类似的问题。虽然 Benjamin 的第一个建议为我指明了正确的方向(非常感谢!),但我在使用 'condition' 和 'with' 时遇到了一个意想不到的问题,了解一下可能会有所帮助。

如果您要加入的表(示例中为“provider”)有自己的 defaultScope,那么当您使用“with”时,这似乎会作为 SQL ON 子句的一部分应用,从而限制返回的行。

由于使用了外连接,您仍会为主表(“item”)中的每一行返回一条记录,但如果提供者的 defaultScope 阻止返回这些行,则某些行的“提供者”字段可能为空.

在您尝试应用涉及这些提供者字段之一的“条件”之前,这不会导致问题。这是作为连接后处理的 WHERE 子句的一部分完成的,但由于该字段为 null,条件将失败,并且不会返回记录。

在某些情况下,这可能是您想要的行为,但在其他情况下,您可能希望使用 on 选项将“提供者”字段上的测试移动到连接内:

public function defaultScope()

return array(
    'with'=> array("provider" => array(
        'condition'=> "t.offline = false",
        'on'=>"provider.offline = false",
    )
);

【讨论】:

以上是关于引用 yii 中的关系应用默认范围的主要内容,如果未能解决你的问题,请参考以下文章

Java中的基本数据类型和引用类型

JSF 2 应用程序中的默认托管 Bean 范围是啥?

yii2开发后记

Yii2.0开发初学者必看

Yii:如何自定义 CHtml 渲染的视图?

Yii1在迁移中设置DB列的默认值