来源:http://trac.seagullproject.org/wiki/Tutorials/WorkingWithActions
现在你已经学会了输出内容,应该是了解一下动作方法的时候了,亦或者你可以在一个管理类中执行处理多个动作。
我们将以一个GET动作做为一个最简单的例子。你已经会通过请求某个特殊的URI来输出内容,现在我们可以通过单击一个链接来调用一个不同的动作来输出内容。
许多模板默认提供了这些方法而不需要额外输入库,你可以在Output库中找到,它包含了你可以在你的模板中调用的方法。
要创建一个链接你需要零个或多个参数来多个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'),
);
}
上面代码解析如下:
Seagull鼓励开发者认真处理请求变量。这样做的效果是以老的register_globals相反,只有显式声明的变量才可以在程序中使用。虽然你习惯了你这样使用
SELECT foo FROM var where id = $_GET['id']
Seagull还是鼓励你使用一种更安全的方法。
任何一个管理类都需要一个validate方法,毫不意外地,在这里验证输入数据。validate方法带两个参数,请求对象和输入对象,在这里可以测试请求变量并将它赋给$input对象。在框架的稍后处理过程中,$input都是在可见的范围内的。
概念是很简单的,从请求对象收集数据,如果被验证是可靠的,数据将被传递给请求中动作参数指定的方法。如果数据无效,也就是说$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变量是通过参考传递的,所以无须返回值。
要运行例子只需在浏览器中载入管理类并单击hello和goodbye链接,并看输出结果的不同。
http://localhost/seagull/www/index.php/helloworld/
结果应该是这样的 http://seagullfiles.phpkitchen.com/images/goodbyeWorld.png
在本教程中你会尝到如何创建一个基本的管理类,不同的动作方法,URI映射和简单的模板。下期我们将会介绍使用Seagull的相关技术。
你可以从这里下载本教程的代码。