ZendChina | Zend中文权威资讯's Archiver

ZendChina 发表于 2008-1-10 14:49

和Zend Framework 一起成长(四)

上接:[url=http://bbs.zendchina.net/thread-119-1-1.html][color=#0000ff]和Zend Framework 一起成长(三)[/color][/url]

[b]列表Albums[/b]
       我们设置了配置和数据库信息,程序应该可以列出一些album。 这些在IndexController 类里完成。
       很清楚,在IndexController 里,每个action 将用Album 类来处理album 数据库。当控制器实例化的时候来加载album 类是很有意义的。这个在init()函数里完成:

zf-tutorial/application/controllers /IndexController.php
[php]...
function init()
{
$this->initView();
$this->view->baseUrl = $this->_request->getBaseUrl();
Zend_Loader::loadClass('Album');
}
...[/php]
注:这是一个用Zend_Loader::loadClass()来加载我们自己的类并且能够工作的例子,因为我们已经在index.php 中把模型路径放到include path 里。
我们打算在indexAction()里的表里列出album:

zf-tutorial/application/controllers/IndexController.php
[php]...
function indexAction()
{
$this->view->title = "My Albums";
$album = new Album();
$this->view->albums = $album->fetchAll();
$this->render();
}
...[/php]
函数Zend_Db_Table::fetchAll()返回一个Zend_Db_Table_Rowset,它允许我们通过返回的记录在视图模板文件里重复使用:

zf-tutorial/application/views/scripts/index/index.phtml
[php]<?php echo $this->render('header.phtml'); ?>
<h1><?php echo $this->escape($this->title); ?></h1>
<p><a href="<?php echo $this->baseUrl; ?>/index/add">Add new album</a></p>
<table>
<tr>
<th>Title</th>
<th>Artist</th>
<th> </th>
</tr>
<?php foreach($this->albums as $album) : ?>
<tr>
<td><?php echo $this->escape($album->title);?></td>
<td><?php echo $this->escape($album->artist);?></td>
<td>
<a href="<?php echo $this->baseUrl; ?>/index/edit/id/<?php
echo $album->id;?>">Edit</a>
<a href="<?php echo $this->baseUrl; ?>/index/delete/id/<?php
echo $album->id;?>">Delete</a>
</td>
</tr>
<?php endforeach; ?>
</table>
<?php echo $this->render('footer.phtml'); ?>[/php]

[url=http://localhost/zf-tutorial/]http://localhost/zf-tutorial/[/url] (或任何你使用的地址)应该可以列出一个很好的(两行)album 列
表。

[b]添加新的 Albums[/b]
我们现在就可以做添加新的album 的函数。有两点:
[list][*]显示一个表单让用户提供信息[*]处理这个表单的提交并把数据保存到数据库里[/list]
这个在 addAction()里完成:
zf-tutorial/application/controllers/IndexController.php
[php]...
function addAction()
{
$this->view->title = "Add New Album";
if (strtolower($_SERVER['REQUEST_METHOD']) == 'post') {
Zend_Loader::loadClass('Zend_Filter_StripTags');
$filter = new Zend_Filter_StripTags();
$artist = $filter->filter($this->_request->getPost('artist'));
$artist = trim($artist);
$title = trim($filter->filter($this->_request->getPost('title')));
if ($artist != '' && $title != '') {
$data = array(
'artist' => $artist,
'title' => $title,
);
$album = new Album();
$album->insert($data);
$this->_redirect('/');
return;
}
}
// set up an "empty" album
$this->view->album = new stdClass();
$this->view->album->id = null;
$this->view->album->artist = '';
$this->view->album->title = '';
// additional view fields required by form
$this->view->action = 'add';
$this->view->buttonText = 'Add';
$this->render();
}
...[/php]

       注意我们如何检查变量$_SERVER['REQUEST_METHOD']来看表单是否被提交。如果表单被提交,我们就从用Zend_Filter_StripTags 类产生的post 数组里提取artist 和title,以确保里面没有html 代码。接着,假定它们已经被填入,我们用模型类,album(),把信息插入到数据库的表里。

       在添加了一个album 之后,我们用控制器的_redirect()方法重定向来返回到程序的根(root)。终于,我们建立了我们将在模板里使用的视图表单。进一步看,我们能预计到编辑action 的表单和这个非常类似,所以我们将使用共同的模板文件(_form.phtml),模板文件将被add.phtml 和edit.phtml 调用。
用于添加album 的模板如下:

zf-tutorial/application/views/scripts/index/add.phtml
[php]<?php echo $this->render('header.phtml'); ?>
<h1><?php echo $this->escape($this->title); ?></h1>
<?php echo $this->render('index/_form.phtml'); ?>
<?php echo $this->render('footer.phtml'); ?>
zf-tutorial/application/views/scripts/index/_form.phtml
<form action="<?php echo $this->baseUrl ?>/index/<?php
echo $this->action; ?>" method="post">
<div>
<label for="artist">Artist</label>
<input type="text" name="artist"
value="<?php echo $this->escape(trim($this->album->artist));?>"/>
</div>
<div>
<label for="title">Title</label>
<input type="text" name="title"
value="<?php echo $this->escape($this->album->title);?>"/>
</div>
<div id="formbutton">
<input type="hidden" name="id" value="<?php echo $this->album->id; ?>" />
<input type="submit" name="add"
value="<?php echo $this->escape($this->buttonText); ?>" />
</div>
</form>[/php]
这是相当简单的代码。我们打算在编辑action 里也用_form.phtml,用$this->action 比hard coding 要好些。相似地,我们在提交按钮里显示的文字也使用变量。

[b]编辑一个 Album[/b]
编辑一个album 几乎和添加一个album 相同, 所以代码非常类似:
zf-tutorial/application/controllers/IndexController.php
[php]...
function editAction()
{
$this->view->title = "Edit Album";
$album = new Album();
if (strtolower($_SERVER['REQUEST_METHOD']) == 'post') {
Zend_Loader::loadClass('Zend_Filter_StripTags');
$filter = new Zend_Filter_StripTags();
$id = (int)$this->_request->getPost('id');
$artist = $filter->filter($this->_request->getPost('artist'));
$artist = trim($artist);
$title = trim($filter->filter($this->_request->getPost('title')));
Page 16 of 18
if ($id !== false) {
if ($artist != '' && $title != '') {
$data = array(
'artist' => $artist,
'title' => $title,
);
$where = 'id = ' . $id;
$album->update($data, $where);
$this->_redirect('/');
return;
} else {
$this->view->album = $album->fetchRow('id='.$id);
}
}
} else {
// album id should be $params['id']
$id = (int)$this->_request->getParam('id', 0);
if ($id > 0) {
$this->view->album = $album->fetchRow('id='.$id);
}
}
// additional view fields required by form
$this->view->action = 'edit';
$this->view->buttonText = 'Update';
$this->render();
}
...[/php]
注意程序不在 “post” 模式, 我们使用getParam()从请求的params 属性中读取id 参数。
模板如下:

zf-tutorial/application/views/scripts/index/edit.phtml
[php]<?php echo $this->render('header.phtml'); ?>
<h1><?php echo $this->escape($this->title); ?></h1>
<?php echo $this->render('index/_form.phtml'); ?>
<?php echo $this->render('footer.phtml'); ?>[/php]

[b]改进![/b]
       你可能已经注意到AddAction() 和 EditAction() 非常类似并且添加和编辑使用同一个模板,看来需要改进一下。这个就留给你,亲爱的读者… …

[b]删除一个 Album[/b]
       为了使我们的程序完整,需要一个删除的功能。在列表页里,每个album 旁边有个删除链接,这是个非常朴素的办法让你去点击删除。这可能错了。记得我们的HTTP spec,不能使用不可以撤回动作的GET,作为代替,要使用POST。Google 的最近的加速器beta 把这点带给许多人。

       我们要用一个确认表单,当用户点”yes”,我们将做删除动作。
这段代码看起来还是和添加、编辑的action 有点象:

zf-tutorial/application/controllers/IndexController.php
[php]...
function deleteAction()
{
$this->view->title = "Delete Album";
$album = new Album();
if (strtolower($_SERVER['REQUEST_METHOD']) == 'post') {
Zend_Loader::loadClass('Zend_Filter_Alpha');
$filter = new Zend_Filter_Alpha();
$id = (int)$this->_request->getPost('id');
$del = $filter->filter($this->_request->getPost('del'));
if ($del == 'Yes' && $id > 0) {
$where = 'id = ' . $id;
$rows_affected = $album->delete($where);
}
} else {
$id = (int)$this->_request->getParam('id');
if ($id > 0) {
// only render if we have an id and can find the album.
$this->view->album = $album->fetchRow('id='.$id);
if ($this->view->album->id > 0) {
$this->render();
return;
}
}
}
// redirect back to the album list unless we have rendered the view
$this->_redirect('/');
}
...[/php]
再一次,我们使用同样的计策去检查请求方法来决定我们要显示确认表单还是应该删除。通过Album()类,就像插入和更新,实际的删除动作通过调用Zend_Db_Table::delete()来完成。

       注意,我们在设置响应body 后立即返回。这就是为什么我们在函数的最后能重定向到album列表。这样,任何不同的健全的检查失败,我们就返回到album 列表而不需要在这个函数里调用_redirect()多次。
模板是一个简单的表单:

zf-tutorial/application/views/indexDelete.tpl.php
[php]<?php echo $this->render('header.phtml'); ?>
<h1><?php echo $this->escape($this->title); ?></h1>
<?php if ($this->album) :?>
<form action="<?php echo $this->baseUrl ?>/index/delete" method="post">
<p>Are you sure that you want to delete
'<?php echo $this->escape($this->album->title); ?>' by
'<?php echo $this->escape($this->album->artist); ?>'?
</p>
<div>
<input type="hidden" name="id" value="<?php echo $this->album->id; ?>" />
<input type="submit" name="del" value="Yes" />
<input type="submit" name="del" value="No" />
</div>
</form>
<?php else: ?>
<p>Cannot find album.</p>
<?php endif;?>
<?php echo $this->render('footer.phtml'); ?>[/php]

[b]故障排除[/b]
       如果除了index/index 能工作外,你发现其他控制模块不能如你所愿,最有可能的问题是路由不能确定你的网站在那个子目录下。就目前来看,通常发生的情况是你网站的url 不同于web-root 的目录。
如果这个缺省代码不适用,你应该自行设置适合你的服务器的$baseURL 的值:

zf-tutorial/index.php
[php]...
// setup controller
$frontController = Zend_Controller_Front::getInstance();
$frontController->throwExceptions(true);
$frontController->setBaseUrl('/mysubdir/zf-tutorial');
$frontController->setControllerDirectory('./application/controllers');
...[/php]

       你应当用正确的URL 指向index.php 的路径来替换'/mysubdir/zf-tutorial/'。例如:如果你的指向index.php 的URL 是[url=http://localhost/~ralle/zf_tutorial/index.php]http://localhost/~ralle/zf_tutorial/index.php[/url],正确的$baseUrl 的值就是'/~ralle/zf_tutorial/'。

[b]结论[/b]
       本教程使用Zend Framwork 开发了一个简单但功能齐全的MVC 应用例程,我希望你能感兴趣和觉得有用。如果你发现任何错误,请给我发邮件到 [email=rob@akrabat.com]rob@akrabat.com[/email]!
       本教程只涉及到Zend Framework 的最节本的用法,你应该去看看手册([url=http://framework.zend.com/manual]http://framework.zend.com/manual[/url])那里有更多的类可以使用,还有wiki([url=http://framework.zend.com/wiki]http://framework.zend.com/wiki[/url]) 中更多的内幕 !如果你对开发Zend Framwork 感兴趣,到开发wiki([url=http://framework.zend.com/developer]http://framework.zend.com/developer[/url]) 中去看看… …

页: [1]

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.