【问题标题】:Yii2 ActiveRecord - default condition causes sql errorYii2 ActiveRecord - 默认条件导致 sql 错误
【发布时间】:2015-10-07 16:01:20
【问题描述】:

我正在做一个项目,我有自己的 ActiveRecord 类,该类扩展 \yii\db\ActiveRecord:

class ActiveRecord extends \yii\db\ActiveRecord
{   
    const DELETED_STATUS = 1;

    /**
     *  Defines the soft delete field
     */
    public static function softDeleteField()
    {
        return 'Deleted';
    }

    /**
     *  Overrides the find() function to add sensitivity to deletes
     */
    public static function find()
    {
        return parent::find()->where(['not',[
            static::softDeleteField() => static::DELETED_STATUS
        ]]);
    }
}

我希望能够使所有内容都可以软删除。根据documentation,应用这样的默认条件应该是可行的。

它在大多数情况下工作得很好,但是当我尝试进行连接时,我得到一个 sql 错误。这方面的一个例子是:

$query = Model::find(); // ActiveRecord of table1

$query->joinWith(['alias' => function($query) { $query->from(['alias' => 'table2']); }]);

我得到了错误:

SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'Deleted' in where clause is ambiguous
The SQL being executed was: SELECT COUNT(*) FROM `table1` LEFT JOIN `table2` `alias` ON `table1`.`StatusID` = `alias`.`StatusID` WHERE (NOT (`Deleted`=1)) AND (NOT (`Deleted`=1))

能够通过将我的联接查询更改为

来使其工作
// Omitting the alias in the from() method
$query->joinWith(['alias' => function($query) { $query->from('table2'); }]);

并将我的 find() 方法更改为

public static function find()
{
    return parent::find()->where(['not',[
        static::tableName()."."static::softDeleteField() => static::DELETED_STATUS
    ]]);
}

但这只有在没有别名的情况下才有效。我可以做些什么来使这个工作也适用于带有别名的连接查询吗?

【问题讨论】:

    标签: mysql activerecord yii2


    【解决方案1】:

    我认为你应该使用SELF 而不是static

    喜欢这个

    public static function find()
    {
        return parent::find()->where(['not',[
            SELF::softDeleteField() => SELF::DELETED_STATUS
        ]]);
    }
    

    【讨论】:

    • 我可以这样做,但是在扩展我的 ActiveRecord 类的类中,指示是否删除某些内容的字段有时会有所不同,因此我需要使用后期静态绑定。
    【解决方案2】:

    错误消息说:许多表有已删除的字段,您必须明确在您的 sql 查询中使用什么字段。

    你必须用类似的表名或别名来定义Deleted

    /**
     *  Defines the soft delete field
     */
    public static function softDeleteField()
    {
        return self::tableName() . '.Deleted';
    }
    

    【讨论】:

    • 您知道一种以编程方式确定表是否被别名的方法吗?正如您在我原来的问题中看到的那样,我现在使用tableName() 方法,但是如果表在连接查询中具有别名,则此方法不起作用。
    • @spencer4of6,我想你可能不会在 Yii2 中使用别名,因为它对 ActiveQuery 和 SQL builder 没有用处
    猜你喜欢
    • 1970-01-01
    • 2019-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-08
    • 2020-11-25
    相关资源
    最近更新 更多