CakePHP 自2005年首次发布以来,它的web应用程序开发特性集是否持续大幅增长. As a result, 完全掌握其用于软件开发的能力需要一些时间, 这使得寻找真正的CakePHP专家成为一个真正的挑战.
寻找高质量的CakePHP程序员需要一个高效的招聘过程, 正如我们在文章中所描述的 寻找并雇佣行业内的佼佼者 . 这样的过程可以用问题来扩展——比如这里给出的问题——来识别那些真正掌握了CakePHP web开发的候选人.
问:CakePHP约定和对象关系映射(ORM)如何帮助简化查询? 还要讨论任何潜在的缺陷.
CakePHP的对象关系映射(ORM)从CakePHP约定中受益匪浅. 通过按照Cake的标准设置数据库模式, 您可以通过Cake强大的ORM快速地将表连接在一起. 你几乎不需要编写SQL语句,因为CakePHP可以处理表连接之类的事情, hasMany
, and even hasAndBelongsToMany
轻松的关系.
充分利用CakePHP的 ContainableBehavior
, 通过模型关联,您可以指定要从SQL查询中选择哪些数据库表和字段. 这可以深入到几张表, 通过ORM可以很容易地快速构建高度复杂的SQL语句. 它可以帮助您以干净一致的方式搜索和过滤数据,还可以帮助提高应用程序的速度和整体性能. (它的工作原理是暂时或永久地改变你的模型的关联, 使用提供的容器生成一系列对应的 bindModel
and unbindModel
calls.)
Overall, Cake的ORM确实有助于简化开发流程, if used correctly, 是一个快速构建复杂查询的神奇工具吗. 尽管如此,开发人员花时间完全理解ORM并确保他们的查询得到适当优化(在任何语言中都是如此)是至关重要的。.
ORM的挑战在于,它使使用SQL变得如此简单, 如果开发者不小心, 他或她可以无意地编写低效的SQL查询. 这些问题往往会在系统部署之后出现, 随着数据库的增长,写得不好的查询变得越来越慢.
问:什么是CakePHP助手? 列出10种可用的helper类型,并使用 FormHelper
作为一个例子,描述如何使用helper来加速开发.
CakePHP Helpers 应用程序的表示层是类似组件的类吗. 它们包含可以被许多视图、元素或布局共享的逻辑.
CakePHP中可用的10种帮助器是:
CacheHelper
FormHelper
HtmlHelper
JsHelper
NumberHelper
Paginator
RSS
SessionHelper
TextHelper
TimeHelper
通过将常用功能封装为可重用的形式, CakePHP helper帮助加快开发. 一个很好的例子是 FormHelper ,它根据数据库表模式设置创建表单输入字段. For example, 一个TINY INT字段将自动映射到一个复选框, 而TEXT字段将自动映射到文本区域.
通过确保FormHelper名称与数据库表中的名称匹配, 表单将自动创建.
使用您的数据验证规则,CakePHP将 automatically 如果数据验证失败,则在表单输入旁边显示错误消息. 开发人员需要做的就是将表单输入与数据库中的字段相匹配. 在控制器的帮助下, 一旦验证成功通过,数据将自动保存到数据库中.
问:什么是组件?使用组件的好处是什么? 提供一个如何通过控制器访问组件的示例.
Components 控制器之间是否共享逻辑模块. CakePHP自带一组核心组件用于常见任务,您也可以创建自己的组件. 创建和使用组件可以帮助保持控制器代码的整洁,并促进跨项目和跨项目之间的代码重用. For example, 您可能希望创建一个自定义“购物车”组件,以便在电子商务应用程序中跨多个控制器使用.
控制器中包含的每个组件都作为该控制器的属性公开. 例如,如果您包含 SessionComponent
and the CookieComponent
在你的控制器中,你可以这样访问它们:
类PostsController扩展AppController {
Public $components = array('Session', 'Cookie');
公共函数delete() {
if ($this->Post->delete($this->request->data('Post.id')) {
$this->Session->setFlash('Post deleted.');
return $this->redirect(array('action' => 'index'));
}
}
问:什么是行为?它们的优点是什么? 列出CakePHP中“开箱即用”支持的4种行为.
与组件扩展控制器的方式大致相同 Behavior extends a Model. 行为使您能够分离和重用执行某种行为类型的逻辑, 而且不需要继承遗产.
As an example, 考虑一个模型,该模型提供对存储树结构信息的数据库表的访问. Removing, adding, 在树中迁移节点并不像删除节点那么简单, inserting, 编辑表中的行. 而不是在每个模型的基础上创建那些树操作方法(对于每个需要该功能的模型), 我们可以简单地把 TreeBehavior to our model.
以下4个行为在CakePHP中是“开箱即用”的:
AclBehavior :提供了一种将模型与ACL(访问控制列表)系统无缝集成的方法
ContainableBehavior 简化了搜索和过滤操作
TranslateBehavior :用于国际化
TreeBehavior :便于访问和操作数据库表中的分层数据
你也可以创建自己的行为. 行为可以是保持代码库整洁并使代码远离控制器的好方法. 开源就是一个很好的例子 ImageUploadBehavior
它允许非常简单的图像或文件上传. 通过在模型文件中指定一些规则, 文件将被自动验证和上传, 在控制器文件中不需要额外的代码. 这种特殊行为的额外好处是它使用 PHP Thumb 自动调整任何图片上传的大小.
问:如何处理CakePHP中的嵌套数据,比如类别树?
创建一个无限层次的类别结构是CakePHP的一个很好的例子 TreeBehavior can come in handy.
使用TreeBehavior非常简单,在你的模型文件中如下所示:
public $actsAs = 'Tree';
类别表可能看起来像这样:
创建表类别
id INTEGER(10) UNSIGNED NOT NULL
parent_id INTEGER(10) DEFAULT NULL,
左整数(10)默认NULL,
右整数(10)默认NULL,
name VARCHAR(255) DEFAULT ",
PRIMARY KEY (id)
);
By setting the parent_id
字段保存数据时, lft
and rght
字段将自动填充. The lft
and rght
fields follow an MPTT(修改的预定树遍历) structure.
然后,所有TreeBehavior的方法都可以使用. Examples include:
generateTreeList()
-返回值的层次数组(例如.g.,用于HTML选择框等.)
孩子(parentId美元)
-返回指定元素的子元素列表 $parentId
getPath($id)
-返回一个节点数组,在树中分层遍历以到达指定的节点 $id
问:如何在CakePHP中执行数据验证?
CakePHP简化了数据验证, 使您能够在模型文件中为每个数据库表指定数据验证规则,这些规则对于该模型是通用的. 这符合 DRY(不要重复自己的话) 原则,允许您只指定一次规则,然后让它们在整个模型中应用.
CakePHP中支持的验证规则很多. 下面是一些很好的例子:
Public $validate = array(
'phone' => array(
'rule' => 'phone',
'message' => 'A valid phone number is required.'
),
'email' => array(
'rule' => 'email',
'message' => 'A valid email address is required.'
),
'password' => array(
'rule' => array('minLength', '8'),
'message' => 'Minimum 8 characters long'
),
'dob' => array(
'rule' => 'date',
'message' => 'Enter a valid date',
'allowEmpty' => true
)
);
特别要注意 allowEmpty
key in the 'dob'
数组,该数组允许字段为空. 基于这些验证规则, dob字段可以留空, 但是如果输入一个日期, 它将被检查以确认它是一个有效的日期值.
问:在CakePHP中提供一些文件夹和文件操作的例子.
通常单独使用标准PHP是一个挑战 Folder & File Utilities 在需要创建、上传或操作文件夹或文件时是否有用.
以下是一些关键的例子:
The Folder::copy
方法简化了将文件从一个位置复制到另一个位置:
//复制folder1及其所有内容到folder2
$folder1 = new Folder('/path/to/folder1');
$folder1->copy('/path/to/folder2');
The Folder::copy
方法还支持其他选项. Specifically:
$folder = new folder ('/path/to/folder');
$folder->copy(array(
'to' => '/path/to/new/folder',
'from' => '/path/to/copy/from',
'mode' => 0755,
'skip' => array('skip-me.php', '.git'),
'scheme' => Folder::SKIP // Skip directories/files that already exist
));
或创建新文件夹,只需使用 Folder::create
method:
$folder = new folder ();
if ($folder->create('foo' . DS . 'bar' . DS . 'baz' . DS . 'shoe' . DS . 'horn')) {
//成功创建嵌套文件夹
}
The Folder::find
方法特别有用,因为它使您能够动态查找目录中的文件:
// Find all .PNG在你的app/webroot/img/文件夹和排序的结果
$dir = new Folder(wwww_root . path . 'img');
$files = $dir->find('.*\.png', true);
问:“胖模型,瘦控制器”的方法有哪些优点? 提供一个如何在CakePHP中使用它的示例.
“Fat Model, “瘦控制器”——经常被Ruby on Rails开发者所提倡——是Ruby on Rails中的一种方法 模型/视图/控制器(MVC) 架构范例,逻辑应该主要存在于模型中. 这将“瘦”控制器降级为视图和模型之间的控制接口.
Consider, for example, 执行一个简单的CRUD(创建), read, 更新和删除)操作, 比如在博客中添加帖子. 默认的add方法可能如下所示:
公共函数add() {
if ($this->request->is('post')) {
$this->Post->create();
if ($this->Post->save($this->request->data)) {
$this->Session->setFlash(__('Your post has been saved.'));
return $this->redirect(array('action' => 'index'));
}
$this->Session->setFlash(__('Unable to add your post.'));
}
}
这个控制器动作对于一个简单的添加来说是很好的, 但是,如果您想在添加帖子时向管理员发送电子邮件等操作,会发生什么呢, 或者在添加帖子时更新另一个模型关联? 这是额外的逻辑,但是这个逻辑不应该出现在控制器文件中.
相反,我们可以在 Post.php
模型,也许是这样的:
公共功能addPost($data = array(), $emailAdmin = true) {
$this->create();
$this->save($data);
//更新其他表
if ($emailAdmin) {
//发送邮件给admin用户
}
//如果一切成功
return true;
}
这将只需要对控制器动作做如下的小改变:
公共函数add() {
if ($this->request->is('post')) {
if ($this->Post->addPost($this->request->data)) {
$this->Session->setFlash(__('Your post has been saved.'));
return $this->redirect(array('action' => 'index'));
}
$this->Session->setFlash(__('Unable to add your post.'));
}
}
如您所见,新操作实际上少了一行,因为 $this->Post->create()
已经移动到模型文件,帮助实现干净和简洁的代码.
问:CakePHP如何处理身份验证和用户登录? 提供一个代码示例.
CakePHP有一个内置的身份验证组件(AuthComponent ),这使得设置用户注册和登录系统非常简单. 通过设置带有用户名或电子邮件字段和密码字段的用户表, 程序员可以快速地将身份验证合并到他们的应用程序中. CakePHP还处理密码加密, 提供了几个不同的加密类,包括B加密和摘要身份验证. CakePHP也有一些高级的方法来做一些事情,比如自动登录用户.
以下是如何在代码中轻松利用这些功能的方法:
您的数据库表可能看起来像这样:
创建表用户
INT UNSIGNED AUTO_INCREMENT主键;
用户名VARCHAR (50),
密码VARCHAR (255),
role VARCHAR(20),
创建DATETIME默认为NULL
修改后的DATETIME默认为NULL
);
In your AppController.php
然后设置组件:
/ /应用程序/控制器/有一个.php
类AppController扩展控制器{
Public $components = array(
'Session',
'Auth' => array(
'loginRedirect' => array(
'controller' => 'posts',
'action' => 'index'
),
'logoutRedirect' => array(
'controller' => 'pages',
'action' => 'display',
'home'
),
'authenticate' => array(
'Form' => array(
'passwordHasher' => 'Blowfish'
)
)
)
);
In your User.php
模型文件中,您可以将密码加密代码设置在 beforeSave
callback:
// app/Model/User.php
应用程序:使用(“AppModel的”、“模型”);
应用::使用(“BlowfishPasswordHasher”,“控制器/组件/身份验证”);
类用户扩展AppModel {
// ...
公共函数beforeSave($options = array()) {
if (isset($this->data[$this->alias]['password'])) {
$passwordHasher = new BlowfishPasswordHasher();
$this->data[$this->alias]['password'] = $passwordHasher->hash(
$this->data[$this->alias]['password']
);
}
return true;
}
Then, in your UsersController.php
,可以设置登录动作:
/ /应用程序/控制器/ UsersController.php
公共函数login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirect());
}
$this->Session->setFlash(__('Invalid username or password, try again'));
}
}
注意它是多么简单. 代码只是查找一个帖子,然后调用 Auth->login
组件方法,用于登录用户.
视图登录文件可能看起来像这样:
/ /应用程序/视图/用户/登录.ctp
Form->create('User'); ?>
Form->input('username');
echo $this->Form->input('password');
?>
Form->end(__('Login')); ?>
只需用用户名和密码字段设置表单,CakePHP将处理其余的工作.
最后,对于注销脚本,在您的 UsersController
注销操作看起来像这样:
公共函数注销(){
return $this->redirect($this->Auth->logout());
}
问:请举例说明如何使用CakePHP的回调函数.
CakePHP回调使您能够在模型操作之前操作或检查数据. 验证前的例子包括, before save, after save, before delete, after delete, and after find.
For example, 考虑这样一种情况,您希望操作一个日期,使其显示方式不同于保存在数据库中的方式. (也许您正在使用一个旧的数据库,该数据库将日期保存在 time()
格式或非标准数据库日期格式.)
要做到这一点,这些回调可以在你的模型文件中:
public function afterFind($results, $primary = false) {
foreach ($results as $key => $val) {
如果(isset(美元瓦尔(“事件”)(“begindate”))) {
$results[$key]['Event']['begindate'] = $this->dateFormatAfterFind(
美元瓦尔(“事件”)(“begindate”)
);
}
}
return $results;
}
dateFormatAfterFind($dateString) {
return date('d-m-Y', strtotime($dateString));
}
The afterFind
Callback将获取查找查询返回的数据,并更改日期的格式. 在本例中,我们将日期设置为 d-m-Y
格式——可能是准备数据进入日期选择器或类似的东西. 该代码将在数据返回到控制器之前被调用, 它允许我们在控制器接收数据之前操作数据.
在保存数据之前,我们还需要有一个回调, 要将日期格式还原为数据库中使用的格式:
公共函数beforeSave($options = array()) {
if (!empty($this->data['Event']['begindate'])) {
$this->data['Event']['begindate'] = $this->dateFormatBeforeSave(
$this->data['Event']['begindate']
);
}
//确保返回true,否则保存将失败!
return true;
}
dateFormatBeforeSave($dateString) {
return date('Y-m-d', strtotime($dateString));
}
问:CakePHP中的虚拟字段是什么? 你如何使用它们,为什么使用它们. Provide an example.
Virtual Fields 允许您创建任意SQL表达式并将其分配为模型中的字段. 这些字段不能保存,但将像其他模型字段一样进行读操作. 它们将在模型的键下与其他模型字段一起被索引.
作为一个简单的例子,考虑一个包含 first_name
and last_name
fields. 您可能会发现,您经常希望使用用户的全名. 在这种情况下,你可以在你的模型文件中添加:
public $virtualFields = array(
'full_name' => 'CONCAT(User.first_name, " ", User.last_name)'
);
这将添加一个名为 full_name
. 当执行查找查询时,数据将显示如下:
Array
(
[0] => Array
(
[User] => Array
(
[id] => 1
[fist_name] => John
[last_name] => Smith
[full_name] => John Smith
)
)
)
虚拟字段的另一个很好的用途是当您需要计算数据时. 让我们以文章有注释的例子为例. 我们经常需要计算一篇文章有多少评论. 这在虚拟字段中很容易做到. 例如,在你的模型文件中,你可以添加以下内容:
public $virtualFields = array(
'num_comments' => 'SELECT COUNT(id) FROM comments WHERE article_id = Article.id'
);
This will add num_comments
在任何文章查找查询的末尾,e.g:
Array
(
[0] => Array
(
[Article] => Array
(
[id] => 1
[title] => Test Article
[description] => Test Description
[num_comments] => 2
)
)
)
但是,虚拟字段并非没有任何惩罚. 它们的缺点是性能. 在创建虚拟字段时应该记住这一点, 你的虚拟领域越复杂, 虚拟字段对查询性能的影响越大.
Wrap-up
无论你是在美国还是国外, 寻找全职或兼职的帮助, 本指南中提出的问题可以非常有效地评估开发人员对CakePHP开发框架知识的广度和深度. 然而,重要的是要记住,这些问题仅仅是作为一个指南. 并不是每一个值得雇佣的“A”候选人都能正确回答所有问题, 回答所有问题也不能保证成为A级考生. 在一天结束的时候, 雇佣专门的CakePHP开发人员既是一门科学,也是一门艺术.