来源:http://trac.seagullproject.org/wiki/Tutorials/WorkingWithActions

2. 使用动作方法

  • requires >= Seagull 0.6.0

介绍

现在你已经学会了输出内容,应该是了解一下动作方法的时候了,亦或者你可以在一个管理类中执行处理多个动作。

GET and POST

我们将以一个GET动作做为一个最简单的例子。你已经会通过请求某个特殊的URI来输出内容,现在我们可以通过单击一个链接来调用一个不同的动作来输出内容。

创建一个链接

许多模板默认提供了这些方法而不需要额外输入库,你可以在Output库中找到,它包含了你可以在你的模板中调用的方法。

  • 创建URIs
  • 格式化日期
  • 创建复选框,单选按钮和其它典型的HTML控件
  • 权限检查
  • 翻译

要创建一个链接你需要零个或多个参数来多个makeUrl()函数。可以简单的调用

{makeUrl()}

它会在当前页面创建一个链接,换句话说,它会检测当前的动作,管理类和模块,并提供在链接中。在你的模块中试一下吧,代码如下:

<a href="{makeUrl()}">say good bye</a>

如果你查看源代码,你应该会看到下面的代码

<a href="http://localhost/seagull/www/index.php/helloworld/">say good bye</a>

makeUrl()的三个可选参数分别是动作名,管理类名,模块名,它的函数原型(也就是函数签名了):

{makeUrl(action,manager,module)}

在我们继续前进之前让我们回顾一下Flexy模板的一些规则,它是Seagull默认使用的模板引擎。然而开发者可以选择他喜欢的模板引擎,目前支持的是引擎是Flexy,Smarty和Savant。常见规则是:

 1. 所有的变量和函数名必须被大括号包含
 2. 在变量参数之间不要使用空格,Flexy不支持

在我们学习过程中我们会接触到更多。现在,让我们在URI中调用一个动作方法,如sagGoodBye。将下列代码放到你的模板中:

<a href="{makeUrl(#sayGoodBye#)}">say good bye</a>

你可能会问#号是干什么用的?换句话说,如果你要传递的参数不是变量而是字符串常量的话你要用#号包含起来,如果你查看源代码,你应该会看到如下代码:

<a href="http://localhost/seagull/www/index.php/helloworld/action/sayGoodBye/">say good bye</a>

创建动作映射

现在我们已经在URI中指定了动作,下一步是在我们的HelloWorldMgr添加一些代码来侦听对动作方法的调用。

首先我们需要在类构造函数中添加动作映射,这样Seagull就知道根据URI请求中的动作参数来调用方法。在上一篇教程创建的类中创建一个构造函数,代码如下:

    function HelloWorldMgr()
    {
        parent::SGL_Manager();
        $this->_aActionsMapping =  array(
            'sayGoodBye'   => array('sayGoodBye'),
        );
    }

上面代码解析如下:

  • 如果你想让你的项目兼容PHP4/5,你可以使用PHP4风格的构造函数,当然使用PHP5的构造函数是不会有什么影响
  • 构造函数不需要任何参数
  • 调用父类的构造函数 - 简单的说这样做是为了在你的管理类中使用某些资源,如数据库连接,配置信息等。

获取请求变量

Seagull鼓励开发者认真处理请求变量。这样做的效果是以老的register_globals相反,只有显式声明的变量才可以在程序中使用。虽然你习惯了你这样使用

SELECT foo FROM var where id = $_GET['id']

Seagull还是鼓励你使用一种更安全的方法。

  • 技巧: 所有的用户输入数据可被认为是不干净的数据直到它被赋给$input对象。

任何一个管理类都需要一个validate方法,毫不意外地,在这里验证输入数据。validate方法带两个参数,请求对象和输入对象,在这里可以测试请求变量并将它赋给$input对象。在框架的稍后处理过程中,$input都是在可见的范围内的。

  • 请求对象是$_REQUEST数据的封装,它提供了净化数据的方法。
  • 输入对象作为数据和资源的注册对象被用在整个请求/响应周期当中
  • 将输入提交给动作方法,在处理完后,将数据赋给输出对象

概念是很简单的,从请求对象收集数据,如果被验证是可靠的,数据将被传递给请求中动作参数指定的方法。如果数据无效,也就是说$validated属性的值是false,应用程序控件类将数据直接传递给display()方法,不发生任何处理。

有了这些基本原理后,下面来看一个简单的validate方法:

    function validate($req, &$input)
    {
        $this->validated = true;
        $input->action   = $req->get('action');
    }

将这个方法添加到构造函数HelloWorldMgr后面。

设置默认动作

validate方法需要进一步加工,我们需要设置默认动作。如果在URI中没有显式设置动作参数,默认动作会被设置给$input→action。请把validate方法改成下面这样:

    function validate($req, &$input)
    {
        $this->validated = true;
        $input->action   = ($req->get('action')) ? $req->get('action') : 'sayGoodBye';
    }

动作方法名称是大小写敏感的,所有要小心一点。如果这让你很头痛,那就使用小写动作名称吧。

请求对象是作为一个参数传递给validate方法,用$req→get()来获得动作变量的值,将它映射到输入对象。控制类将使用这个值来将请求传递给相关动作方法,在我们的例子中是sagGoodBye方法。而且为了简单起见我们还末做任何验证,我们只是把管理类的状态设置成已验证。

创建动作方法

完成了映射和验证后,我们现在应该创建创建动作方法。对于初学者,我们只在方法中显示一个‘foo’字符串。添加下列代码:

    function _cmd_sayGoodBye(&$input, &$output)
    {
        print 'foo';
    }

注意动作方法名称必须带有字符串_cmd_做前缀,这只用来和公有与私有方法区别。动作方法是半私有的,所以如果你指定bar作为动作参数的值,控制类将试图在管理类中寻找一个_cmd_bar方法。

旁注:我们发现将一组动作放在一个管理类中是非常有效的,打开越少的文件,你就会运行的越快。方法也可以包含私有方法,如典型的用来取数据方法,或公有方法,如果同一个模块中的其它管理类可能需要访问它。

如果你保存了上面的代码,刷新你的浏览器你会看到‘foo’显示在页面上,这说明到目前为止一切代码都能正常工作。

使用动作修改数据

既然你已经确信你已经能够通过链接请求一个动作方法,我们一起来完成这个例子,并使用请求方法来使框架一会儿输出hello一会儿输出goodbye world。

要实现这个功能我们需要两个动作方法,现在的_cmd_sayGoodBye()和将要添加的被设置成默认动作的_cmd_sayHello()方法。请对HelloWorldMgr类稍作修改,修改后应该是这样的:

<?php
class HelloWorldMgr extends SGL_Manager
{
    function HelloWorldMgr()
    {
        parent::SGL_Manager();
        $this->_aActionsMapping =  array(
            'sayHello'    => array('sayHello'),
            'sayGoodBye'    => array('sayGoodBye'),
        );
    }

    function validate($req, &$input)
    {
        $this->validated = true;
        $input->action   = ($req->get('action')) ? $req->get('action') : 'sayHello';
    }

    function display(&$output)
    {
        $output->template = 'helloWorld.html';
        $output->testVariable = 'World!';
    }

    function _cmd_sayHello(&$input, &$output)
    {
        $output->word = 'Hello';
    }

    function _cmd_sayGoodBye(&$input, &$output)
    {
        $output->word = 'Goodbye';
    }
}
?>

我们所作的是:

 1. 我们现在有两个动作方法_cmd_sayHello()和_cmd_sayGoodBye()
 2. 每一个方法在构造函数中$this->_aActionsMapping有一个对应的映射
 3. 在validate()中,如果在请求中末检测到动作就设置一个默认动作。
 4. 删除了$output->testVariable变量,添加变量output->word来存储输出的值

按下面对你的模板稍做修改:

{word} {testVariable}
<p><a href="{makeUrl(#sayHello#)}">say hello</a></p>
<p><a href="{makeUrl(#sayGoodBye#)}">say good bye</a></p>

现在我们有了两个链接,两个变量,第一个的值可能是Hello或Goodbye,另一个是我们前面例子中的值。如果你想知道为什么在动作方法中没有返回值,那是因为$input和$output变量是通过参考传递的,所以无须返回值。

  • 技巧:如果你只是使用PHP5,那么你不必指明参数是以参考传递的,默认情况下它会以参考传递的。

要运行例子只需在浏览器中载入管理类并单击hello和goodbye链接,并看输出结果的不同。

http://localhost/seagull/www/index.php/helloworld/

结果应该是这样的 http://seagullfiles.phpkitchen.com/images/goodbyeWorld.png

结论

在本教程中你会尝到如何创建一个基本的管理类,不同的动作方法,URI映射和简单的模板。下期我们将会介绍使用Seagull的相关技术。

下载代码

你可以从这里下载本教程的代码。

 
tutorials/workingwithactions.txt · 上一次变更: 2007/03/23 16:39 通过 xinhaozheng
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki