[转]Cake 指南:建立一个简单的Blog

news/2024/12/14 18:03:13

 
注意!本指南针对cake_0.9.1_dev 发布版不是SVN的版本。请不要把指南的代码改成于SVN一样。

Cake 指南:建立一个简单的Blog

这是一个还在不断变化的一个应用框架的指南。文章中的东西可能可以运行,但是如果有些东西无法运行,请您先仔细阅读 API 文档。错误报告对我们很有价值,所以,请报告任何影响您使用的地方。

注意:命名方法的约定已经从下划线_风格变成了骆驼回归法则。所以,在我们目前的发布版中link_to()已经变成linkTo()

默认Cake目录结构一览

在本篇指南中,我们将一起使用Cake来创建一个简单的Blog应用。我假设你对PHP十分了解,可以在你的系统中游刃有余(包括从命令行中运行程序),同时已经有一个配置好的开发服务器环境,例如运行PHP的 XAMPP。

下载

下载最新的Cake 包并解压缩到你的Web服务器的DOCUMENT_ROOT下(因为本文是指南的缘故,我假设他可以从http://localhost/cake/ 下访问)。你可以看到基本的目录结构。

创建数据库

创建一个用来存放Blog帖子的表格,并且初始化一些数据。以下是SQL语句:

CREATE TABLE posts (    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,    title VARCHAR(50),    body TEXT,    created DATETIME DEFAULT NULL,    updated DATETIME DEFAULT NULL);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使用的所有表格的默认形式。还有,idcreatedupdated字段是有特殊含义的,等一会儿你就会发现。也就是说现在你不应该更改他们的名字

配置Cake的数据库设置

若要配置数据库访问,我们编辑 config/database.php.default (他应该是自己包含说明的), 并将它保存为config/database.php. 如果config/database.php 不存在,Cake仍会运行,并且不使用数据库访问。

创建一个模型类 (MVC中的Model)

现在给帖子表格posts创建一个模型类,新建 app/models/post.php包含以下内容 :

app/models/post.php


    class Post extends AppModel{}?>

这已经足以使Cake来关注这个模型了,载入、并把它和数据库表格连接在一起。注意:模型类的类名是单数形式。坚持命名约定十分重要,因为如果不这样,Cake就不会自动运行。默认情况下,模型类和数据库表使用同一个单词而前者以单数形式,后者是复数形式。

建立一个控制器助手类

新建一个控制器助手类。把下面的内容放在 app/helpers/posts_helper.php中:

app/helpers/posts_helper.php


    class PostsHelper extends AppController {}?>

创建一个控制器类 (Controller)

新建一个控制器类. 把下面的内容放在 app/controllers/posts_controller.php中:

app/controllers/posts_controller.php


    class PostsController extends PostsHelper {}?>

控制器已经准备好了,这是我们需要在他里面添上行为(Action)来对存储的数据进行操作。添加一个方法到 PostsController 类中 :

app/controllers/posts_controller.php


    class PostsController extends PostsHelper{        function index()        {        }}?>

PostsController::index() 不需要其他内容了,除了需要一个模版(在Cake中称之为视图“View”)。

建立一个视图 (View)

把下面的代码放入 app/views/posts/index.thtml:

Blog posts

foreach ($this->models['post']->findAll() as $post): ?> endforeach; ?>
IdTitleCreated
echo $post['id']?> echo $html->linkTo($post['title'], "/posts/view/{$post['id']}")?> echo $post['created']?>

这应该可以正确运行,我们来测试一下。我假设你可以通过浏览http://localhost/cake/ 来得到Cake目录,这样测试一下我们的新控制器,它指向http://localhost/cake/posts/index 。你会(希望如此)看到类似于下面的一些东西:

Blog postsID  	Title  	                Created1 	The title 	        2005-07-03 10:52:212 	A title once again 	2005-07-03 10:52:343 	Title strikes back 	2005-07-03 10:52:43

为什么我没看到呢?

如果你遇到了一个页面,上面说“not Found: The requested URL /posts/index was not found on this server,”你可能要使用 http://localhost/cake/index.php?url=posts 来访问 . 很明显,这很不美观。如果你遇到了一个页面上说“Fatal error: Call to a member function on a non-object ...”那么你可能要检查一下你的配置内容,有没有把config/database.php.default 改名为config/database.php. 参见 Blog指南中的故障及解决方法。

我们现在做了些什么?

让我们回顾一下。我们创建了数据库表posts,一个模型类Post,一个控制器PostsController 和他的index()方法,还有一个视图文件app/views/posts/index.thtml。我觉得他一点也不困难。让我们继续吧。

帖子标题是连接到/cake/posts/view/[post_id]的. 让我们点击它。

Missing actionYou are seeing this error because the action is not defined in controller PostsNotice: this error is being rendered by the app/views/errors/missing_action.thtml view file,a user-customizable error page for handling invalid action dispatches.Error: Unable to execute action on Posts

噢~,对了,我们忘记添加PostsController::view()行为了。让我们现在完成它:

app/controllers/posts_controller.php


    class PostsController extends PostsHelper{        function index()        {        }        function view($id)        {                $this->models['post']->setId($id);                $this->set('data', $this->models['post']->read());        }}?>

还有视图文件:

app/views/posts/view.thtml

echo $data['title']?>

Created: echo $data['created']?>

echo $data['body']?>

回到浏览器,刷新,看到:

The titleCreated: 2005-07-04 03:31:47This is the post body.

成功了!

添加功能

在指南的第一部分之后,我们有了一个帖子的列表,同时我们可以查看帖子了。当我们完成了第二部分,我们可以:

  • 添加一个新的帖子。
  • 删除不要的帖子。
  • 编辑存在的帖子。

添加一个新的帖子

添加一个新的帖子:

app/controllers/posts_controller.php


    class PostsController extends PostsHelper{        function index()        {        }        function view($id)        {                $this->models['post']->setId($id);                $this->set('data', $this->models['post']->read());        }        function add()        {                if (empty($this->params['data']))                {                        $this->render();                }                else                {                        if ($this->models['post']->save($this->params['data']))                        {                                $this->flash('Your post has been saved.','/posts');                        }                        else                        {                                $this->set('data', $this->params['data']);                                $this->validateErrors($this->models['post']);                                $this->render();                        }                }        }}?>

同时行为的模版文件是:

app/views/posts/add.thtml

Add post to blog

echo $html->formTag('/posts/add')?>

Title: echo $html->inputTag('post/title', 40)?> echo $html->tagErrorMsg('post/title', 'Title is required.') ?>

Body: echo $html->areaTag('body') ?> echo $html->tagErrorMsg('post/body', 'Body is required.') ?>

echo $html->submitTag('Save') ?>

现在你可以通过地址"/cake/posts/add"来访问 add 页面page at the address "/cake/posts/add", 或者,我们可以在索引页面的底部放上一个快捷的“Add new post”连接:

app/views/posts/index.thtml

Blog posts

foreach ($this->post->findAll() as $post): ?> endforeach; ?>
IdTitleCreated
echo $post['id']?> echo $html->linkTo($post['title'], "/posts/view/{$post['id']}")?> echo $post['created']?>
echo $html->linkTo('Add new post', '/posts/add') ?>

现在让我们试试添加一些帖子。

像我这样没规矩的,添加了一个没有标题的帖子。当然,我们可以通过数据有效性检验(Data Validation)来避免这种不正确的行为。

数据有效性

数据有效性规则是放在数据模型中的。

app/models/post.php


    class Post extends AppModel{        var $validate = array(                'title'=>VALID_NOT_EMPTY,                'body'=>VALID_NOT_EMPTY);}?>

了解API文档中更多关于有效检验器的内容。

删除一个帖子

app/controllers/posts_controller.php


    class PostsController extends PostsHelper{        function index()        {        }        function view($id)        {                $this->models['post']->setId($id);                $this->set('data', $this->models['post']->read());        }        function add()        {                if (empty($this->params['data']))                {                        $this->render();                }                else                {                        if ($this->models['post']->save($this->params['data']))                        {                                $this->flash('Your post has been saved.','/posts');                        }                        else                        {                                $this->set('data', $this->params['data']);                                $this->validateErrors($this->models['post']);                                $this->render();                        }                }        }        function delete($id)        {                if ($this->models['post']->del($id))                {                        $this->flash('The post with id: '.$id.' has been deleted.', '/posts');                }        }}?>

delete 行为没有模版。在成功删除之后,我们只要显示一个快捷消息(所谓的“flash”),然后转回索引页面。

现在我们添加一个删除行为的连接到每一个blog帖子的视图中:

app/views/posts/index.thtml

Blog posts

foreach ($this->post->findAll() as $post): ?> endforeach; ?>
IdTitleCreated
echo $post['id']?> echo $html->linkTo($post['title'], "/posts/view/{$post['id']}")?> echo $html->linkTo('Delete',"/posts/delete/{$post['id']}", null, "Are you sure you want to delete post entitled /'{$post['title']}/'?")?> echo $post['created']?>
echo $html->linkTo('Add new post', '/posts/add') ?>

在完成它之后,我们就可以删除那些空白标题的帖子了。

编辑帖子

app/controllers/posts_controller.php


    class PostsController extends PostsHelper{        function index()        {        }        function view($id)        {                $this->models['post']->setId($id);                $this->set('data', $this->models['post']->read());        }        function add()        {                if (empty($this->params['data']))                {                        $this->render();                }                else                {                        if ($this->models['post']->save($this->params['data']))                        {                                $this->flash('Your post has been saved.','/posts');                        }                        else                        {                                $this->set('data', $this->params['data']);                                $this->validateErrors($this->models['post']);                                $this->render();                        }                }        }        function delete($id)        {                if ($this->models['post']->del($id))                {                        $this->flash('The post with id: '.$id.' has been deleted.', '/posts');                }        }        function edit($id=null)        {                if (empty($this->params['data']))                {                        $this->models['post']->setId($id);                        $this->params['data']= $this->models['post']->read();                        $this->render();                }                else                {                        $this->models['post']->set($this->params['data']);                        if ( $this->models['post']->save())                        {                                $this->flash('Your post has been updated.','/posts');                        }                        else                        {                                $this->set('data', $this->params['data']);                                $this->validateErrors($this->models['post']);                                $this->render();                        }                }        }}?>

app/views/posts/edit.thtml

Edit post to blog

echo $html->formTag('/posts/edit')?> type="hidden" name="data[id]" value=" echo $html->tagValue('id')?>"/>

Title: echo $html->inputTag('post/title', 40)?> echo $html->tagErrorMsg('post/title', 'Title is required.') ?>

echo $html->areaTag('body') ?> echo $html->tagErrorMsg('post/body', 'Body is required.') ?>

echo $html->submitTag('Save') ?>

你也可以在表单标签中用

  hiddenTag('id')?>

来代替直接使用html的标签。

同时, 在 index.thtml 中, 我们添加一个编辑连接:

Blog posts

foreach ($this->post->findAll() as $post): ?> endforeach; ?>
IdTitleCreated
echo $post['id']?> echo $html->linkTo($post['title'], "/posts/view/{$post['id']}")?> echo $html->linkTo('Delete',"/posts/delete/{$post['id']}", null, "Are you sure you want to delete post entitled /'{$post['title']}/'?")?> echo $html->linkTo('Edit',"/posts/edit/{$post['id']}")?> echo $post['created']?>
echo $html->linkTo('Add new post', '/posts/add') ?>

从视图中分离逻辑

让我们回头看一下 index.thtml 视图:

app/views/posts/index.thtml

...
     foreach ($this->post->findAll() as $post): ?>...

我们应该从视图中删除 findAll() 的调用,然后把它放在控制器重。这可以建立一种更好的逻辑和视图的分离。然后我们从控制器重为视图获取数据。现在就让我们完成它吧。

在帖子的控制器中,我们从posts模型中获取所有的记录,并且储存在变量 data 中。

app/controllers/posts_controller.php


    ...function index (){        $this->set('data', $this->models['post']->findAll());}...?>

同时在视图中,我们通过对每行数据的迭代,来全部显示他的内容。

app/views/posts/index.thtml

...
     foreach ($data as $post): ?>...

这太简单了,不是么?


ShiningRay @ Nirvna Studio


文章来源: http://shiningray.cnblogs.com/archive/2005/08/05/207807.html




http://www.niftyadmin.cn/n/3652270.html

相关文章

springboot整合websocket遇到的小问题

今天尝试了通过springboot整合websocket来初步学习使用websocket,然后发现启动的时候报错了,发这篇文章分享一下。 springboot整合websocket的步骤很简单: 第一步:创建一个springboot项目,在这里命名为websocket 在I…

Squid私房菜————Squid 代理服务器|ACL访问控制|Squid 日志分析|Squid 反向代理|详细图解

Squid 代理服务器1.ACL访问控制1.1 访问控制列表格式1.2 测试部署2.Squid 日志分析2.1 安装图像处理软件包2.2 添加不计入站点文件,添加的域名将不被显示在排序中2.3 运行2.4 验证2.5 添加计划任务,执行每天生成报告3.Squid 反向代理3.1 修改客户端的域名…

NoSQL私房菜————关系数据库|非关系型数据库|Redis概述|Redis 高可用|

NoSQL之Redis1.关系数据库与非关系型数据库概述1.1 关系型数据库1.2 非关系型数据库1.3 关系数据库与非关系型数据库区别(1)数据存储方式不同(2)扩展方式不同(3)对事务性的支持不同1.4 非关系型数据库产生背…

[同事文章] 软件项目版本号的命名格式

软件项目版本号的命名格式作者: lzlhero为了维护软件项目, 我们提出了对版本进行管理控制的要求. 而对于用户来说, 版本直接体现在版本号的命名上. 那么, 如何对版本号进行命名呢? 我查了许多的资料, 希望能解释得比较具体, 同时也希望您在阅读本文的时候, 能够对版本号的命名…

[转]一生成柱状图、横柱图、折线图的类

//在网上搜索到次类,使用之后,却是觉得强大,稍微修饰代码后贴上,供日后参考。/** * 文件:cal_image.class.php * 功能:产生柱状、折线图、横柱图类 * 作者:yemaosheng.com */Class ImageReport{…

Redis私房菜————|Redis持久化|Redis持久化|RDB持久化|AOF持久化

Redis1.Redis 高可用2.Redis 持久化2.1 RDB 持久化(1)触发条件手动触发自动触发其他自动触发机制(2)执行流程(3)启动时加载2.2 AOF 持久化(1) 开启AOF(2)执行…

[转]Siege:压力模拟/测试工具

Siege:压力模拟/测试工具作者:车东Siege(英文意思是围攻)是一个压力测试和评测工具,设计用于WEB开发这评估应用在压力下的承受能力:可以根据配置对一个WEB站点进行多用户的并发访问,记录每个用户…

Redis私房菜————|Redis性能管理|String数据|List数据类型|散列类型

Redis1.Redis 性能管理1.1 查看Redis内存使用1.2 内存碎片率1.3 内存使用率1.4内回收key2.String数据类型2.1 set / get / append / strlen2.2 incr / decr / incrby / decrby2.3 getset2.4 setex2.5 setnx2.6 mset / mget / msetnx3.List数据类型3.1 lpush / lpushx / lrange3…