在 Symfony2 架構中,控制器是處理 HTTP 請求並返回 HTTP 回應的核心元件。它接收 Request 物件,執行業務邏輯(資料庫查詢、表單處理、郵件發送等),最終必須返回一個 Response 物件。無論回應內容是 HTML、JSON、XML、圖片、重定向或 404 錯誤,本質上都是 Response 物件的不同表現形式。
app.php 或 app_dev.php)進入應用程式_controller 參數注意:前端控制器與控制器是不同概念。前端控制器是 web/ 目錄下的 PHP 入口檔案,每個應用通常只有一個生產版(app.php)和一個開發版(app_dev.php)。
use Symfony\Component\HttpFoundation\Response;
public function helloAction()
{
return new Response('Hello world!');
}
// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
class HelloController
{
public function indexAction($name)
{
return new Response('Hello '.$name.'!');
}
}
命名慣例:
Controller 結尾(路由配置時只取前綴)Action 結尾(路由配置時只取前綴)Bundle:Controller:action → AcmeHelloBundle:Hello:index路由中的佔位符與 defaults 會自動映射到控制器方法參數(按名稱而非順序):
# 路由配置
hello:
pattern: /hello/{first_name}/{last_name}
defaults: { _controller: AcmeHelloBundle:Hello:index, color: green }
public function indexAction($first_name, $last_name, $color)
{
// 參數自動注入,順序可任意調換
}
規則:
_route 可獲取當前路由名稱在方法簽名中型別提示 Request 即可自動注入:
use Symfony\Component\HttpFoundation\Request;
public function updateAction(Request $request)
{
$form = $this->createForm(...);
$form->bindRequest($request);
// ...
}
繼承 Symfony\Bundle\FrameworkBundle\Controller\Controller 可獲得豐富輔助方法:
public function indexAction()
{
return $this->redirect($this->generateUrl('homepage')); // 302
// return $this->redirect($this->generateUrl('homepage'), 301); // 301
}
public function indexAction($name)
{
$response = $this->forward('AcmeHelloBundle:Hello:fancy', array(
'name' => $name,
'color' => 'green'
));
return $response;
}
轉發是內部子請求,不會觸發瀏覽器重定向。目標控制器:
public function fancyAction($name, $color)
{
// 建立並返回 Response 物件
}
// 簡化寫法
return $this->render('AcmeHelloBundle:Hello:index.html.twig', array('name' => $name));
// 等同於
$content = $this->renderView('AcmeHelloBundle:Hello:index.html.twig', array('name' => $name));
return new Response($content);
$request = $this->getRequest();
$templating = $this->get('templating');
$router = $this->get('router');
$mailer = $this->get('mailer');
查看所有可用服務:php app/console container:debug
public function indexAction()
{
$product = // 從資料庫查詢
if (!$product) {
throw $this->createNotFoundException('產品不存在');
}
return $this->render(...);
}
拋出任意 Exception 會自動轉為 500 錯誤回應。
$session = $this->getRequest()->getSession();
// 儲存屬性
$session->set('foo', 'bar');
// 讀取屬性
$foo = $session->get('foo');
// 設定語系
$session->setLocale('fr');
適用於重定向後顯示一次性通知:
public function updateAction()
{
// ... 表單處理
if ($form->isValid()) {
$this->get('session')->setFlash('notice', '變更已儲存!');
return $this->redirect($this->generateUrl(...));
}
return $this->render(...);
}
模板中顯示:
{% if app.session.hasFlash('notice') %}
{{ app.session.flash('notice') }}
{% endif %}
// 簡單回應
$response = new Response('Hello ' . $name, 200);
// JSON 回應
$response = new Response(json_encode(array('name' => $name)));
$response->headers->set('Content-Type', 'application/json');
headers 屬性為 HeaderBag 物件,提供豐富的標頭操作方法。
$request = $this->getRequest();
$request->isXmlHttpRequest(); // 判斷 AJAX 請求
$request->getPreferredLanguage(array('en','fr'));
$request->query->get('page'); // 獲取 $_GET 參數
$request->request->get('page'); // 獲取 $_POST 參數
Symfony2 控制器設計遵循單一職責原則,透過基礎類提供的輔助方法大幅簡化常見任務。開發者可專注於業務邏輯,而將 HTTP 細節交由框架處理。無論是渲染模板、重定向、轉發、錯誤處理還是 Session 管理,都有標準化的解決方案。