>  기사  >  백엔드 개발  >  Symfony2 컨트롤러 사용법에 대한 자세한 설명

Symfony2 컨트롤러 사용법에 대한 자세한 설명

*文
*文원래의
2018-01-05 17:43:051819검색

이 글에서는 주로 Symfony2 컨트롤러의 사용법을 소개하고, Symfony 컨트롤러의 기능, 구현 기술 및 관련 기술 세부 사항을 자세히 분석합니다. 도움이 필요한 친구들이 참고하면 좋을 것 같아요.

컨트롤러는 HTTP 요청(요청)을 수신하고 HTTP 응답(응답)을 생성 및 반환하는 PHP 함수입니다. 응답 객체(Response)는 HTML 페이지, XML 문서, 직렬화된 JSON 배열, 이미지, 리디렉션, 404 오류 또는 원하는 모든 것이 될 수 있습니다. 컨트롤러에는 페이지 콘텐츠를 렌더링하는 데 필요한 모든 로직이 포함될 수 있습니다.

다음은 Hello world를 인쇄하는 가장 간단한 컨트롤러의 예입니다!

use Symfony\Component\HttpFoundation\Response;
public function helloAction()
{
 return new Response('Hello world!');
}

컨트롤러의 궁극적인 목표는 응답 객체를 생성하고 반환하는 것과 동일합니다. 이 아이디어에 따라 요청 개체에서 정보를 읽고, 데이터베이스 리소스를 로드하고, 이메일을 보내고, 사용자 세션에 정보를 쓸 수 있습니다. 그러나 모든 경우에 Controller는 결국 Response 객체를 반환하고 클라이언트에 배포됩니다.

예를 들어 다음 상황은 다음과 같습니다.

컨트롤러 A는 웹 사이트 홈페이지 콘텐츠를 나타내기 위해 응답 개체를 준비합니다.
컨트롤러 B는 요청에서 슬러그 매개변수를 읽고, 데이터베이스에서 블로그 콘텐츠를 로드하고, 블로그를 표시하기 위한 응답 개체를 생성합니다. 슬러그가 데이터베이스에 없으면 404 상태 코드가 포함된 응답 개체를 생성하고 반환합니다.

컨트롤러 C는 문의 양식을 처리하고 요청 개체에서 양식 정보를 읽고 연락처 정보를 데이터베이스에 저장합니다. 그리고 관리자에게 이메일을 보냅니다. 마지막으로 클라이언트 브라우저를 문의 양식 감사 페이지로 리디렉션하는 응답 객체를 생성합니다.

요청, 컨트롤러, 응답의 라이프사이클

Symfony2 프로젝트에서 처리되는 모든 요청은 동일한 간단한 라이프사이클을 거칩니다. 프레임워크는 반복적인 작업을 담당하며 궁극적으로 애플리케이션 코드를 포함하는 컨트롤러를 실행합니다:

1. 각 요청은 통합된 프런트 엔드 컨트롤러 파일(예: app.php 또는 app_dev.php)에 의해 처리됩니다. , 그러면 응용 프로그램이 시작됩니다.
2.Router는 요청에서 URI 정보를 읽고, 일치하는 경로를 찾은 다음 경로에서 _controller 매개변수를 읽습니다.
3. 성공적으로 일치된 경로의 컨트롤러가 실행되고 컨트롤러의 코드가 Response 객체를 생성하고 반환합니다.
4.HTTP 헤더와 생성된 응답 개체 콘텐츠가 클라이언트로 다시 전송됩니다.

페이지 생성은 컨트롤러를 생성하고 URL을 컨트롤러에 매핑하는 경로를 생성하는 것만큼 쉽습니다.

참고: 프런트엔드 컨트롤러와 컨트롤러는 이름은 비슷하지만 실제로는 다릅니다.
프런트엔드 컨트롤러는 웹 디렉토리에 저장된 PHP 파일이며, 모든 요청은 이를 통해 리디렉션됩니다. 모든 애플리케이션에는 프로덕션 프런트엔드 컨트롤러 app.php와 개발 프런트엔드 컨트롤러 app_dev.php가 있습니다. 편집하거나 보거나 걱정할 필요가 없습니다.

간단한 컨트롤러 살펴보기: 모든 PHP 호출 가능 콘텐츠(예: 함수, 개체 메서드 또는 클로저)가 컨트롤러가 될 수 있습니다. Symfongy2에서 컨트롤러는 일반적으로 컨트롤러 개체의 단일 메서드입니다. 컨트롤러는 흔히 액션이라고도 합니다.

// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
class HelloController
{
 public function indexAction($name)
 {
  return new Response(&#39;<html><body>Hello &#39;.$name.&#39;!</body></html>&#39;);
 }
}

이 예제에서 컨트롤러는 컨트롤러 클래스(HelloController)에 존재하는 indexAction 메서드라는 점에 유의하세요. 혼동하지 마십시오. 컨트롤러 클래스(HelloController)가 정의된 이유는 여러 컨트롤러/액션을 함께 구성하는 것을 용이하게 하기 위한 것입니다. 일반적으로 컨트롤러 클래스에는 여러 컨트롤러/작업이 있습니다.

위 예제의 컨트롤러는 매우 간단합니다.

Namespace 행은 Symfony2가 PHP5.3의 네임스페이스 기능을 사용하여 전체 컨트롤러 클래스에 대한 네임스페이스를 지정하는 곳입니다.
use 키워드는 컨트롤러가 반환해야 하는 Response 클래스를 가져옵니다.

Controller 클래스 이름은 이름 끝에 Controller를 추가하여 정의하는데, 통일성을 위해 앞부분만 실제 이름입니다. 라우팅 구성 중에는 첫 번째 부분만 사용됩니다.

실제 컨트롤러에 사용되는 Controller 클래스의 모든 메소드에는 통합 접미사 Action이 추가됩니다. 마찬가지로 라우팅을 구성할 때 첫 번째 부분만 취하고 Action을 무시합니다. URL에 매핑하세요.

각 컨트롤러 메소드의 끝에서 Response 객체를 생성하고 반환해야 합니다.

URL을 컨트롤러 메소드에 매핑:

위 예제의 컨트롤러 메소드는 간단한 HTML 페이지를 반환합니다. 브라우저에서 이 페이지에 액세스하려면 해당 페이지에 대한 경로를 생성하고 특정 패턴을 사용하여 URL에 매핑해야 합니다.

# app/config/routing.yml
hello:
 pattern:  /hello/{name}
 defaults:  { _controller: AcmeHelloBundle:Hello:index }

XML 형식:

<!-- app/config/routing.xml -->
<route id="hello" pattern="/hello/{name}">
 <default key="_controller">AcmeHelloBundle:Hello:index</default>
</route>

PHP 코드 형식:

// app/config/routing.php
$collection->add(&#39;hello&#39;, new Route(&#39;/hello/{name}&#39;, array(
 &#39;_controller&#39; => &#39;AcmeHelloBundle:Hello:index&#39;,
)));

이제 URL /hello/ryan이 HelloController::indexAction() 컨트롤러에 매핑되고 ryan을 $name 변수에 전달한다고 상상해 보세요.

소위 페이지를 만드는 것은 실제로 컨트롤러 메서드와 관련 경로를 만드는 것입니다.

컨트롤러 메서드를 가리키는 데 사용하는 구문에 유의하세요: AcmeHelloBundle:Hello:index

Symfony2使用了一个非常灵活的字符串声明来指向不同的controller。它告诉Symfony2在一个名叫AcmeHelloBundle的bundle中去查找一个叫HelloController的类,并执行它的indexAction()方法。在这个例子中,我们的路由配置直接写在了app/config/ 目录下,一个更好的组织方式是把你的路由放到各自的bundle中。

路由参数作为Controller方法参变量

你已经了_controller参数 AcmeHelloBundle:Hello:index指向一个位于AcmeHelloBundle中名叫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方法有一个唯一参数,$name, 它对应着route中定义的{name}占位符名称。事实上,等你执行你的controller时,Symfony2会匹配controller和route中每一个参数。

如果我修改一下Hello的路由定义:

YAML格式:

# app/config/routing.yml
hello:
 pattern:  /hello/{first_name}/{last_name}
 defaults:  { _controller: AcmeHelloBundle:Hello:index, color: green }

XML格式:

<!-- 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代码格式:

// app/config/routing.php
$collection->add(&#39;hello&#39;, new Route(&#39;/hello/{first_name}/{last_name}&#39;, array(
 &#39;_controller&#39; => &#39;AcmeHelloBundle:Hello:index&#39;,
 &#39;color&#39;  => &#39;green&#39;,
)));

这时候controller中可以获取这些参变量了:

public function indexAction($first_name, $last_name, $color)
{
 // ...
}

注意route定义中无论是占位符变量还是默认值变量都会被转化为controller方法的输入变量。当一个route匹配成功时,它会合并占位符和defaults到一个数组传递给controller。映射route参数到controller参数非常简单和灵活。它们从route到controller不匹配顺序。Symfony能够把route中参变量的名字映射到controller方法签名中的变量名字。比如{last_name} => $last_name,跟排列顺序无关。

Controller方法中的参数必须匹配route中定义的参数下面为hello route定义的controller方法将会抛出异常:

public function indexAction($last_name, $color, $first_name)
{
 // ..
}

如果我们把$foo变量变为可选变量,那么就不会抛异常了。

public function indexAction($first_name, $last_name, $color, $foo)
{
 // ..
}

并不是每一个在route中定义的参数都需要在controller中有与之对应的签名参变量的,比如hello route中定义的{$last_name} 如果对你没什么意义的话可以在controller中省略掉它。

public function indexAction($first_name, $color)
{
 // ..
}

反之,如果你在Controller签名中定义了变量,并且不是可选变量,那么必须在route中有与之对应的参数被定义。

在route定义中有一个特殊参数 _route, 它匹配route的名称(如上例中的hello)。虽然不常用,但是它也可以作为controller方法的一个参变量使用。

Request作为一个Controller方法签名变量

为了方便,你可能会让symfony传递你的Request对象作为参数到你的controller方法。这在你处理表单时尤为方便。

use Symfony\Component\HttpFoundation\Request;
public function updateAction(Request $request)
{
 $form = $this->createForm(...);
 $form->bindRequest($request);
 // ...
}

Controller基类

为了方便,Symfony2定义了一个Controller基类,包含了一些常用的controller任务并给了你的controller类访问任何你需要的资源的途径。通过继承该类,你可以获得许多帮助方法。

// 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(&#39;<html><body>Hello &#39;.$name.&#39;!</body></html>&#39;);
 }
}

在Symfony中controller并不一定非得继承Controller基类,因为它内部的帮助方法等都不是必须的。你也可以继承 Symfony\Component\DependencyInjection\ContainerAware 服务容器对象可以通过container属性来访问。同时你也可以把controller定义成service。

通用的Controller任务:

尽管Controller可以干任何事情,但是大部分的controller还是要重复的干一些基础的任务。比如 重定向,跳转,渲染模板和访问核心服务等。

重定向(redirecting)

如果你想重定向你的用户到另一个页面,可以使用redirect()方法。

public function indexAction()
{
 return $this->redirect($this->generateUrl(&#39;homepage&#39;));
}

这里generateUrl()方法是一个帮助函数,用于根据给定的route生成相应的URL。默认情况下,redirect()方法执行一个302重定向。如果要执行301重定向,那么需要修改第二个参数如下:

public function indexAction()
{
 return $this->redirect($this->generateUrl(&#39;homepage&#39;), 301);
}

redirect()方法其实是一个简化写法,真正的代码如下:

use Symfony\Component\HttpFoundation\RedirectResponse;
return new RedirectResponse($this->generateUrl(&#39;homepage&#39;));

跳转(Forwarding)

你可以使用forward()方法很容易从一个controller到另一个controller内部。它执行的是一个内部子请求,来调用指定的controller,所以不会产生用户客户端浏览器的重定向。forward()方法返回的Response对象还将从原controller返回。

public function indexAction($name)
{
 $response = $this->forward(&#39;AcmeHelloBundle:Hello:fancy&#39;, array(
  &#39;name&#39; => $name,
  &#39;color&#39; => &#39;green&#39;
 ));
 // further modify the response or return it directly
 return $response;
}

这里forward()方法使用了跟route配置中相同的字符串参数。这里传入数组参数会作为目标调用controller的参数。当将controller嵌入到模板时,也会使用同样的接口。目标调用的controller方法应该是如下定义:

public function fancyAction($name, $color)
{
 // ... create and return a Response object
}

就像为一个route创建一个controller一样,跟参数的顺序没关系。symfony2 会匹配索引键名称name到方法参数名称$name,即使顺序打乱也没关系。跟其它Controller基类方法一样,forward方法也仅仅是一个symfony2核心函数的快捷写法。一个跳转可以直接通过http_kernel服务来完成,返回一个Response对象。

$httpKernel = $this->container->get(&#39;http_kernel&#39;);
$response = $httpKernel->forward(&#39;AcmeHelloBundle:Hello:fancy&#39;, array(
 &#39;name&#39; => $name,
 &#39;color&#39; => &#39;green&#39;,
));

渲染模板:

虽然不是必须的,但是大部分controller将最终渲染一个负责生成为controller负责生成HTML的模板。renderView()方法会渲染一个模板并返回它的内容。这个返回内容可以用作创建Response对象,以供controller返回使用。

$content = $this->renderView(&#39;AcmeHelloBundle:Hello:index.html.twig&#39;, array(&#39;name&#39; => $name));
return new Response($content);

上面的代码完全可以更进一步的使用下面的代码形式来写:

return $this->render(&#39;AcmeHelloBundle:Hello:index.html.twig&#39;, array(&#39;name&#39; => $name));

这两种情况下,AcmeHelloBundle中的模板Resources/views/Hello/index.html.twig都会被渲染。

renderview()方法是如下代码的快捷写法:

$templating = $this->get(&#39;templating&#39;);
$content = $templating->render(&#39;AcmeHelloBundle:Hello:index.html.twig&#39;, array(&#39;name&#39; => $name));

当然也可以在子目录中渲染模板

$templating->render(&#39;AcmeHelloBundle:Hello/Greetings:index.html.twig&#39;, array(&#39;name&#39; => $name));
// index.html.twig 存放于 Resources/views/Hello/Greetings 目录.

访问其它服务

只要是继承了Controller基类,你就可以通过get()方法访问symfony2的服务了。比如:

$request = $this->getRequest();
$templating = $this->get(&#39;templating&#39;);
$router = $this->get(&#39;router&#39;);
$mailer = $this->get(&#39;mailer&#39;);

Symfony2中还有无数的可用服务,同时也鼓励你定义自己的服务。要查看所有的服务,可以使用container:debug 命令行工具

$ php app/console container:debug

管理错误和404页面

当一些东西没有找到,你应该重置HTTP协议返回一个404 回复。要做到这个,你将抛出一个特殊类型的异常。如果你是继承了Controller基类,则:

public function indexAction()
{
 $product = // retrieve the object from database
 if (!$product) {
  throw $this->createNotFoundException(&#39;The product does not exist&#39;);
 }
 return $this->render(...);
}

createNotFoundException()方法创建一个特定的NotFoundHttpException对象,它最终触发404 HTTP回复。当然你从你的controller方法中可以抛出任何类型的Exception 类,Symfony2会自动返回一个500 HTTP回复代码。

throw new \Exception(&#39;Something went wrong!&#39;);

管理Session

Symfony2 提供了一个非常好的Session对象,你可以用它来在请求之间存贮有关用户的信息。默认情况下,Symfony2 通过PHP本身的Session保存属性到cookie。在任何controller中存储和获取Session信息将非常容易:

$session = $this->getRequest()->getSession();
// 为用户的后一个请求使用存储一个属性
$session->set(&#39;foo&#39;, &#39;bar&#39;);
// 在另一个controller中为另一个请求获取该属性
$foo = $session->get(&#39;foo&#39;);
// 设置用户的本地化语言
$session->setLocale(&#39;fr&#39;);

Flash 消息

你可以为特定的请求存储少量的消息到用户的Session。这在处理一个表单时非常有用,你想重定向和一个特定的信息显示在下一个请求中。这种类型的消息被称为Flash消息。比如,假设你处理一个表单提交:

public function updateAction()
{
 $form = $this->createForm(...);
 $form->bindRequest($this->getRequest());
 if ($form->isValid()) {
  // 做些排序处理
  $this->get(&#39;session&#39;)->setFlash(&#39;notice&#39;, &#39;Your changes were saved!&#39;);
  return $this->redirect($this->generateUrl(...));
 }
 return $this->render(...);
}

此例中,在处理完请求后,controller设置了一个notice flash消息并作了重定向。名字notice没什么意义,只是用于标识该消息。在下一个活动的模板中,下面的代码能够渲染这个notic消息:

Twig

{% if app.session.hasFlash(&#39;notice&#39;) %}
 <p class="flash-notice">
  {{ app.session.flash(&#39;notice&#39;) }}
 </p>
{% endif %}

PHP代码:

<?php if ($view[&#39;session&#39;]->hasFlash(&#39;notice&#39;)): ?>
 <p class="flash-notice">
  <?php echo $view[&#39;session&#39;]->getFlash(&#39;notice&#39;) ?>
 </p>
<?php endif; ?>

这样设计,flash消息就能够为准确的某个请求存在了。他们一般被设计出来就是用于重定向的。

Response对象

作为一个Controller来说,唯一必须做到的是返回一个Response对象。

Response对象是一个PHP代码对HTTP Response的抽象。
HTTP Response是一个基于文本的消息有HTTP headers和 返回给客户端的内容组成。

//创建一个简单的Response对象,默认状态码为200
$response = new Response(&#39;Hello &#39; .$name, 200);
//创建一个基于JSON的Response对象,状态码也为200
$response = new Response(json_encode(array(&#39;name&#39;=>$name)));
$response->headers->set(&#39;content-type&#39;,&#39;application/json&#39;);

其中headers属性是一个HeaderBag对象,内部包含许多有用的方法来读取和改变Response的头信息。头名字被标准化使用Content-Type 与content-type或者content_type效果等同。

请求对象Request

除了路由占位符的值以外,如果继承了Controller基类那么该controller还可以访问Request对象。

$request = $this->getRequest();
$request->isXmlHttpRequest(); // 判断是不是Ajax请求
$request->getPreferredLanguage(array(&#39;en&#39;,&#39;fr&#39;));
$request->query->get(&#39;page&#39;); // 获取$_GET 参数
$request->request->get(&#39;page&#39;); //获取$_POST参数

跟Response对象一样,Request对象的头也保存在HeaderBag对象中,可以很方便的被访问。

总结思考:

无论何时,你创建一个页面,你最终需要为它写一些包含逻辑的代码。在Symfony中,这叫一个controller, 它是一个PHP的函数,它可以为了最后返回一个Response对象给用户可以做需要的任何事情。简单的说,你可以选择继承一个Controller基类,它包含了许多执行controller通用任务的快捷方法。比如,你不想把HTML代码写入你的controller, 你可以使用render()方法来渲染并返回一个模板内容。

相关推荐:

详解Symfony模板快捷变量的用法

详解Symfony在模板和行为中取得request参数的方法

详解symfony如何使用命令创建项目

위 내용은 Symfony2 컨트롤러 사용법에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.