《PHP实例:Symfony2学习笔记之控制器用法详解》要点:
本文介绍了PHP实例:Symfony2学习笔记之控制器用法详解,希望对您有用。如果有疑问,可以联系我们。
本文实例讲述了Symfony2控制器用法.分享给大家供大家参考,具体如下:PHP实例
一个controller是你创建的一个PHP函数,它接收HTTP哀求(request)并创建和返回一个HTTP回复(Response).回复对象(Response)可以是一个HTML页面,一个XML文档,一个序列化的JSON数组,一个图片,一个重定向,一个404错误或者任何你想要的内容.controller中可以包含任何渲染你页面内容的所需要的逻辑.PHP实例
下面是一个controller最简单的例子,仅仅打印一个Hello world!PHP实例
use Symfony\Component\HttpFoundation\Response; public function helloAction() { return new Response('Hello world!'); }
Controller的终极目标都是相同的那就是创建并返回一个Response对象.依照这个思路,你可以从request对象读取信息,加载数据库资源,发送email,或者在用户的Session中写入信息.但是所有情况下,Controller将最终都会返回一个Response对象并被分发会客户端.PHP实例
比如如下情况:PHP实例
Controller A 准备一个Response对象来表现网站homepage内容.
Controller B 从Request中读取slug参数从数据库中加载一个blog内容并创建一个Response对象来显示这个blog.如果slug在数据库中不存在,它将创建并返回一个带有404状态码的Response对象.PHP实例
Controller C 处理一个从联系表单,它从Request对象中读取表单信息,保存联系信息到数据库并发邮件给管理员.最后,它创建一个Response对象重定向客户端浏览器到联系表单感谢页面.PHP实例
Requests,Controller, Response的生命周期PHP实例
Symfony2项目中处理的每一个Request都是经过了相同的简单生命周期.框架负责重复的任务,最终执行一个controller,该controller会包含你的应用程序代码:PHP实例
1.每个Request都会被一个统一的前端控制器文件(比如,app.php,或者app_dev.php)处理,它会启动应用程序.
2.Router从Request中读取URI信息,并找到匹配它的Route,从该Route中读取_controller参数.
3.匹配成功的route的controller被执行,controller中的代码创建并返回一个Response对象.
4.HTTP头和生成的Response对象内容将会被发回客户端.PHP实例
创建一个页面跟创建一个controller一样容易,创建一个路由来映射一个URL到该controller.PHP实例
注意:尽管从名字上来看,前端控制器和controller差不多,其实它们是不同的.
一个前端控制器是一个存放于web目录下的PHP文件,多有的Request都会通过它被重定向.每一个应用程序都会有一个产品前端控制器app.php和一个开发用的前端控制器app_dev.php.你不需要编辑,查看或者担心它们.PHP实例
看一个简单的Controller: 任何的PHP可调用内容(比如函数,对象办法或者一个Closure)都可以成为一个controller.Symfongy2中,一个controller通常为controller对象中一个单一的办法.Controllers通常也被称为actions.PHP实例
// src/Acme/HelloBundle/Controller/HelloController.php namespace Acme\HelloBundle\Controller; use Symfony\Component\HttpFoundation\Response; class HelloController { public function indexAction($name) { return new Response('<html><body>Hello '.$name.'!</body></html>'); } }
注意在这个例子中controller是indexAction办法,它存在于controller类(HelloController)中.不要混淆,之所以定义一个controller类(HelloController)只是为了方便组织多个controllers/actions在一起.一般情况下,一个controller类会有多个controllers/actions.PHP实例
上面例子中的controller相当简单:PHP实例
Namespace行是symfony2使用了PHP5.3的命名空间功能来为整个controller类指定命名空间.
use关键字导入了Response类,这是我们的controller必须返回的内容.PHP实例
Controller类名字都是由其名字后面加Controller来定义,但是只有前面的部分才是其真正名字,为了统一起见,在后面统一添加Controller. 在路由配置时只会取前面部分.PHP实例
Controller类中每个被用于真正controller的办法都会被添加一个统一的后缀Action,同样我们在配置其路由时也只会取前面部分而忽略掉Action.把它映射到某个URL.PHP实例
每个controller办法的最后必然会创建一个Response对象并返回它.PHP实例
映射一个URL到一个Controller办法:PHP实例
上面例子中的controller方法返回一个简单的HTML页面.如果要在浏览器中拜访到该页面,那么你需要为它创建一个route,把它映射到一个特定模式的URL上.PHP实例
# app/config/routing.yml hello: pattern: /hello/{name} defaults: { _controller: AcmeHelloBundle:Hello:index }
XML格式:PHP实例
<!-- app/config/routing.xml --> <route id="hello" pattern="/hello/{name}"> <default key="_controller">AcmeHelloBundle:Hello:index</default> </route>
PHP代码格式:PHP实例
// app/config/routing.php $collection->add('hello', new Route('/hello/{name}', array( '_controller' => 'AcmeHelloBundle:Hello:index', )));
现在想URL /hello/ryan 将被映射到HelloController::indexAction() controller并将ryan传递给$name变量.PHP实例
创建一个所谓的页面,其实就是创建一个controller办法和一个相关的route.PHP实例
注意我们使用的指向controller办法的表示语法:AcmeHelloBundle:Hello:indexPHP实例
Symfony2使用了一个非常灵活的字符串声明来指向不同的controller.它告诉Symfony2在一个名叫AcmeHelloBundle的bundle中去查找一个叫HelloController的类,并执行它的indexAction()办法.在这个例子中,我们的路由配置直接写在了app/config/ 目录下,一个更好的组织方式是把你的路由放到各自的bundle中.PHP实例
路由参数作为Controller办法参变量PHP实例
你已经了_controller参数 AcmeHelloBundle:Hello:index指向一个位于AcmeHelloBundle中名叫HelloController::indexAction()的办法.有趣的是路由中参数都会被传递给该办法.PHP实例
<?php // src/Acme/HelloBundle/Controller/HelloController.php namespace Acme\HelloBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; class HelloController extends Controller { public function indexAction($name) { // ... } }
上例中controller办法有一个唯一参数,$name, 它对应着route中定义的{name}占位符名称.事实上,等你执行你的controller时,Symfony2会匹配controller和route中每一个参数.PHP实例
如果我修改一下Hello的路由定义:PHP实例
YAML格式:PHP实例
# app/config/routing.yml hello: pattern: /hello/{first_name}/{last_name} defaults: { _controller: AcmeHelloBundle:Hello:index, color: green }
XML格式:PHP实例
<!-- app/config/routing.xml --> <route id="hello" pattern="/hello/{first_name}/{last_name}"> <default key="_controller">AcmeHelloBundle:Hello:index</default> <default key="color">green</default> </route>
PHP代码格式:PHP实例
// app/config/routing.php $collection->add('hello', new Route('/hello/{first_name}/{last_name}', array( '_controller' => 'AcmeHelloBundle:Hello:index', 'color' => 'green', )));
这时候controller中可以获取这些参变量了:PHP实例
public function indexAction($first_name, $last_name, $color) { // ... }
注意route定义中无论是占位符变量还是默认值变量都会被转化为controller办法的输入变量.当一个route匹配成功时,它会合并占位符和defaults到一个数组传递给controller.映射route参数到controller参数非常简单和灵活.它们从route到controller不匹配顺序.Symfony能够把route中参变量的名字映射到controller办法签名中的变量名字.比如{last_name} => $last_name,跟排列顺序无关.PHP实例
Controller办法中的参数必须匹配route中定义的参数下面为hello route定义的controller办法将会抛出异常:PHP实例
public function indexAction($last_name, $color, $first_name) { // .. }
如果我们把$foo变量变为可选变量,那么就不会抛异常了.PHP实例
public function indexAction($first_name, $last_name, $color, $foo) { // .. }
并不是每一个在route中定义的参数都需要在controller中有与之对应的签名参变量的,比如hello route中定义的{$last_name} 如果对你没什么意义的话可以在controller中省略掉它.PHP实例
public function indexAction($first_name, $color) { // .. }
反之,如果你在Controller签名中定义了变量,并且不是可选变量,那么必须在route中有与之对应的参数被定义.PHP实例
在route定义中有一个特殊参数 _route, 它匹配route的名称(如上例中的hello).虽然不常用,但是它也可以作为controller办法的一个参变量使用.PHP实例
Request作为一个Controller办法签名变量PHP实例
为了方便,你可能会让symfony传递你的Request对象作为参数到你的controller办法.这在你处理表单时尤为方便.PHP实例
use Symfony\Component\HttpFoundation\Request; public function updateAction(Request $request) { $form = $this->createForm(...); $form->bindRequest($request); // ... }
Controller基类PHP实例
为了方便,Symfony2定义了一个Controller基类,包含了一些常用的controller任务并给了你的controller类拜访任何你需要的资源的途径.通过继承该类,你可以获得许多帮助方法.PHP实例
// src/Acme/HelloBundle/Controller/HelloController.php namespace Acme\HelloBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Response; class HelloController extends Controller { public function indexAction($name) { return new Response('<html><body>Hello '.$name.'!</body></html>'); } }
在Symfony中controller并不一定非得继承Controller基类,因为它内部的帮助方法等都不是必须的.你也可以继承 Symfony\Component\DependencyInjection\ContainerAware 服务容器对象可以通过container属性来拜访.同时你也可以把controller定义成service.PHP实例
通用的Controller任务:PHP实例
尽管Controller可以干任何事情,但是大部分的controller还是要重复的干一些基础的任务.比如 重定向,跳转,渲染模板和拜访核心服务等.PHP实例
重定向(redirecting)PHP实例
如果你想重定向你的用户到另一个页面,可以使用redirect()办法.PHP实例
public function indexAction() { return $this->redirect($this->generateUrl('homepage')); }
这里generateUrl()办法是一个帮助函数,用于根据给定的route生成相应的URL.默认情况下,redirect()办法执行一个302重定向.如果要执行301重定向,那么需要修改第二个参数如下:PHP实例
public function indexAction() { return $this->redirect($this->generateUrl('homepage'), 301); }
redirect()办法其实是一个简化写法,真正的代码如下:PHP实例
use Symfony\Component\HttpFoundation\RedirectResponse; return new RedirectResponse($this->generateUrl('homepage'));
跳转(Forwarding)PHP实例
你可以使用forward()方法很容易从一个controller到另一个controller内部.它执行的是一个内部子哀求,来调用指定的controller,所以不会产生用户客户端浏览器的重定向.forward()方法返回的Response对象还将从原controller返回.PHP实例
public function indexAction($name) { $response = $this->forward('AcmeHelloBundle:Hello:fancy', array( 'name' => $name, 'color' => 'green' )); // further modify the response or return it directly return $response; }
这里forward()办法使用了跟route配置中相同的字符串参数.这里传入数组参数会作为目标调用controller的参数.当将controller嵌入到模板时,也会使用同样的接口.目标调用的controller办法应该是如下定义:PHP实例
public function fancyAction($name, $color) { // ... create and return a Response object }
就像为一个route创建一个controller一样,跟参数的顺序没关系.symfony2 会匹配索引键名称name到办法参数名称$name,即使顺序打乱也没关系.跟其它Controller基类办法一样,forward办法也仅仅是一个symfony2核心函数的快捷写法.一个跳转可以直接通过http_kernel服务来完成,返回一个Response对象.PHP实例
$httpKernel = $this->container->get('http_kernel'); $response = $httpKernel->forward('AcmeHelloBundle:Hello:fancy', array( 'name' => $name, 'color' => 'green', ));
渲染模板:PHP实例
虽然不是必须的,但是大部分controller将最终渲染一个负责生成为controller负责生成HTML的模板.renderView()办法会渲染一个模板并返回它的内容.这个返回内容可以用作创建Response对象,以供controller返回使用.PHP实例
$content = $this->renderView('AcmeHelloBundle:Hello:index.html.twig', array('name' => $name)); return new Response($content);
上面的代码完全可以更进一步的使用下面的代码形式来写:
PHP实例
这两种情况下,AcmeHelloBundle中的模板Resources/views/Hello/index.html.twig都会被渲染.PHP实例
renderview()办法是如下代码的快捷写法:PHP实例
$templating = $this->get('templating'); $content = $templating->render('AcmeHelloBundle:Hello:index.html.twig', array('name' => $name));
当然也可以在子目录中渲染模板PHP实例
$templating->render('AcmeHelloBundle:Hello/Greetings:index.html.twig', array('name' => $name)); // index.html.twig 存放于 Resources/views/Hello/Greetings 目录.
拜访其它服务PHP实例
只要是继承了Controller基类,你就可以通过get()方法拜访symfony2的服务了.比如:PHP实例
$request = $this->getRequest(); $templating = $this->get('templating'); $router = $this->get('router'); $mailer = $this->get('mailer');
Symfony2中还有无数的可用服务,同时也鼓励你定义自己的服务.要查看所有的服务,可以使用container:debug 命令行工具PHP实例
$ php app/console container:debug
管理错误和404页面PHP实例
当一些东西没有找到,你应该重置HTTP协议返回一个404 回复.要做到这个,你将抛出一个特殊类型的异常.如果你是继承了Controller基类,则:PHP实例
public function indexAction() { $product = // retrieve the object from database if (!$product) { throw $this->createNotFoundException('The product does not exist'); } return $this->render(...); }
createNotFoundException()办法创建一个特定的NotFoundHttpException对象,它最终触发404 HTTP回复.当然你从你的controller办法中可以抛出任何类型的Exception 类,Symfony2会自动返回一个500 HTTP回复代码.PHP实例
throw new \Exception('Something went wrong!');
管理SessionPHP实例
Symfony2 提供了一个非常好的Session对象,你可以用它来在哀求之间存贮有关用户的信息.默认情况下,Symfony2 通过PHP本身的Session保存属性到cookie.在任何controller中存储和获取Session信息将非常容易:PHP实例
$session = $this->getRequest()->getSession(); // 为用户的后一个哀求使用存储一个属性 $session->set('foo', 'bar'); // 在另一个controller中为另一个哀求获取该属性 $foo = $session->get('foo'); // 设置用户的本地化语言 $session->setLocale('fr');
Flash 消息PHP实例
你可以为特定的哀求存储少量的消息到用户的Session.这在处理一个表单时非常有用,你想重定向和一个特定的信息显示在下一个哀求中.这种类型的消息被称为Flash消息.比如,假设你处理一个表单提交:PHP实例
public function updateAction() { $form = $this->createForm(...); $form->bindRequest($this->getRequest()); if ($form->isValid()) { // 做些排序处理 $this->get('session')->setFlash('notice', 'Your changes were saved!'); return $this->redirect($this->generateUrl(...)); } return $this->render(...); }
此例中,在处理完哀求后,controller设置了一个notice flash消息并作了重定向.名字notice没什么意义,只是用于标识该消息.在下一个活动的模板中,下面的代码能够渲染这个notic消息:PHP实例
TwigPHP实例
{% if app.session.hasFlash('notice') %} <div class="flash-notice"> {{ app.session.flash('notice') }} </div> {% endif %}
PHP代码:PHP实例
<?php if ($view['session']->hasFlash('notice')): ?> <div class="flash-notice"> <?php echo $view['session']->getFlash('notice') ?> </div> <?php endif; ?>
这样设计,flash消息就能够为准确的某个哀求存在了.他们一般被设计出来就是用于重定向的.PHP实例
Response对象PHP实例
作为一个Controller来说,唯一必须做到的是返回一个Response对象.PHP实例
Response对象是一个PHP代码对HTTP Response的抽象.
HTTP Response是一个基于文本的消息有HTTP headers和 返回给客户端的内容组成.PHP实例
//创建一个简单的Response对象,默认状态码为200 $response = new Response('Hello ' .$name, 200); //创建一个基于JSON的Response对象,状态码也为200 $response = new Response(json_encode(array('name'=>$name))); $response->headers->set('content-type','application/json');
其中headers属性是一个HeaderBag对象,内部包含许多有用的办法来读取和改变Response的头信息.头名字被标准化使用Content-Type 与content-type或者content_type效果等同.PHP实例
哀求对象RequestPHP实例
除了路由占位符的值以外,如果继承了Controller基类那么该controller还可以拜访Request对象.PHP实例
$request = $this->getRequest(); $request->isXmlHttpRequest(); // 判断是不是Ajax哀求 $request->getPreferredLanguage(array('en','fr')); $request->query->get('page'); // 获取$_GET 参数 $request->request->get('page'); //获取$_POST参数
跟Response对象一样,Request对象的头也保存在HeaderBag对象中,可以很方便的被访问.PHP实例
总结思考:PHP实例
无论何时,你创建一个页面,你最终需要为它写一些包含逻辑的代码.在Symfony中,这叫一个controller, 它是一个PHP的函数,它可以为了最后返回一个Response对象给用户可以做需要的任何事情.简单的说,你可以选择继承一个Controller基类,它包含了许多执行controller通用任务的快捷办法.比如,你不想把HTML代码写入你的controller, 你可以使用render()办法来渲染并返回一个模板内容.PHP实例
希望本文所述对大家基于Symfony框架的PHP程序设计有所赞助.PHP实例
《PHP实例:Symfony2学习笔记之控制器用法详解》是否对您有启发,欢迎查看更多与《PHP实例:Symfony2学习笔记之控制器用法详解》相关教程,学精学透。维易PHP学院为您提供精彩教程。
转载请注明本页网址:
http://www.vephp.com/jiaocheng/7334.html