具体介绍:
Controller:
use Symfony\Component\HttpFoundation\Response;
public function helloAction()
{
return new Response('Hello world!');
}
控制器的目标总是相同的:创建和返回一个response对象。他可能顺便从request中读取信息,装载点数据库资源,发送一个邮件或者设置用户的session信息。但是大部分情况下,控制器最终会返回一个将要被传送到客户端的对象。
Requests, Controller, Response Lifecycle
1..每个请求都被单独的前端控制文件(比如app.php或者app_dev.php文件,可以启动应用程序)控制。
2.Router从请求(uri)中读取信息,从路由中读取控制信息,找到一个和信息匹配的路由。
3.匹配路由的控制器被执行并且控制器的代码创建并且返回一个response对象。
4.Response对象的内容和头都被返回到客户端。
创建页面就是创建一个控制器然后创建和控制器对应的路由。尽管有相同的命名,一个前端控制器,不同于这章讨论的控制器。前端控制器是一个存在于web目录,通过所有的请求都被)的php文件。
A Simple Controller
虽然在Symfony2中控制器可以是任何一个php callable(a function , method on an object, or a closure),一个控制器同窗是在控制器对象里的方法,控制器也被叫做 actions。
// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
3.use Symfony\Component\HttpFoundation\Response;
//第3行用了php5.3 的命名方式,他把我们必须返回的response给引进来了。
class HelloController//类名是为控制类等一系列的名称。这是一个用来向控制器提供会话,并且允许他们映射到从路由中的一部分的名字。
{
public function indexAction($name)//每个action类都是以action为后缀,它通过action的名字来和路由配置中的action相对应。下一章,你将创建一个映射action的路由,你将学到占位符怎么变成action方法对应的字段。
{
return new Response('<html><body>Hello '.$name.'!</body></html>');//控制器创建并返回一个Response实体。
}
}
Mapping a URL to a Controller
一个控制器返回一个简单的html页面。为了在你的浏览器中看到,你需要创建一个来引导特殊url到控制器的路由
# app/config/routing.yml
hello:
pattern: /hello/{name}
defaults: { _controller: AcmeHelloBundle:Hello:index }
顺着/hello/ryan现在可以执行HelloController::indexAction()控制器,并且给$name变量传ryan。注意,这种句法常常被用来指向控制器:AcmeHelloBundle:Hello:index。Symfony2用一个灵活的标签来指向不同的控制器。这是最常用的来告诉Symfony2来寻找在bundle里边名称是HelloControlle的类的语法,然后方法indexAction()就被执行了。
Route Parameters as Controller Argument
你已经知道控制器字段AcmeHelloBundle:Hello:index指向一个位于AcmeHelloBundle bundle的HelloController::indexAction() 方法
<?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中。事实上,当执行你的控制器的时候,Symfony2会匹配相应的参数。
# app/config/routing.yml
hello:
pattern: /hello/{first_name}/{last_name}
defaults: { _controller: AcmeHelloBundle:Hello:index, color: green }
public function indexAction($first_name, $last_name, $color)
{
// ...
}
控制器会获取很多参数。
当您开发的时候请遵守如下指导:
1.控制器字段的顺序不重要。
2.控制器的每个字段必须和路由器的字段匹配。
3.在路由中的字段可以不出现在控制器中。
The Request as a Controller Argument
为了方便,你也可以向你的控制器中传送字段,当你用forms工作的时候,你会感觉特别方便,比如:
use Symfony\Component\HttpFoundation\Request;
public function updateAction(Request $request)
{
$form = $this->createForm(...);
$form->bindRequest($request);
// ...
}
The Base Controller Class
为了方便,Symfony2伴随着 一个基本的控制类(它和大部分的通用控制器关联并且给你任何需要的资源),通过扩展这个控制类,你可充分利用很多帮助方法。
// 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>');
}
}
Common Controller Tasks
尽管事实上一个控制器可以做任何事情,大部分控制器可以执行相同的人。这些任务,比如redirecting,forwarding,rendering templates(返回)并且接受核心的服务,在Symfony2中都是很容易管理的。
Redirecting
如果你想重定向到另一个页面,你可以用redirect()方法:
public function indexAction()
{
return $this->redirect($this->generateUrl('homepage'));
}
generateurl的方法只是一个从给定的路由生成url的帮助函数。为获取更多信息,看路由器章节。默认地,the redirect()方法执行的是302重定向,为了执行301重定向,你需要需改第二个字段。
public function indexAction()
{
return $this->redirect($this->generateUrl('homepage'), 301);
}
重定向方法是简单的一个创建一个response对象(它是用来特殊化重定向用户)。
use Symfony\Component\HttpFoundation\RedirectResponse;
return new RedirectResponse($this->generateUrl('homepage'));
Forwarding
你可以用forward()方法很容易的转向另一个内部控制器。它可以创建一个子请求,调用一个特殊的控制器,而不是重定向用户的浏览器。Forward()方法返回一个从控制器返回来的response对象。
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()方法用相同的控制器(用在路由配置中)展示字符串。在这种情况下,在一些AcmeHelloBundle的内部,目标控制类将是HelloConrtoller。在结果控制器中数组传到方法变成一个字段。目标控制器应该看起来向下面这样
public function fancyAction($name, $color)
{
// ... create and return a Response object
}
像其他基本的控制方法,forward方法只是核心Symfony2的缩写。Forward可以直接通过http_kernel service来完成。Forward返回一个response对象。
$httpKernel = $this->container->get('http_kernel');
$response = $httpKernel->forward('AcmeHelloBundle:Hello:fancy', array(
'name' => $name,
'color' => 'green',
));
Rendering Templates
尽管不是必须的,大部分控制器最终会返回一个可以为控制器生成html的模板。renderView()方法提供一个模板,并且返回它的内容。来自模板的内用可以用来创建一个response对象。
$content = $this->renderView('AcmeHelloBundle:Hello:index.html.twig', array('name' => $name));
return new Response($content);它甚至可以用render()方法一步解决所用问题。他返回一个response对象。
return $this->render('AcmeHelloBundle:Hello:index.html.twig', array('name' => $name));
在templating章节,Symfony的模板驱动详细的解释了一些东西。Renderview方法是templating service 的缩写。Templating service也可以直接调用。
$templating = $this->get('templating');
$content = $templating->render('AcmeHelloBundle:Hello:index.html.twig', array('name' => $name));
Accessing other Services
当继承了基本的控制类,你可以通过get()方法访问任何Symfony2的 service。下边是你可能需要的很多常用的services
$request = $this->getRequest();
$templating = $this->get('templating');
$router = $this->get('router');
$mailer = $this->get('mailer');
Managing Errors and 404 Pages
当事情找不到的时候,你应该用http协议并且返回404。
public function indexAction(){ $product = // retrieve the object from database
if (!$product) {throw $this->createNotFoundException('The product does not exist'); } return $this->render(...);}
createNotFoundException()方法创建了一个特殊的NotFoundHttpException 对象,他最最终会在Symfony里边出发404的http response
当然,你也可很容易的在你的控制器中抛出其他的exception类。以下是一个返回500错误的http response的代码。throw new \Exception('Something went wrong!');
Managing the Session
Symfony2 提供一个好的session对象(你可以用浏览器来存储用户信息)。默认地,用本地php session来存储cookie中的属性。从session中存储和找回信息是很容易完成的。
$session = $this->getRequest()->getSession();
// store an attribute for reuse during a later user request
$session->set('foo', 'bar');
// in another controller for another request
$foo = $session->get('foo');
// set the user locale
$session->setLocale('fr');
Flash Messages
你也可以为一个额外的请求存储一些那些将被存储在用户的session中的小信息。当运行一个form(在下个请求中,你想重定向并且有一个特殊的消息展示)的时候是很有用的。这种类型的信息被叫做flash消息。比如:假设你正在运行一个form的提交:
public function updateAction(){ $form = $this->createForm(...);
$form->bindRequest($this->getRequest());
if ($form->isValid()) {
// do some sort of processing
$this->get('session')->setFlash('notice', 'Your changes were saved!');
return $this->redirect($this->generateUrl(...));
}
return $this->render(...);
}
请求进程后,控制器设置一个notice flash信息,然后重定向,这个name(notice)没有意义。它只是你正在用来识别信息的类型。
在下一个action的模板中,下面的代码将被用来render notice消息。
% if app.session.hasFlash('notice') %}
<div class="flash-notice">
{{ app.session.flash('notice') }}
</div>
{% endif %}
The Response Object
对控制唯一的需要就是返回一个response 对象。
// create a simple Response with a 200 status code (the default)
$response = new Response('Hello '.$name, 200);
// create a JSON-response with a 200 status code
$response = new Response(json_encode(array('name' => $name)));
$response->headers->set('Content-Type', 'application/json');
The Request Object
$request = $this->getRequest();
$request->isXmlHttpRequest(); // is it an Ajax request?
$request->getPreferredLanguage(array('en', 'fr'));
$request->query->get('page'); // get a $_GET parameter
$request->request->get('page'); // get a $_POST parameter
正如 response 对象,存储在HeaderBag对象下的请求头很容易访问。
Final Thoughts