我有一个包含多个表和关系的简单数据库,即: 文章 - 类别 用户 - 组 等...
我已经实现了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();
我的解决方案
所以我决定,在框架中这样做是:
总体经验:尽量保持所有业务逻辑尽可能靠近数据库,以防止出现差异。
首先,我在考虑使用会在层次结构中传播软删除的触发器。但是在考虑了一点之后我决定不这样做。原因是,这样,如果我(或接口或某物)决定重新激活父记录,就没有办法说明哪个子记录被链删除,哪一个被删除之前: 案件: 让我们说类别和文章。 首先,删除一篇文章。 然后删除整个类别。 然后你意识到这是一个错误,你想取消删除类别。您如何通过删除类别来知道哪个文章被删除?哪个文章应该保留删除?是的,有解决方案,即时间戳,但......太复杂,太容易破解
所以我的解决方案到底是: 意见。我想我会从yii ORM转向使用视图来处理比基本事物更复杂的事情。
这对我有两个好处: 1)作为一名DBA,我可以更快地做出更好的SQL 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",
)
);