CakePHP中文手册【翻译】-Cake Blog创建指南
Cake Blog创建指南
第1节
介绍
欢迎来到Cake。你可能正在使用本指南,因为你想学习更多关于Cake是如何工作的知识。其目的就是为了提高效率,并且让编写代码变得更加有趣。我们希望当你深入代码时能够体会到这些。
本指南将一步步向你介绍如何创建一个简单blog应用程序。我们会获取并安装Cake,创建和配置数据库,而且构建充分的应用程序逻辑来列出,增加,编辑以及删除blog的post。
下面是你需要的东西:
1.
一个正在运行的web服务器。我们假设你正在使用Apache,对于你正在使用其他服务器,遵循的指令是非常相似的。我们也许不得不对服务器作出一点配置,但是大多数人可以在完全不用配置的情况下让Cake运行起来。
2.
一个数据服务器。在本指南中我们打算使用MySQL。你需要知道SQL,以便创建一个数据库:Cake将会在这里占主导地位。
3.
基本的PHP知识。你对面向对象编程做的越多,那么会越好:但是如果你是一个热衷于过程编程的话,也不用害怕。
4.
最后,你需要掌握一些关于MVC变成模式的只是。可以在“基本概念”一章中的第2节:MVC模式中有一个快速的概括。不用担心,它仅半页左右而已。
让我们开始吧。
第2节
获取Cake
首先,让我们得到一份最新的Cake代码。在我们编写本手册时,我们使用的最新发行版本是CakePHP 1.0.1.2708.
为了获取一个最新的版本,请访问CakeForge上的CakePHP项目:http://cakeforge.org/projects/cakephp/
,并下载一个稳定的版本。
你也可以从https://svn.cakephp.org/repo/trunk/cake/1.x.x.x/取出/导出一份最新的代码。
不管你如何下载它,都将这些代码放在你的DocumentRoot,一旦完成之后,你的目录结构看起来应该如下:
/path_to_document_root
/app
/cake
/vendors
.htaccess
index.php
VERSION.txt
|
现在也许是一个好时候学习一点点关于Cake的目录结构是如何工作的:查看"基本概念"这一章的第3节:Cake文件布局总览。
第3节
创建Blog数据库
下面,让我们为blog建立底层的数据库。现在,我们仅仅需要建立一个表来存储我们的post。我们也应该马上发表一些post来测试它。执行下面的SQL语句到数据库中:
/* First, create our posts table: */ CREATE TABLE posts (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(50),
body TEXT,
created DATETIME DEFAULT NULL,
modified DATETIME DEFAULT NULL ); /* Then insert some posts for testing: */ INSERT INTO posts (title,body,created) VALUES ('The
title', 'This is the post body.', NOW()); INSERT INTO posts (title,body,created) VALUES ('A
title once again', 'And the post body follows.', NOW()); INSERT INTO posts (title,body,created)
VALUES ('Title
strikes back', 'This is really exciting! Not.',
NOW()); |
表上的选项以及列名并不是随心所欲的。如果你遵照了Cake的数据库命名规则,以及Cake的类命名规则(都在附录"Cake规则"中有描述),你将会使用许多免费功能,并且可以避免配置。甚至当配置那些遗留下来的最坏的数据库结构时,Cake也非常灵活,但是遵照规则,会给你省下不少时间。
参看附录"Cake命名规则"获取更多信息,自动命名我们的表'posts',这会将它应用到Post model中。Cake会自动将字段称为 'modified' 以及'created'。
第4节
Cake数据库配置
前前后后:让我们告诉Cake我们的数据库在什么地方,并且如何才能连接到它。这是你配置任何事情的第一次,也是最后一次。
可以在/app/config/database.php.default发现一个数据库配置的拷贝。在相同的目录下制作本文件的另一份拷贝,但是需将它命名为database.php.
配置文件也是相当直观明了:将$default数组中的值替换为在你的建立中应用的值。一个完成的简单配置数组可以如下:
var $default = array('driver' => 'mysql', 'connect' => 'mysql_pconnect', 'host' => 'localhost', 'login' => 'cakeBlog', 'password' => 'c4k3-rUl3Z', 'database' => 'cake_blog_tutorial' ); |
一旦保存了新的database.php文件,你可以打开你的浏览器,应该可以看到Cake的欢迎页面,它告诉你已经找到你的数据库连接文件,并且Cake可以成功的连接到数据库。
第5节
关于mod_rewrite的说明
一个新用户偶尔会走进mod_rewrite问题中,因此我会在外面提起他们。如果Cake的欢迎页面看起来有点意思(没有图像以及CSS样式),这意味着在系统里mod_rewrite没有起作用。这里有一些技巧帮助你站起来,并让它运行:
1.
确保一个.htaccess
覆盖是允许的:在httpd.conf中,你应该有一块为服务器上的每个Directory定义一个部分。对相应的Directory,务必将AllowOverride 设为All。
2.
确保编辑系统的httpd.conf,而非一个用户级或者站点级的httpd.conf。
3.
由于某种原因或其他,你可能已经获取没有需要的.htaccess文件的CakePHP拷贝。有时会出现这种情况,因为有些操作系统将以"."开头的文件当成隐藏文件,而且不要复制他们。确保你的CakePHP来自站点的下载部分以及SVN里。
4.
确保正确加载mod_rewrite!在httpd.conf,你应该可以看到类似LoadModule rewrite_module libexec/httpd/mod_rewrite.so 和AddModule mod_rewrite.c的东西。
如果不想或者不能让mod_rewrite(或者其他兼容的模块)在你的服务器上运行,你需要使用Cake内建的URL。在/app/config/core.php, 取消下面的行的注释:
define ('BASE_URL', env('SCRIPT_NAME')); |
它让URL看起来像:
www.example.com/index.php/controllername/actionname/param
而非www.example.com/controllername/actionname/param.
第6节
创建一个Post model
Model类是CakePHP应用程序的面包和奶油。创建一个与我们数据库交互的Cake Model,这样我们在稍后就有基础来完成查看,增加,编辑,以及删除操作。
Cake的Model类文件在/app/models中,而且我们将创建的文件将保存为/app/models/post.php.完成的文件应该如下:
/app/models/post.php
<?php class Post extends AppModel { var $name = 'Post'; } ?> |
因为类和文件的命名方式,它会告诉Cake你想让一个Post Model在PostsController中可用,此PostsController与缺省的数据库中的’posts’表紧紧相联系。
一直使用$name变量是一个不错的主意,可以使用它来避免PHP4中的某些类名的差异。
为获取更多关于model的信息,如表前缀,回调,验证,参考“Model”这一章。
第7节
创建一个Posts Controller
接下来,为我们的post创建一个controller。Controller是所有post交互逻辑发生之处,它也是找到所有model的动作的地方。你应该将新的Controller放在一个posts_controller.php文件里,此文件在 /app/controllers 目录之下。基本的Controller应该如下:
下面
/app/controllers/posts_controller.php
<?php class PostsController extends
AppController { var $name = 'Posts'; } ?> |
现在,让我们为Controller加入一个动作。当用户请求www.example.com/posts时,它和请求www.example.com/posts/index一样。因为当我们的读者访问此URL时,我们想让他们查看一列Post,index动作看起来应该如下:
/app/controllers/posts_controller.php
(index action added)
<?php class PostsController extends
AppController { var $name = 'Posts'; function index() {
$this->set('posts', $this->Post->findAll()); } } ?> |
让我稍微解释一下此动作。在PostsController里定义index()函数,用户现在可以请求www.example.com/posts/index来访问这里的逻辑。同样,如果我们定义一个foobar()函数,用户可以访问www.example.com/posts/foorbar。
在此动作里,唯一一行代码使用了set()将数据传送到view(我们接下来view)。本行代码设置了一个view变量'posts',它等同于返回Post
model的findAll()方法的值。Post model在$this->Post中自动可用,因为我们已经遵循了Cake的命名规则。
为了学习更多关于Cake Controller的信息,参看'Controller’这章。
第8节
创建Post View
既然我们已经使用model将数据库连接起来,而且controller已经定义了应用程序逻辑和流程,那就让我们为上面定义的index动作创建一个view吧。
Cake view只不过是应用程序布局里的HTML和PHP元素片段。可以定义布局,并且在他们之间选择他们。但是,现在还是让我们使用默认的吧。
还记得在上一节我们是如何使用set()方法将'posts'变量赋值给view的吗?下面的代码将处理传给view的数据:
// print_r($posts) output: Array (
[0] => Array
(
[Post] => Array ( [id] => 1
[title] => The
title [body] => This is the
post body. [created] =>
2006-03-08 14:42:22 [modified] => )
)
[1] => Array
(
[Post] => Array ( [id] => 2 [title] => A title
once again [body] => And the post
body follows. [created] =>
2006-03-08 14:42:23 [modified] =>
)
)
[2] => Array
(
[Post] => Array ( [id] => 3 [title] => Title
strikes back [body] => This is
really exciting! Not. [created] =>
2006-03-08 14:42:24 [modified] => )
) ) |
Cake的view文件存储在一个/app/views的他们对应的Controller后命名的文件夹下(我们必须创建一个名为'posts'的文件夹)。为了将post数据以表格的形式非常好的格式化,我们的view代码看起来应该是::
/app/views/posts/index.thtml
<h1>Blog posts</h1> <table> <tr>
<th>Id</th>
<th>Title</th>
<th>Created</th> </tr> <!-- Here's where we loop through our
$posts array, printing out post info --> <?php foreach ($posts as $post): ?> <tr>
<td><?php
echo $post['Post']['id']; ?></td>
<td>
<?php echo
$html->link($post['Post']['title'],
"/posts/view/".$post['Post']['id']); ?>
</td>
<td><?php
echo $post['Post']['created']; ?></td> </tr> <?php endforeach; ?> </table> |
希望它看起来比较简单。
你可能已经注意到一个$html对象的使用。它是一个HtmlHelper类的实例。Cake带有一组view 'helper’,这些'helper'会做一些事情,例如链接,表单输出,JavaScript,Ajax等。你可以在‘Helper'一章中学到更多关于如何使用他们的知识。但是这里更需要注意的重要事情是link()方法生成一个给定标题(第一个参数)和URL(第二个参数)的HTML链接。
当在Cake里指定URL的同时,你简单给定一个基于应用程序的相对路径,Cake会填充剩余的。例如,你的URL典型的会采用/controller/action/id的格式。
现在你应该可以将浏览器指向http://www.example.com/posts/index.
你会看到你的view已经正确格式化标题以及显示post列的表格。
如果你碰巧点击我们在view创建的链接之一(它会将post的标题链接到URL /posts/view/some_id),Cake很有可能提示你动作没有定义。如果你没有得到提示,要么是某些事情错误,要么是实际上你已经定义,不管是哪一种情况,你都会很不爽。否则的话,现在让我们创建一个吧:
/app/controllers/posts_controller.php
(增加了view 动作)
<?php class PostsController extends
AppController { var $name = 'Posts'; function index() {
$this->set('posts', $this->Post->findAll()); } function view($id = null) {
$this->Post->id = $id;
$this->set('post', $this->Post->read()); } } ?> |
set()调用应该非常熟悉。注意我们正在使用read()而不是findAll(),因为我们只想得到一个post信息。
注意view动作只有一个参数。这个参数用来处理URL调用的动作。如果一个用户请求/posts/view/3,那么'3'会传递给$id.
现在让们为新的'view'动作创建一个view,并将它放到/app/views/posts/view.thtml.
/app/views/posts/view.thtml
<h1><?php echo $post['Post']['title']?></h1> <p><small>Created: <?php echo $post['Post']['created']?></small></p> <p><?php echo $post['Post']['body']?></p> |
试一试/posts/index或者手动请求/posts/view/1看它是否运行。
第9节
增加Post
从数据库读取数据,并为我们显示post,这非常好,并且非常花俏,但是让我们允许增加新的post吧。
首先,从PostsController的add()动作开始吧:
/app/controllers/posts_controller.php
(已加入add动作)
<?php class PostsController extends
AppController { var $name = 'Posts'; function index() {
$this->set('posts', $this->Post->findAll()); } function view($id) {
$this->Post->id = $id;
$this->set('post', $this->Post->read()); } function add() {
if (!empty($this->data))
{
if ($this->Post->save($this->data))
{ $this->flash('Your
post has been saved.','/posts');
}
} } } ?> |
让我们以普通的英语为你读读add()动作吧:如果表单数据不为空,试图使用这些数据保存post model。如果由于某些原因他没有保存,给我数据验证错误,并让view显示这些错误。
当一个用户使用一个表单来POST数据到应用程序中,这些信息在$this->params中可以得到。如果你想看看它到底是什么样子,你可以将它pr()(译者注:pr()的作用是打印,更多信息,请参看Cake的全局函数)出。$this->data是$this->params['data']的别名。
$this->flash()函数是一个Controller函数,它会将一个信息在用户面前闪过几秒(使用flash布局),然后将用户前进到另外一个URL(这里是/posts)。如果DEBUG设置为0,$this->flash()会自动跳转,虽说如此,如果DEBUG>0的话,你可以看到一个闪烁的布局,并且点击消息来完成跳转。
调用save()方法的时候,会检查验证错误,如果任何错误发生,它不会保存。这里有许多方法可用,你可以检查验证错误,但是我们会说一点validateErrors()调用,因此当我们转到数据验证那节向你说明view是什么样的同时,让背后添材加火的人先停下来吧。
第10节
数据验证
Cake采用一种比较长的方法来脱离单调的表单数据验证。每个人都讨厌无休止的编码以及他们的验证路线。Cake让他们变得更容易,而且更快。
为了利用验证特征,你需要在view中使用Cakede HtmlHelper。HtmlHelper对所有view都缺省可用,而且为$html.
这里是我们的增加view:
/app/views/posts/add.thtml
<h1>Add Post</h1> <form method="post"
action="<?php echo $html->url('/posts/add')?>">
<p>
Title:
<?php echo $html->input('Post/title',
array('size' => '40'))?>
<?php echo $html->tagErrorMsg('Post/title',
'Title is required.') ?>
</p>
<p>
Body:
<?php echo $html->textarea('Post/body',
array('rows'=>'10')) ?>
<?php echo $html->tagErrorMsg('Post/body',
'Body is required.') ?>
</p>
<p>
<?php echo $html->submit('Save')
?>
</p> </form> |
伴随$html->link(),$html->url()会为来自Controller和我们给它的动作生成一个合适的URL。缺省的,它会打印一个POST表单标记,但是它可以由第二个参数修改。$html->input()以及$html->textarea()函数生成相同名字的表单元素。第一个参数告诉Cake它们对应哪一个model和字段,第二个参数是一个多余的HTML属性(像input字段的大小)。参看’Helper‘这一章了解更多关于Helper的知识。
一旦有一个验证错误,tagErrorMsg()函数会输出错误信息。
如果你愿意,你可以更新你的/app/views/posts/index.thtml view来包含一个新的’Add Post'链接,此链接指向www.example.com/posts/add.
看起来它足够酷了,但是我如何告诉Cake我的验证需求呢?这就是我们返回到model的地方。
/app/models/post.php
(validation array added)
<?php class Post extends AppModel { var $name = 'Post'; var $validate = array(
'title' => VALID_NOT_EMPTY,
'body' => VALID_NOT_EMPTY
); } ?> |
$validate数组告诉Cake当调用save()方法时如何验证你的数据。这些键值仅仅是Cake设置的常数,解释为正则匹配(参看/cake/libs/validators.php),刚才Cake的验证就是基于正则的,但是你也可以使用Model::invalidate()动态设置你自己的验证。
既然你有自己的验证,使用应用程序并在没有标题或者body情况下,试图增加一个post看看它是如何工作的。
第11节
删除Post
接下来,我们会为用户创建一种途径来删除post。在PostsController里从delete()动作开始:
/app/controllers/posts_controller.php
(仅删除动作)
function delete($id) { $this->Post->del($id); $this->flash('The post with id: '.$id.' has been deleted.', '/posts'); } |
本逻辑会删除$id的post,并在转向到/posts之前,使用flash()向用户显示一个确认信息。
因为我们正执行某些逻辑以及重定向,所以本动作是没有view的。即便如此,你也许想更新你的index view,使用户可以删除post。
/app/views/posts/index.thtml
(加入增加以及删除链接)
<h1>Blog posts</h1> <p><?php echo $html->link('Add Post',
'/posts/add'); ?></p> <table> <tr>
<th>Id</th>
<th>Title</th>
<th>Created</th> </tr> <!-- Here's where we loop through our
$posts array, printing out post info --> <?php foreach ($posts as $post): ?> <tr>
<td><?php
echo $post['Post']['id']; ?></td>
<td>
<?php echo
$html->link($post['Post']['title'], '/posts/view/'.$post['Post']['id']);?>
<?php echo $html->link( 'Delete',
"/posts/delete/{$post['Post']['id']}", null, 'Are you sure?' )?>
</td>
</td>
<td><?php
echo $post['Post']['created']; ?></td> </tr> <?php endforeach; ?> </table> |
在用户试图删除一个post时,view代码也会使用HtmlHelper并用一个JavaScript的确认对话框来提示用户。
第12节
编辑Post
因此...,我们在这里对post进行编辑吧。到现在为止,你已是一个Cake专业人士了,因此你应该已经捡起一个模式了。先实现动作,然后是view。Post Controller的编辑动作应该如下:
/app/controllers/posts_controller.php
(仅编辑动作)
function edit($id = null) { if (empty($this->data)) {
$this->Post->id = $id;
$this->data = $this->Post->read(); } else {
if ($this->Post->save($this->data['Post']))
{
$this->flash('Your post has been
updated.','/posts');
} } } |
它会检查一下提交的表单数据。如果什么都没有提交,它会查找Post,并提交给view。如果提交了某些数据,会试图保存Post model(或返回,并向用户显示验证错误)。
编辑的view可能如下:
/app/views/posts/edit.thtml
<h1>Edit Post</h1> <form method="post" action="<?php
echo $html->url('/posts/edit')?>"> <?php echo $html->hidden('Post/id'); ?> <p>
Title:
<?php echo $html->input('Post/title',
array('size' => '40'))?>
<?php echo $html->tagErrorMsg('Post/title',
'Title is required.') ?> </p> <p>
Body:
<?php echo $html->textarea('Post/body',
array('rows'=>'10')) ?>
<?php echo
$html->tagErrorMsg('Post/body', 'Body is required.') ?> </p> <p>
<?php echo $html->submit('Save') ?> </p> </form> |
本view输出编辑的表单(并带有值),以及必要的错误信息(如果有的话).这里需要注意的常见事情是:如果'id'字段存在并且已经存在了当前的model,Cake会假定你正在编辑一个model。如果'id'不存在(回头看看add视图),当调用save()时,Cake假定你正在插入一个新的model。
你现在可以让你的index view带有链接,以至能编辑指定的post:
/app/views/posts/index.thtml
(加入编辑链接)
<h1>Blog posts</h1> <p><a href="/posts/add">Add Post</a></p> <table> <tr>
<th>Id</th>
<th>Title</th>
<th>Created</th> </tr> <!-- Here's where we loop through our
$posts array, printing out post info --> <?php foreach ($posts as $post): ?> <tr>
<td><?php
echo $post['Post']['id']; ?></td>
<td>
<?php echo
$html->link($post['Post']['title'], '/posts/view/'.$post['Post']['id']);?>
<?php echo $html->link( 'Delete',
"/posts/delete/{$post['Post']['id']}", null, 'Are you sure?' )?>
<?php echo $html->link('Edit',
'/posts/edit/'.$post['Post']['id']);?>
</td>
</td>
<td><?php
echo $post['Post']['created']; ?></td> </tr> <?php endforeach; ?> </table> |
第13节
路由
本部分可选,但是有助于你理解Cake的URL如何映射到指定的函数调用。在本指导里,我们仅打算对路由做出一个快速的变化。要获取更多信息,参看”配置"这一章的第3节:路由配置。
Cake缺省的路由会把一个正访问站点的根目录(例如,http://www.example.com)的人带到PagesController那里,并render一个称为home的view。如果不那样,我们想让blog的用户转到快速创建的PostsController。
Cake的路由可在/app/config/routes.php找到。你想取消注释或者删掉这行,像下面这样:
$Route->connect ('/', array('controller'=>'pages',
'action'=>'display', 'home')); |
本行将URL /与缺省的Cake主页面连接起来。我们想让它与我们自己的Controller链接,因此我们增加一行,如下:
$Route->connect ('/', array('controller'=>'posts',
'action'=>'index')); |
它应该将正在访问'/'的用户连接到我们立即创建的PostsController的index()动作。
第14节
总结
按这种方式创建应用程序会赢得和平,荣誉,女人,以及金钱,甚至超越你的无限幻想。简单,是不是?请记住,本指导是最基础的。Cake还提供了更多的特性,我们不想在这里涉及的方式,它们太灵活了。使用本手册的其余本分作为一个指导,来创建更加具有丰富特性的应用程序。
既然你已经创建了一个基本的Cake应用程序,你已经准备好做一些真实的事情了。开始创建你自己的工程吧,并阅读其余的手册和API。
如果你需要帮助,来CakePHP看看我们吧。欢迎Cake!