2008年6月11日星期三

写自定义验证规则

一些时候内置的验证规则对于一些特殊的需求可能不够灵活,因此你可以自己写验证规则,而且非常简单。

首先,你必须在你的model下面写一个方法来进行验证 。该方法必须接受至少一个参数(需验证的值)。如果数据是合法的,该方法返回值为真,不然的话返回值为假。举例如下:


public function validateNotEmpty($value) {
if (trim($value[key($value)]) == ”) {
return false;
} else {
return true;
}
}

一件必须注意的事是$value是一个包含一对key/value的数组。键值是你认证的field的名字,值则是用户输入

下一步和最后一步,我们必须定义我们想要使用的这个方法。这个和内置的认证规则写法一样,唯一的不同则是我们必须使用方法名字来作为rule的名字:

public $validate = array('name' => array('rule' => 'validateNotEmpty'));

你也可以写一些加上参数的验证规则。让我们假设你想要写一个验证规则来验证一个字符包括一个特定的字母。验证方法如下:

public function validateContainsChar($value, $char) {
return (strpos($value[key($value)], $char) !== false);
}

现在,如果我们想要确定"name"field的值包括"x",那么$validate 数组将是:

public $validate = array('name' => array('rule' => array('validateContainsChar', 'x')));

就这么简单,做你自己想要的任何验证!

新的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是一件非常棒的事情:)

2008年6月2日星期一

Cakephp-即将要用的新的php框架初探

最近一直在研究cakephp的东西,看了官方的API后感觉关于cakephp的文档资料太少了,而后通过google找到了两个非常不错的网站:debuggablebakery.cakephp.org

第一个网站是两个德国小伙子的blog,他们都是cakephp社区的活跃分子,通过这个blog我开始关注起了cakephp的源代码,因为只有理解了源码才能更好的在开发的时候灵活运用各种方法和接口,另外最大的收获是我了解了什么是TDD开发模式,即Test Driven Development(测试驱动开发),cakephp用到了simpletest的unit test方式,通过开发人员的test模块,我一点点的了解了cakephp的MVC的核心,cakephp是基于ruby on rails的快速开发模型演变而来的,所以类和方法是它的最大特点,二次开发的时候必须要了解各个方法的作用,其中很多都是对php的各个函数的扩充,cake目录下的lib目录就是精华所在,很多有用的类都在其中,包括controller,component,model,behavior,datasource,view,helpers等
另外cake目录下的tests目录就是全部的核心代码测试文件了,cases下的libs就是全部核心测试文件,还有fixtures目录文件中的数据就是每一个测试model类对应数据表的表结构和测试数据,看懂了libs下面的所有类方法才算是对API掌握的比较透彻了。

另一个bakery的网站则是开源社区人贡献的很多第三方组件以及很多是用的技巧。

因为即将要做cakephp的广告联盟项目,所以我也把工作平台挪到了LAMP下,最近也积累了不少这方面的心得和体会,感觉linux就是比windows灵活不少,虽然IDE和windows下有不少的差距,但是看看bash,就够写一本书的了,它可以让我更好的去执行系统任务,虽然一开始编译安装不如windows下面的来得快捷,但是配置更加灵活方便。

还有一个使用lamp的原因是最近正在帮助andyhuang做一个wordpress的blog项目,用到了capenl, smart auto blog, openx(phpnewads),很多文档的任务执行也是在linux下实现的.越用越发现自己离不开linux了,至少它不像windows这么傻瓜式的使用,更符合程序员的逻辑。

这两天一直在看model的unit test,光一个测试文件就有3000多行代码,汗!!!发现cakephp的model简直就是一个怪物,把所有的sql语句都封装了起来,和windows欲把大家都变成傻瓜没什么两样,还得了解各个方法的运行机制和参数调用,还有那几个belongTo,hasMany, belongToAndHasMany等逻辑关系,等琢磨过来发现返回的数据数组的层次结构也得费一番周折才能搞明白,真是不理解为什么cakephp的开发人员为什么要把model设计的这么复杂,看得真是累。

不过cakephp通过console界面的scaffold方式来自动生成MVC架构是我用的最爽的功能,ruby on rails的快速开发工具果然了得。更多的心得也有待于开发之中慢慢积累了,今天先到这儿吧

2007年9月14日星期五

第一天用google blog

一直想好好用一下google的产品,以前用过google maps,google rss,gmail,google suggestion,感觉客户体验都非常棒,以后可以在google上安家了