CakePHP中文手册【翻译】-Cake Blog创建指南

Cake Blog创建指南

1

介绍

欢迎来到Cake。你可能正在使用本指南,因为你想学习更多关于Cake是如何工作的知识。其目的就是为了提高效率,并且让编写代码变得更加有趣。我们希望当你深入代码时能够体会到这些。

本指南将一步步向你介绍如何创建一个简单blog应用程序。我们会获取并安装Cake,创建和配置数据库,而且构建充分的应用程序逻辑来列出,增加,编辑以及删除blogpost

下面是你需要的东西:

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,这样我们在稍后就有基础来完成查看,增加,编辑,以及删除操作。

CakeModel类文件在/app/models中,而且我们将创建的文件将保存为/app/models/post.php.完成的文件应该如下:

/app/models/post.php

<?php

 

class Post extends AppModel

{

    var $name = 'Post';

}

 

?>

因为类和文件的命名方式,它会告诉Cake你想让一个Post ModelPostsController中可用,此PostsController与缺省的数据库中的’posts’表紧紧相联系。

一直使用$name变量是一个不错的主意,可以使用它来避免PHP4中的某些类名的差异。

为获取更多关于model的信息,如表前缀,回调,验证,参考“Model”这一章。

7

创建一个Posts Controller

接下来,为我们的post创建一个controllerController是所有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时,我们想让他们查看一列Postindex动作看起来应该如下:

/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 modelfindAll()方法的值。Post model$this->Post中自动可用,因为我们已经遵循了Cake的命名规则。

为了学习更多关于Cake Controller的信息,参看'Controller’这章。

8

创建Post View

既然我们已经使用model将数据库连接起来,而且controller已经定义了应用程序逻辑和流程,那就让我们为上面定义的index动作创建一个view吧。

Cake view只不过是应用程序布局里的HTMLPHP元素片段。可以定义布局,并且在他们之间选择他们。但是,现在还是让我们使用默认的吧。

还记得在上一节我们是如何使用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] =>

                )

         )

)

Cakeview文件存储在一个/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'会做一些事情,例如链接,表单输出,JavaScriptAjax等。你可以在‘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吧。

首先,从PostsControlleradd()动作开始吧:

/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 HtmlHelperHtmlHelper对所有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');

}

本逻辑会删除$idpost,并在转向到/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专业人士了,因此你应该已经捡起一个模式了。先实现动作,然后是viewPost 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'字段存在并且已经存在了当前的modelCake会假定你正在编辑一个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

路由

本部分可选,但是有助于你理解CakeURL如何映射到指定的函数调用。在本指导里,我们仅打算对路由做出一个快速的变化。要获取更多信息,参看”配置"这一章的第3节:路由配置

Cake缺省的路由会把一个正访问站点的根目录(例如,http://www.example.com)的人带到PagesController那里,并render一个称为homeview。如果不那样,我们想让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'));

它应该将正在访问'/'的用户连接到我们立即创建的PostsControllerindex()动作。

14

总结

按这种方式创建应用程序会赢得和平,荣誉,女人,以及金钱,甚至超越你的无限幻想。简单,是不是?请记住,本指导是最基础的。Cake还提供了更多的特性,我们不想在这里涉及的方式,它们太灵活了。使用本手册的其余本分作为一个指导,来创建更加具有丰富特性的应用程序。

既然你已经创建了一个基本的Cake应用程序,你已经准备好做一些真实的事情了。开始创建你自己的工程吧,并阅读其余的手册和API

如果你需要帮助,来CakePHP看看我们吧。欢迎Cake!

Last Updated:2006年12月5日
posted @ 2006-11-30 09:55  张太国  阅读(...)  评论(...编辑  收藏