2008年6月11日星期三

新的core behavior: containable

changeset 6918介绍了一个新的behavior Containable. 它是由原来的Containable behavior Felix Geisendörfer (aka the_undefined) 编写和 Bindable behavior Mariano Iglesias编写后的结合体.

为了使用这个behavior, 你或是把它加在model属性的$actsAs里头:

class Post extends AppModel {
var $actsAs = array('Containable');
}

或者你也能够这样来绑定behavior:

$this->Post->Behaviors->attach('Containable');

好了,现在让我们看一些例子。例如我将会用到三个models Post, Comment和Tag,他们之间的关系是: Post hasMany Comments, Post hasAndBelongsToMany Tags.

如果我们使用一个简单的find all语句,我们将会获得所有的posts外加所有相关联的记录,像这样:

debug($this->Post->find('all'));

[0] => Array
(
[Post] => Array
(
[id] => 1
[title] => First article
[content] => aaa
[created] => 2008-05-18 00:00:00
)
[Comment] => Array
(
[0] => Array
(
[id] => 1
[post_id] => 1
[author] => Daniel
[email] => dan@example.com
[website] => http://example.com
[comment] => First comment
[created] => 2008-05-18 00:00:00
)
[1] => Array
(
[id] => 2
[post_id] => 1
[author] => Sam
[email] => sam@example.net
[website] => http://example.net
[comment] => Second comment
[created] => 2008-05-18 00:00:00
)
)
[Tag] => Array
(
[0] => Array
(
[id] => 1
[name] => A
)
[1] => Array
(
[id] => 2
[name] => B
)
)
)

但是经常你不想要获得所有的数据,那就让Containable behavior来做你的好帮手

为了仅仅获得posts,你可以如下写代码:

$this->Post->contain();
debug($this->Post->find('all'));



debug($this->Post->find('all', array('contain' => false)));

或不用containable behavior:

$this->Post->recursive = -1;
debug($this->Post->find('all'));

对于各自的contain()方法。在"contain"选项下我们指定想要获得数据的每一个相关联的models。如果我们除了想要获得posts还有关联的tags(不需要comments),我们将要如下操作:

$this->Post->contain('Tag'); // we could also use an array
debug($this->Post->find('all'));

或是

debug($this->Post->find('all', array('contain' => 'Tag'))); // we could also use an array

或不用 Containable behavior

$this->Post->unbindModel(array('hasMany' => array('Comment')));
debug($this->Post->find('all'));

就如你所见到的,使用Containable behavior的代码比不用它的代码更简洁。

但是这些并不是Containable behavior所能实现的全部功能。你能够过滤一些关联models的数据,如果你对posts和comment的作者(authors)名字感兴趣,你可以这样来写:

$this->Post->contain('Comment.author');
debug($this->Post->find('all'));



debug($this->Post->find('all', array('contain' => 'Comment.author')));

[0] => Array
(
[Post] => Array
(
[id] => 1
[title] => First article
[content] => aaa
[created] => 2008-05-18 00:00:00
)
[Comment] => Array
(
[0] => Array
(
[author] => Daniel
[post_id] => 1
)
[1] => Array
(
[author] => Sam
[post_id] => 1
)
)
)

如你所见,comment数组仅仅包括了作者和post_id(因为cake需要联系结果)

你也能够过滤(comment)数据通过使用一个条件:

$this->Post->contain('Comment.author = "Daniel"');
debug($this->Post->find('all'));

或是

debug($this->Post->find('all', array('contain' => 'Comment.author = "Daniel"')));

[0] => Array
(
[Post] => Array
(
[id] => 1
[title] => First article
[content] => aaa
[created] => 2008-05-18 00:00:00
)
[Comment] => Array
(
[0] => Array
(
[id] => 1
[post_id] => 1
[author] => Daniel
[email] => dan@example.com
[website] => http://example.com
[comment] => First comment
[created] => 2008-05-18 00:00:00
)
)
)

就想你能够从这些例子中看到的,Containable behavior功能相当强大,我极力推荐各位看一下测试文件。(cake/tests/cases/libs/model/behaviors/containable.test.php)

不管怎么敢说,cake核心里头有这个behavior是一件非常棒的事情:)

没有评论: