搜尋
首頁後端開發php教程詳解Symfony2控制器的用法
詳解Symfony2控制器的用法Jan 05, 2018 pm 05:43 PM
控制器用法

本文主要介紹了Symfony2控制器用法,詳細分析了Symfony控制器的功能,實現技巧與相關技術細節。需要的朋友可以參考下,希望對大家有幫助。

一個controller是你建立的一個PHP函數,它接收HTTP請求(request)並建立和傳回一個HTTP回應(Response)。回應物件(Response)可以是一個HTML頁面,一個XML文檔,一個序列化的JSON數組,一個圖片,一個重定向,一個404錯誤或任何你想要的內容。 controller中可以包含任何渲染你頁面內容的所需的邏輯。

下面是一個controller最簡單的例子,只列印一個Hello world!

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

Controller的終極目標都是相同的那就是創建並傳回一個Response物件。依照這個思路,你可以從request物件讀取訊息,載入資料庫資源,發送email,或是在使用者的Session中寫入訊息。但是所有情況下,Controller將最終都會傳回一個Response物件並被分發會客戶端。

例如如下情況:

Controller A 準備一個Response物件來表現網站homepage內容。
Controller B 從Request讀取slug參數從資料庫載入一個blog內容並建立一個Response物件來顯示這個blog。如果slug在資料庫中不存在,它將建立並傳回一個帶有404狀態碼的Response物件.

Controller C 處理一個從聯絡表單,它從Request物件讀取表單訊息,保存聯絡資訊到資料庫並發送電子郵件給管理員。最後,它會建立一個Response物件重新導向客戶端瀏覽器到聯絡表單感謝頁面。

Requests,Controller, Response的生命週期

Symfony2專案中處理的每一個Request都是經過了相同的簡單生命週期。框架負責重複的任務,最終執行一個controller,該controller會包含你的應用程式程式碼:

#1.每個Request都會被一個統一的前端控制器檔案(比如,app.php,或者app_dev .php)處理,它會啟動應用程式。
2.Router從Request讀取URI訊息,並找到符合它的Route,從該Route讀取_controller參數。
3.符合成功的route的controller被執行,controller中的程式碼建立並傳回一個Response物件。
4.HTTP頭和產生的Response物件內容將會被傳回客戶端。

建立一個頁面跟創建一個controller一樣容易,創建一個路由來映射一個URL到該controller。

注意:儘管從名字來看,前端控制器和controller差不多,其實它們是不同的。
一個前端控制器是一個存放於web目錄下的PHP文件,多有的Request都會透過它被重定向。每一個應用程式都會有一個產品前端控制器app.php和一個開發用的前端控制器app_dev.php。你不需要編輯,查看或擔心它們。

看一個簡單的Controller: 任何的PHP可呼叫內容(例如函數,物件方法或一個Closure)都可以成為一個controller。 Symfongy2中,一個controller通常為controller物件中一個單一的方法。 Controllers通常也被稱為actions。

// 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;);
 }
}

注意在這個例子中controller是indexAction方法,它存在於controller類別(HelloController)中。不要混淆,之所以定義一個controller類別(HelloController)只是為了方便組織多個controllers/actions在一起。一般情況下,一個controller類別會有多個controllers/actions。

上面範例中的controller相當簡單:

Namespace行是symfony2使用了PHP5.3的命名空間功能來為整個controller類別指定命名空間。
use關鍵字導入了Response類,這是我們的controller必須回傳的內容。

Controller類別名字都是由其名字後面加上Controller來定義,但是只有前面的部分才是其真正名字,為了統一起見,在後面統一添加Controller。 路由配置時只會取前面部分。

Controller類別中每個被用於真正controller的方法都會被加入一個統一的後綴Action,同樣我們在配置其路由時也只會取前面部分而忽略掉Action。把它映射到某個URL。

每個controller方法的最後必然會建立一個Response物件並回傳它。

映射一個URL到一個Controller方法:

上面範例中的controller方法傳回一個簡單的HTML頁面。如果要在瀏覽器中造訪到該頁面,那麼你需要為它建立一個route,把它對應到一個特定模式的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() controller並將ryan傳遞給$name變數。

創造一個所謂的頁面,其實就是要建立一個controller方法和一個相關的route。

注意我們使用的指向controller方法的表示語法: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
Windows 11 上正确校准 Xbox One 控制器的方法Windows 11 上正确校准 Xbox One 控制器的方法Sep 21, 2023 pm 09:09 PM

由于Windows已成为首选的游戏平台,因此确定其面向游戏的功能就显得尤为重要。其中之一是能够在Windows11上校准XboxOne控制器。借助内置的手动校准,您可以摆脱漂移、随机移动或性能问题,并有效地对齐X、Y和Z轴。如果可用选项不起作用,您可以随时使用第三方XboxOne控制器校准工具。让我们来了解一下!如何在Windows11上校准我的Xbox控制器?在继续操作之前,请确保将控制器连接到电脑并更新XboxOne控制器的驱动程序。当您使用它时,还要安装任何可用的固件更新。1.使用Wind

从零开始学习Laravel:控制器方法调用详解从零开始学习Laravel:控制器方法调用详解Mar 10, 2024 pm 05:03 PM

从零开始学习Laravel:控制器方法调用详解在Laravel的开发中,控制器是一个非常重要的概念。控制器起到了连接模型和视图的桥梁作用,负责处理来自路由的请求,并返回相应的数据给视图展示。控制器中的方法可以被路由调用,这篇文章将详细介绍如何编写并调用控制器中的方法,同时会提供具体的代码示例。首先,我们需要创建一个控制器。可以使用Artisan命令行工具来生

php如何使用CodeIgniter4框架?php如何使用CodeIgniter4框架?May 31, 2023 pm 02:51 PM

PHP是一种非常流行的编程语言,而CodeIgniter4是一种常用的PHP框架。在开发Web应用程序时,使用框架是非常有帮助的,它可以加速开发过程、提高代码质量、降低维护成本。本文将介绍如何使用CodeIgniter4框架。安装CodeIgniter4框架CodeIgniter4框架可以从官方网站(https://codeigniter.com/)下载。下

Python函数介绍:abs函数的用法和示例Python函数介绍:abs函数的用法和示例Nov 03, 2023 pm 12:05 PM

Python函数介绍:abs函数的用法和示例一、abs函数的用法介绍在Python中,abs函数是一个内置函数,用于计算给定数值的绝对值。它可以接受一个数字参数,并返回该数字的绝对值。abs函数的基本语法如下:abs(x)其中,x是要计算绝对值的数值参数,可以是整数或浮点数。二、abs函数的示例下面我们将通过一些具体的示例来展示abs函数的用法:示例1:计算

什么叫laravel控制器什么叫laravel控制器Jan 14, 2023 am 11:16 AM

在laravel中,控制器(Controller)是一个类,用于实现一定的功能;控制器能将相关的请求处理逻辑组成一个单独的类。控制器中存放中一些方法,实现一定的功能,通过路由调用控制器,不再使用回调函数;控制器被存放在“app/Http/Controllers”目录中。

Python函数介绍:isinstance函数的用法和示例Python函数介绍:isinstance函数的用法和示例Nov 04, 2023 pm 03:15 PM

Python函数介绍:isinstance函数的用法和示例Python是一门功能强大的编程语言,提供了许多内置函数,使得编程变得更加方便和高效。其中一个非常有用的内置函数是isinstance()函数。本文将介绍isinstance函数的用法和示例,并提供具体的代码示例。isinstance()函数用于判断一个对象是否是指定的类或类型的实例。该函数的语法如下

Laravel学习指南:控制器方法调用的最佳实践Laravel学习指南:控制器方法调用的最佳实践Mar 11, 2024 am 08:27 AM

在Laravel学习指南中,控制器方法的调用是一个非常重要的主题。控制器扮演着连接路由和模型的桥梁的角色,在应用程序中起着至关重要的作用。本文将介绍控制器方法调用的最佳实践,并提供具体的代码示例帮助读者更好地理解。首先,让我们来了解控制器方法的基本结构。在Laravel中,控制器类通常存放在app/Http/Controllers目录下,每个控制器类包含多个

Python函数介绍:getattr函数的用法和示例Python函数介绍:getattr函数的用法和示例Nov 04, 2023 pm 01:39 PM

Python函数介绍:getattr函数的用法和示例在Python中,getattr()是一个内置函数,用于获取对象的属性值。在不知道对象的属性名称的情况下,可以使用getattr()函数来动态地访问属性。本文将介绍getattr()函数的语法、用法和示例。getattr()函数的语法如下:getattr(object,name[,default])参数

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。