带有Yii和关系的软删除

时间:2015-04-26 10:42:59

标签: php yii orm

我有一个包含多个表和关系的简单数据库,即: 文章 - 类别 用户 - 组 等...

我已经实现了SoftDelete行为,其中有一个Active列,如果设置为0,则认为它已被删除。 我的问题很简单。

如何在尽可能少的地方指定我只想加载属于活动类别的文章。

我已指定关系和默认范围(使用Active = 1)条件。

但是,当我执行findAll()时,它会返回那些Active = 1的文章,即使它所属的类别是Active = 0 ....

谢谢

到目前为止的实施: 在基类

public function defaultScope()
{
    return array('condition' => 'Active = 1');
}    
模特中的

'category' => array(self::BELONGS_TO, 'Category', 'CategoryID'),

'查询':

$data =  Article::model()->findAll();

我的解决方案

所以我决定,在框架中这样做是:

  1. inneficient
  2. 工作太多
  3. 不好,因为它将业务逻辑从数据库中移开 - 这对于稍后在处理接口/ web服务和应该属于产品的其他自定义项时保存工作非常重要。
  4. 总体经验:尽量保持所有业务逻辑尽可能靠近数据库,以防止出现差异。

    首先,我在考虑使用会在层次结构中传播软删除的触发器。但是在考虑了一点之后我决定不这样做。原因是,这样,如果我(或接口或某物)决定重新激活父记录,就没有办法说明哪个子记录被链删除,哪一个被删除之前: 案件: 让我们说类别和文章。 首先,删除一篇文章。 然后删除整个类别。 然后你意识到这是一个错误,你想取消删除类别。您如何通过删除类别来知道哪个文章被删除?哪个文章应该保留删除?是的,有解决方案,即时间戳,但......太复杂,太容易破解

    所以我的解决方案到底是: 意见。我想我会从yii ORM转向使用视图来处理比基本事物更复杂的事情。

    这对我有两个好处: 1)作为一名DBA,我可以更快地做出更好的SQL 2)逻辑停留在数据库中,如果应用程序更改/添加另一个,则无需在多个位置实现逻辑

2 个答案:

答案 0 :(得分:0)

您需要在使用findAll方法时指定条件。因此,您应该使用CDbCriteria来实现此目的:

$criteria=new CDbCriteria;
$criteria->with = "category";
$criteria->condition = "category.Active = 1"; //OR $criteria->compare('category.active', 1 true);
$data =  Article::model()->findAll($criteria);

答案 1 :(得分:0)

您的defaultScope模型中也应该有一个Article,条件应该是category.Active = 1或者你的关系被命名为什么。

public function defaultScope()
{
    return array('condition' => 't.Active = 1 AND category.Active = 1');
}

我现在不记得了,但可能你需要指定关系:

return array(
    'with' => array("category" => array(
        'condition'=> "t.Active = 1 AND category.Active = 1",
    )
);