第三章 掌握Controller 第三节 如何编写action
时间:2007-04-11 来源:xiaoshengcaicai
如果我们不想在Root.pm里面写action,那么在编写action之前,我们需要先创建一个Controller,假设它名字为A,那么在script文件夹下面执行:
perl x_create.pl Controller A
这样你就可以在lib/X/Controller/里面看见刚创建好的A.pm了.
我们在A里面写一个最简单的action:
package X::Controller::A; if ($id) {
$c->res->body("your id is $id"); } else { $c->res->body("no id input"); }
} |
如果客户端请求的URL是: a/list/?id=2007, 那么网页内容会是 your id is 2007,
如果客户端请求的URL是: a/list/, 那么网页内容会是 no id input.
下面先介绍$c的一些常用方法:
1. $c->req
该方法是$c->request的一个别名,返回一个Catalyst::Request对象. 当客户端一个请求过来时,Catalyst把该次请求相关的数据封装在$c->reqeust这个对象里面, 然后使用$c->request一些方法可以得到该次请求里面涉及到的参数内容.
它常用的方法有: (更详细的内容请参看CPAN文档)
1. query_parameters
得到该次请求里面的GET参数.
客户请求a/list/?id=2007, $c->request->query_parameters('id')会得到 2007这个值
2. body_parameters, 别名body_params
得到该次请求里面的POST参数.
客户端向a/list/发送一个POST请求, post参数为id=2007&name=xiaosheng, 那么$c->request->body_parameters('id')会得到 2007这个值,$c->request->body_parameters('name')会得到 xiaosheng这个值
3. param
这个方法比以上2个方法更常用, 该方法可以取到请求参数,而不管该参数是GET参数还是POST参数.
客户请求a/list/?id=2007, $c->request->param('id')会得到 2007这个值
客户端向a/list/发送一个POST请求, post参数为id=2007, $c->request->param('id')一样会得到 2007这个值
4. header
得到请求头部的某个值
$c->req->header('User-Agent')可以得到请求头部里面的User-Agent的值.
5. user_agent
其实就是$c->req->header('User-Agent')
6. address
得到该次请求的IP地址
7. arguments
得到传递给某action的参数.
客户端请求a/b/list/xiao/sheng
但是我们没有定义过a/b/list/xiao/sheng这个action,我们只定义过a/b/list这个action,那么catalyst会把这个请求也交给a/b/list这个action来处理,
在action里面
$c->request->arguments == ['xiao', 'sheng']
取arguments你还可以这样取:
package X::Controller::A::B;
} |
$x就是$c->req->arguments->[0],
$y就是$c->req->arguments->[1].
如果你是在action内部forward到另外一个Private的action,那么$c->req->arguments在forward之前会先被保存起来, 调用完再恢复.
package X::Controller::A::B;
#这里, $c->req->arguments = [$x, $y] = ['xiao', 'sheng']
} |
2. $c->res
该方法是$c->response的一个别名,返回一个Catalyst::Response对象.当处理完客户端的一个请求后,Catalyst要给客户端一个响应, 包含响应头部跟内容(header和body). $c->response就是封装整个响应的一个对象.
它常用的方法有: (更详细的内容请参看CPAN文档)
1. header
设置响应头部, 比如
$c->res->header('Content-Type' => 'text/html');
2 content_type
$c->res->content_type('text/html');
其实就是$c->res->header('Content-Type' => 'text/html');
3 body 跟output是一样的
设置响应的内容
$c->res->body('<html><body>hello world</body></html>');
4. redirect
重定向到另外一个URL里面
$c->res->redirect ('http://www.google.com');
这行代码导致客户端浏览器收到这个响应之后马上再发出一个请求到http://www.google.com.
如果是本站点重定向的话, 经常跟$c->uri_for一起使用:
$c->res->redirect ( $c->uri_for('/book/detail/', { id => 3} ) );
假设一开始的请求URL是http://x.com/action1,那么action1这行代码会导致重定向到:
http://x.com/book/detail/?id=3
关于$c->uri_for的详细说明请参看下文或者CPAN文档
3. $c->stash
该方法返回一个hash引用, 生命周期同$c->req, $c->res, 为一个请求周期. 在一个请求周期内可以把它当作一个垃圾堆来放置数据, 主要用于action之间传递数据或者组件之间传递数据, 在以后的例子会经常看到它.
$c->stash->{list} = ['a', 'b']; #往stash里面放置一个key=list,value=['a','b'].
4. $c->log
该方法返回一个Catalyst::Log对象, 你可以调用该对象的方法来往标准错误里面输出一些DEBUG消息或者错误消息.
$c->log->error('test');
$c->log->info('test');
如果你开着catalyst自带的server来调试程序,就会看到屏幕上打印出字符串"test".
$c->log一般用来输出一些变量的值进行调试用.
5. $c->config
该方法返回整个项目配置的一个hashref.一般我们使用Catalyst::Plugin::ConfigLoader这个插件在项目初始化时读取app.yml文件, 读出来后就是一个哈希引用, 也就是$c->config.
$c->config->{home} 一般就是指Catalyst项目的app目录在磁盘上的路径.
6. $c->forward
跳转到另外一个action或者组件里面进行处理.
forward到action里面的代码其实都会被包裹在eval里面, 这个时候就算你写die也不会导致整个应用程序崩溃.
它有几种参数调用方式:
1. $c->forward( $action [, \@arguments ] )
$action参数必须是一个Controller里面的action的名字,可以是绝对路径, 如果不是绝对路径那就是当前controller里面的action:
my $foo = $c->forward('/foo');
$c->forward('index');
2. $c->forward( $class, $method, [, \@arguments ] )
$class是某个组件的名字, 可以是Controller,也可以是View, Model,$method就是该组件内部定义的方法,如果没有$method参数,默认就是调用组件内部的process方法.
7. $c->detach
跟forward类似,只是跳到另外一个action之后就不再返回执行原action下面的代码.
8. $c->path_to
假设项目所在位置为/home/xiaosheng/X/
$c->path_to('bin', 'do.pl')就是字符串 '/home/xiaosheng/X/bin/do.pl'.
9. $c->uri_for
它返回一个URI对象. 参数形式如下:
$c->uri_for( $path, @args?, \%query_values? )
假设客户端请求http://xiaosheng.com/a/list/ , 匹配这个URL的action是X::Controller::A::list
在这个action里面调用
$c->uri_for( 'list2' ); 将返回URI对象: url为http://xiaosheng.com/a/list2
$c->uri_for( '/list2' ); 将返回URI对象: url为http://xiaosheng.com/list2
$c->uri_for( 'list2', 'detail' ); 将返回URI对象: url为http://xiaosheng.com/a/list2/detail
$c->uri_for( 'list2', { id => 2} ); 将返回URI对象: url为http://xiaosheng.com/a/list2?id=2
$c->uri_for( 'list2', 'detail', { id => 2} ); 将返回URI对象: url为http://xiaosheng.com/a/list2/detail?id=2