1. 禁止布局
如果需要在全局禁止布局则在app_controller.php中设置$this->autoLayout = false,其子类可以继承/重写该设置;如果需要有条件,则可以将$this->autoLayout = false放在app_controller.php的before_filter()过滤器中。
如果只是个别的controller/action的话,那么最好是直接在具体的action定义中设定$this->autoLayout = false,而不是在控制器层级设定。

2. HTML助手
在模板里使用图片的时候,最好是使用助手的方式,如:echo $html->image(’pic.gif’),而不是直接手动编写<img>标签,因为如果硬编码的话,一旦网站目录结构出现变化,问题就严重了。同样的情况还出现在链接上,应该使用助手的方式,如:echo $html->url(array(’action’ => ‘foobar’)。

图片链接生成的两种方式:

 

//由$html->image()方法生成,简单而实用。但不够灵活,不能为<a>链接添加额外的属性
 <?=$html->image('/img/icons/review.png',array('alt'=>__('Review',true),'url'=>'/admin/members/review/'.$member['Account']['id']))?>
//由$html->link()生成,可以添加额外的属性,如提示信息。注意其中最后一个参数必须设置为false,否则会将$html->image转义
<?=$html->link($html->image('/img/icons/destroy.png',array('alt'=>__('Trash',true))),
                                  '/admin/members/destroy/'.$member['Account']['id'],
                                  array(),
                                  'Are you sure you want to delete this record?',
                                  false
                    )
?>

3. 分页助手

分页助手一般使用的都是文字链接,但实际上也可以使用图片链接,方法如下:

<?php echo $paginator->prev($html->image('prev.gif', array('border' => 0)), array('escape' => false));?>

类似的,表单提交按钮如果想使用图片的话,方法如下:

<?php $form->submit(‘pic.gif’)?>

注意所有图片文件都被认为是存放在webroot目录下的img文件夹内的。

分页默认是由div包裹,这个是可以自定义的:

 <?=$paginator->prev('« '.__('Previous', true), array(), null, array('class'=>'disabled prev_page','tag'=>'span'));?>

有时候分页时需要通过URL传递一些查询参数,此时应该在模板文件里按如下设置:

<?php $paginator->options(array('url' => $this->passedArgs));?>

4. Form助手

在CakePHP里,Form助手可以说是所有助手里最重要的,也是最复杂的,其中,尤以input方法为甚,比如说文章属于一个目录,那么在录入文章的表单里我们可以这样生成一个目录的下拉菜单:

<?php
$form->input('category_id');
//当然,仅仅这样还不够,还需要在控制器里提供数据才OK
$this->set('categories', $this->Article->Category->find('list'));
?>

相应表有一个name字段用于显示,当然你也可以在模型里设定var $displayField属性。总体来说非常简单,甚至有点奇幻的感觉,这是因为CakePHP在这里做了点小动作,参考form.php文件:

<?php
if (!isset($options['options']) && in_array($options['type'], $types)) {
    $view =& ClassRegistry::getObject('view');
    $varName = Inflector::variable(
        Inflector::pluralize(preg_replace('/_id$/', '', $this->field()))
    );
    $varOptions = $view->getVar($varName);
    if (is_array($varOptions)) {
        if ($options['type'] !== 'radio') {
            $options['type'] = 'select';
        }
        $options['options'] = $varOptions;
    }
}
?>

CakePHP会把表单元素名字中的_id部分去掉,并转换成复数形式,然后在当前视图变量里查找是否已经有了同名的变量,如果有,且未设置成radio单选标签,就把它当做select下拉菜单。

表单助手缺省创建的input会有div包裹,还有label等等修饰,很多时候这和美工设计的页面结构不同,这时:

$form->input(’password’, array(’div’ => false, ‘label’ => false, ‘error’ => false))

输出记得转义,CakePHP提供了h()方法,很简单,但是总容易忘。

这里还有一个技巧,就是在渲染select的时候,如果原来的数据库表里有一个名为name或者title的字段,那么会自动被当做下拉菜单的显示部分。

5. saveAll方法

saveAll方法可以同时保存一对一,一对多的关系。比如说一个question有多个answer,那么在question的表单里,我们就可以这样设定:

<?php
echo $form->input('Question.title');
echo $form->input('Answer.0.content');
echo $form->input('Answer.1.content');
echo $form->input('Answer.2.content');
echo $form->input('Answer.3.content');
?>

经过这样简单的设定后,在question控制器里就可以使用saveAll方法一次性保存所有的数据了。

6. Configure最多支持三级设置

如果超过三级,比如说Configure::write(’A.B.C.D’, ‘…’);这样是无效的,做多A.B.C三级。


7. 通过HTTP_X_FORWARDED_FOR得到客户端IP

如果想通过HTTP_X_FORWARDED_FOR得到客户端IP,必须传递一个false参数:

<?php $this->RequestHandler->getClientIP(false);?>

就是说要传递一个false参数,不过这样做仅适合安全性要求不高的应用。

8. 钩子方法afterFilter并不一定会执行

这是CakePHP的一个硬伤,因为redirect会直接跳转,所以afterFilter有可能会被忽略,这点要注意。

9. Auth组件缺省设置的弊端

缺省实现里,提交表单时,如果有password字段,会自动哈希处理,但是有的时候反倒麻烦,比如说添加用户时,如果验证未通过,再显示出错表单时,密码字段已经被哈希了,已经不是初始值了,再提交就不对了,所以为了屏蔽问题,就不应该再使用password字段名,而应该改名,以注册表单为例:

原始密码:

<?php echo input(’encrypt_password’); ?>

确认密码:

<?php echo input(’confirm_password’); ?>

这样的话,字段值在提交前后始终保持是初始值,就不会再有问题了。

Today on history:

  1. 2008:  夫妻之间的潜规则(0)
  2. 2008:  我什么都不说,你自己看吧(0)
  3. 2008:  清晨的厦门(0)