helper
CakePHP 中的 helper 主要用于帮助提高视图的开发速度。HTML、Ajax、JavaScript
等等都有 helper。通过使用 helper,可以更轻松地插入要多次编写的 HTML 代码片段。
修改 users_controller.php 文件
为了使用 helper,需要修改前面创建的 users_controller.php
文件。应该给控制器命名,并告诉它希望使用一些 helper(在这个示例中,是 HTML 和 Form helper)。编辑这个文件,添加
$name 和 $helpers 类变量(见清单 16)。
清单 16. users 控制器
<!DOCTYPE HTML><?php class UsersController extends AppController { var $name = 'Users';
var $helpers = array('Html', 'Form' );
function register()
{
... |
现在已经在控制器中包含了 helper,可以开始使用它们了。
更轻松地创建表
Tor 的用户应当能够查看注册使用该应用程序的其他用户。CakePHP 有大量 helper 可用于帮助创建表。这些
helper 包括很多有用的功能,其中一些功能您可能不止一次编写过。为了演示此功能,将创建一个用于显示注册用户的视图。
首先,在 users 控制器中创建 knownusers 操作(见清单 17)。
清单 17. 创建 knownusers 操作
清单 17. 创建 knownusers 操作 function knownusers() { $this->set('knownusers', $this->User->find( 'all', array( 'fields' => array('id','username', 'first_name', 'last_name'), 'order' => 'id DESC' ) )); } |
这将调用 user 模型中的内置函数 find。find 函数接受许多参数,比如匹配条件(在本例中,传递的是
all 而不是一些匹配条件)、要返回的字段数组(不需要所有用户信息,只需要希望所有人都看到的信息),以及一个排序字段和顺序(在本例中,用
id DESC 按 ID 降序排序)。还可以指定限制(返回的最大行数)、分页(如果要给数据分页)以及可用于指定返回与数据关联的模型的递归选项(例如,查询一个
groups 表和属于每个组的若干个用户)。
find 的输出被放入 knownusers 变量。现在就可以从视图访问数据了。
创建 knownusers 视图
在文本编辑器中创建文件 app/views/users/knownusers.ctp。要查看 findAll
返回的数据,应该使用 var_dump 输出 knownusers 变量(见清单 18)。
清单 18. 使用 var_dump 输出 knownusers 变量
<?php var_dump($knownusers) ?> </pre> |
访问位于 http://localhost/users/knownusers 的视图。应当会看到一个用户数据数组,如图
7 所示。
图 7. 结果
如果只列出了一个用户,请返回到 http://localhost/users/register,然后多注册一些用户。最终的结果将会更令人印象深刻。
获得足够大的用户数组了吗?很好!现在就将它转换为一个表。使用清单 19 中的内容替换 knownusers.ctp
的内容。
清单 19. 创建表
<table> <?php
echo $html->tableHeaders(array_keys($knownusers[0]['User']));
foreach ($knownusers as $thisuser)
{
echo $html->tableCells($thisuser['User']);
}
?>
</table> |
第一个 helper 将从数据数组(本例中为用户的键列表)创建一组表标题。第二个 helper 将从数据数组(本例中为每个用户的值)创建一组包围在表行标记中的表单元格。
好的!保存它,然后访问 http://localhost/users/knownusers 来查看结果(见图
8)。
图 8. 结果
通过使用 tableCells helper,不必再编写循环遍历用户数据数组的代码。这仅仅是通过 helper
更轻松地在 CakePHP 中使用 HTML 的一个示例。
生成表单
构建不使用表单的 Web 应用程序就像给小鸡喂奶一样:极为复杂,而且基本上是白费工夫。良好的可维护的表单是任何良好的应用程序的基础。如果需要经常构建表单,自然会希望找到能更轻松地完成此过程的方法。
在注册表单中使用 helper
在生成表单时 helper 尤为有用。可以使用它们为输入字段生成 HTML,以及生成占位符来保存检验错误消息。使用
helper 为 Tor 生成表单字段和错误消息占位符,register 视图可能类似于清单 20。
清单 20. 使用 helper 生成注册表单
<p>Please fill out the form below to register an account.</p> <?php echo $form->create('User', array('action' => 'register'));?>
<?php
echo $form->input('first_name');
echo $form->input('last_name');
echo $form->input('username');
echo $form->input('email');
echo $form->input('password');
?>
<?php echo $form->end('Register');?> |
如您所见,使用 CakePHP 的 helper 可以节省编写基本表单元素所需的大量时间。现在来看看如何更充分地利用
helper。
充分利用 helper
要想通过 helper 获得更多的收益,需要做两件事:更新 users 控制器并引入一小段数据检验。打开
controllers/users_controller.php,然后将 register 函数改为清单
21 所示的内容。
清单 21. 更新 users 控制器
function register() { if (!empty($this->data)) { if ($this->User->save($this->data)) { $this->Session->setFlash('Your registration information was accepted.'); } } } |
注意,出现 $this->params['form'] 的位置都已改为 $this->data。
现在,打开 user 模型并添加一小段数据检验(稍后详细说明)。现在,按照清单 22 修改 user
模型。
清单 22. 修改 user 模型
<?php class User extends AppModel { var $name = 'User';
var $validate = array (
'username' => array (
'rule' => 'notEmpty',
'message' => 'This field cannot be left blank.'
),
'password' => array (
'rule' => 'notEmpty',
'message' => 'This field cannot be left blank.'
),
'email' => array(
'rule' => 'email',
'message' => 'Please supply a valid email address.'
)
);
}
?> |
简单解释一下,$validate 数组包含用于检验的条目,由键(表单字段名)和用于评估数据的正则表达式组成。没必要检验所有表单字段。在清单
20 中,last_name 和 first_name 是可选的。CakePHP 附带了若干个预定义的用于数据检验的正则表达式。notEmpty
规则仅用于确保字段不为空,而 email 规则用于检验字符串像不像电子邮件地址。还有许多其他预定义的检验规则。
现在来试着运行一下。尝试提交没有数据的表单,将一个或两个必填字段留空,提供无效的电子邮件地址(见图 9)。您看到了什么?
图 9. 首次尝试数据检验
现在,再来尝试一次,这次缺少不同的数据(见图 10)。
图 10. 第二次尝试数据检验
应当注意的一件事是,CakePHP 会自动显示和关闭错误消息。还应当注意,CakePHP 会记住并填充表单字段的值,无需您执行任何操作。
这就是最大的收益。您不必做哪些操作呢?一方面,不必告诉表单字段重新填充来自 _POST 数组的信息。CakePHP
替您执行了此操作。不必检查每个字段以查找错误,并有条件地单独显示每个消息。CakePHP 替您执行了此操作。不必确保将标记设置为有效的
xhtml。CakePHP 也替您执行了此操作。
helper 说明
本教程只涉及了 helper 的皮毛。这个主题非常广泛,可以针对它撰写一个完整的教程。了解如何更好地使用
helper 将会帮助您进一步加快 CakePHP 开发。CakePHP 包含用于 Ajax(使用 prototype.js)、JavaScript、数字转换、文本处理、日期、时间等方面的helper。要了解这些
helper 的更多信息,请查看手册(请参阅 参考资料)。
CakePHP 数据检验
通过引入基于正则表达式的基本用户检验,您现在应该已经简要了解了 CakePHP
数据检验。通过定义自己的正则表达式来执行数据检验,可以在 Tor 内练习进一步控制各个表单字段的成功/失败条件。
Tor user 模型
再来看一看 user 模型(见清单 23)。
清单 23. user 模型
<?php class User extends AppModel { var $name = 'User';
var $name = 'User';
var $validate = array (
'username' => array (
'rule' => 'notEmpty',
'message' => 'This field cannot be left blank.'
),
'password' => array (
'rule' => 'notEmpty',
'message' => 'This field cannot be left blank.'
),
'email' => array(
'rule' => 'email',
'message' => 'Please supply a valid email address.'
)
}
?> |
这是一个好的开始,但还不够。需要确保字段长度不超出限制并且这个用户名尚不存在。这需要定义自己的用于检验的正则表达式,并定义在保存用户前在
users 表中查找用户名的函数。
正则表达式(简要介绍)
全面讨论正则表达式超出了本教程的范围。PHP Manual 包含 PHP
正则表达式的相关信息,在编写自己的数据检验正则表达式之前应当先参考一下(见 参考资料)。
基本上,正则表达式 是在对一个字符串与另一个字符串进行比较时使用的字符模式。例如,正则表达式中的字符
* 将匹配任意字符任意次数。如果不了解正则表达式,请不必担心。下面的示例应当能帮助您入门。
定义自己的检验
对于用户名和密码字段,需要确认提交的数据长度不超过 40 个字符。检验用户名和密码的长度不少于
6 个字符也会有帮助。此外,我们还将使用的字符限定为数字和字母。用于匹配长度在 6 至 40 个字符之间的字符串的正则表达式类似于
/^[a-z0-9]{6,40}$/i。从左至右阅读这个正则表达式:
/— 表示正则表达式的开头
^— 表示字符串的开头
[a-z0-9]— 表示 a~z 或 0~9 之间的任意字符之一
{6,40}— 表示至少 6 个字符,但不能超过 40 个字符
$— 表示字符串结束
/— 表示正则表达式结束
i— 忽略任意字母的大小写
因此,连在一起读,这个正则表达式的意思就是 “从字符串的开头开始,有至少
6 个但不超过 40 个字母或数字,然后字符串结束,并忽略大小写”。
要使用这个正则表达式(见清单 24),请将出现 notEmpty 的地方替换为用单引号包围的正则表达式(为了阻止
PHP 尝试解释任何特殊字符)。
清单 24. PHP 脚本中的正则表达式
<?php class User extends AppModel { var $name = 'User';
var $validate = array (
'username' => array (
'rule' => '/^[a-z0-9]{6,40}$/i',
'message' => 'This field must have between
6 and 40 alphanumeric characters.'
),
'password' => array (
'rule' => '/^[a-z0-9]{6,40}$/i',
'message' => 'This field must have between
6 and 40 alphanumeric characters.'
),
'email' => array(
'rule' => 'email',
'message' => 'Please supply a valid email address.'
)
);
}
?> |
确保保存所有文件,返回到 http://localhost/users/register,然后尝试用一个具有
4 个字符的用户名注册用户。应当会看到类似图 11 的内容。
图 11. 数据检验
正则表达式可以实现许多功能,但不能执行检查用户名是否已注册之类的操作。
进一步检验
有时,无法仅仅查看数据就判断出它是否有效。例如,用户名可能在 6 至 40 个字符之间,但还必须检查数据库来查看这个用户名是否已被占用。CakePHP
提供了可将字段手动标记为无效的功能。看一看清单 清单 25 中的 beforeValidate 方法。这个方法应该添加到
user 模型中。
清单 25. 检验用户名
function beforeValidate() { if (!$this->id) { if ($this->findByUsername($this->data['User']['username'])) { $this->invalidate('username_unique'); return false; } } return true; } |
这个方法告诉模型,在运行任何检验之前,应该检查提交的数据是否有 ID。如果没有
ID,就寻找用户名相同的其他用户。如果找到这样的用户,就将用户名字段标为无效,并跳过其他检验(返回 false)。通过将
register.ctp 视图中的用户名输入行改为清单 26 所示的代码,就可以启用这个功能。
清单 26. 新的用户名输入行
echo $form->input('username', array('after' => $form->error ('username_unique', 'The username is taken. Please try again.'))); |
这告诉 register 视图,在遇到错误消息 'username_unique'(在
beforeValidate 方法中设置)时应该做什么。
保存文件,然后尝试操作。首先,访问 http://localhost/user/knownusers
以获取现有用户列表。然后访问 http://localhost/user/register,随后尝试创建一个具有相同用户名的用户。应当会看到以下内容,如图
12 所示。
图 12. 数据检验成功
良好的数据检验是创建任何安全应用程序的重要步骤。在构建 Tor 应用程序的过程中,要寻找改进数据检验的机会。不要害怕引入比本教程更多的数据检验。决不要假定用户会把所需的数据发送给您。检验一切内容。CakePHP
可以帮助您轻松完成。
补充功能
到目前为止,用户可以向应用程序注册并查看已经注册的其他用户。这个应用程序需要补充一些功能。使用迄今为止您学到的技巧,尝试补充更多功能。请查阅
第 2 部分 以获得以下内容的示例。
登录
login 视图应当收集用户登录信息并将其提交给 users 控制器。users
控制器应当查看这个用户是否已在数据库中,并检验密码是否正确。如果用户已经正确地登录,则把用户名写入会话并把用户发送到
index 操作。
提示:
使用内置的 $this->User->findByUsername($your_username_variable_here)
在数据库中搜索用户
用 $this->Session->write('user',
$your_username_variable_here) 把用户的名称写到 Session 中
Index 操作
index 操作应当查看用户的名称是否已被写入会话。如果用户的名称已被写入会话,则将该信息从数据库中取出,并向用户显示一条定制的欢迎词。如果用户尚未登录,则让用户执行
login 操作。
注销
logout 操作应当从会话中删除用户的用户名,并将用户转发到 login
操作。
其他
修改 register 操作,把用户自动登录到系统中,并把用户转到 index
操作。修改 register 和 login 操作以使用散列的密码,而不是将密码作为明文保存到数据库中。
如果对上述问题还不是很清楚,请不必过分担心。第 2 部分 将提供这些问题的示例解决方案,从而让您可以投入其中并构建出
Tor 应用程序产品库。
编程愉快!
结束语
本教程讲解了如何安装和配置 CakePHP、MVC 设计的基本原理、如何在
CakePHP 中检验用户数据、如何使用 CakePHP helper 以及如何使用 CakePHP 快速建立并运行应用程序。第
2 部分 将介绍如何为应用程序编写插件以及如何使用 CakePHP 访问控制列表(ACL)。
|