《PHP實例:Symfony2學習筆記之控制器用法詳解》要點:
本文介紹了PHP實例:Symfony2學習筆記之控制器用法詳解,希望對您有用。如果有疑問,可以聯(lián)系我們。
本文實例講述了Symfony2控制器用法.分享給大家供大家參考,具體如下:PHP實例
一個controller是你創(chuàng)建的一個PHP函數(shù),它接收HTTP哀求(request)并創(chuàng)建和返回一個HTTP回復(Response).回復對象(Response)可以是一個HTML頁面,一個XML文檔,一個序列化的JSON數(shù)組,一個圖片,一個重定向,一個404錯誤或者任何你想要的內容.controller中可以包含任何渲染你頁面內容的所需要的邏輯.PHP實例
下面是一個controller最簡單的例子,僅僅打印一個Hello world!PHP實例
use Symfony\Component\HttpFoundation\Response; public function helloAction() { return new Response('Hello world!'); }
Controller的終極目標都是相同的那就是創(chuàng)建并返回一個Response對象.依照這個思路,你可以從request對象讀取信息,加載數(shù)據(jù)庫資源,發(fā)送email,或者在用戶的Session中寫入信息.但是所有情況下,Controller將最終都會返回一個Response對象并被分發(fā)會客戶端.PHP實例
比如如下情況:PHP實例
Controller A 準備一個Response對象來表現(xiàn)網(wǎng)站homepage內容.
Controller B 從Request中讀取slug參數(shù)從數(shù)據(jù)庫中加載一個blog內容并創(chuàng)建一個Response對象來顯示這個blog.如果slug在數(shù)據(jù)庫中不存在,它將創(chuàng)建并返回一個帶有404狀態(tài)碼的Response對象.PHP實例
Controller C 處理一個從聯(lián)系表單,它從Request對象中讀取表單信息,保存聯(lián)系信息到數(shù)據(jù)庫并發(fā)郵件給管理員.最后,它創(chuàng)建一個Response對象重定向客戶端瀏覽器到聯(lián)系表單感謝頁面.PHP實例
Requests,Controller, Response的生命周期PHP實例
Symfony2項目中處理的每一個Request都是經(jīng)過了相同的簡單生命周期.框架負責重復的任務,最終執(zhí)行一個controller,該controller會包含你的應用程序代碼:PHP實例
1.每個Request都會被一個統(tǒng)一的前端控制器文件(比如,app.php,或者app_dev.php)處理,它會啟動應用程序.
2.Router從Request中讀取URI信息,并找到匹配它的Route,從該Route中讀取_controller參數(shù).
3.匹配成功的route的controller被執(zhí)行,controller中的代碼創(chuàng)建并返回一個Response對象.
4.HTTP頭和生成的Response對象內容將會被發(fā)回客戶端.PHP實例
創(chuàng)建一個頁面跟創(chuàng)建一個controller一樣容易,創(chuàng)建一個路由來映射一個URL到該controller.PHP實例
注意:盡管從名字上來看,前端控制器和controller差不多,其實它們是不同的.
一個前端控制器是一個存放于web目錄下的PHP文件,多有的Request都會通過它被重定向.每一個應用程序都會有一個產(chǎn)品前端控制器app.php和一個開發(fā)用的前端控制器app_dev.php.你不需要編輯,查看或者擔心它們.PHP實例
看一個簡單的Controller: 任何的PHP可調用內容(比如函數(shù),對象辦法或者一個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來定義,但是只有前面的部分才是其真正名字,為了統(tǒng)一起見,在后面統(tǒng)一添加Controller. 在路由配置時只會取前面部分.PHP實例
Controller類中每個被用于真正controller的辦法都會被添加一個統(tǒng)一的后綴Action,同樣我們在配置其路由時也只會取前面部分而忽略掉Action.把它映射到某個URL.PHP實例
每個controller辦法的最后必然會創(chuàng)建一個Response對象并返回它.PHP實例
映射一個URL到一個Controller辦法:PHP實例
上面例子中的controller方法返回一個簡單的HTML頁面.如果要在瀏覽器中拜訪到該頁面,那么你需要為它創(chuàng)建一個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', )));
現(xiàn)在想URL /hello/ryan 將被映射到HelloController::indexAction() controller并將ryan傳遞給$name變量.PHP實例
創(chuàng)建一個所謂的頁面,其實就是創(chuàng)建一個controller辦法和一個相關的route.PHP實例
注意我們使用的指向controller辦法的表示語法:AcmeHelloBundle:Hello:indexPHP實例
Symfony2使用了一個非常靈活的字符串聲明來指向不同的controller.它告訴Symfony2在一個名叫AcmeHelloBundle的bundle中去查找一個叫HelloController的類,并執(zhí)行它的indexAction()辦法.在這個例子中,我們的路由配置直接寫在了app/config/ 目錄下,一個更好的組織方式是把你的路由放到各自的bundle中.PHP實例
路由參數(shù)作為Controller辦法參變量PHP實例
你已經(jīng)了_controller參數(shù) AcmeHelloBundle:Hello:index指向一個位于AcmeHelloBundle中名叫HelloController::indexAction()的辦法.有趣的是路由中參數(shù)都會被傳遞給該辦法.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辦法有一個唯一參數(shù),$name, 它對應著route中定義的{name}占位符名稱.事實上,等你執(zhí)行你的controller時,Symfony2會匹配controller和route中每一個參數(shù).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到一個數(shù)組傳遞給controller.映射route參數(shù)到controller參數(shù)非常簡單和靈活.它們從route到controller不匹配順序.Symfony能夠把route中參變量的名字映射到controller辦法簽名中的變量名字.比如{last_name} => $last_name,跟排列順序無關.PHP實例
Controller辦法中的參數(shù)必須匹配route中定義的參數(shù)下面為hello route定義的controller辦法將會拋出異常:PHP實例
public function indexAction($last_name, $color, $first_name) { // .. }
如果我們把$foo變量變?yōu)榭蛇x變量,那么就不會拋異常了.PHP實例
public function indexAction($first_name, $last_name, $color, $foo) { // .. }
并不是每一個在route中定義的參數(shù)都需要在controller中有與之對應的簽名參變量的,比如hello route中定義的{$last_name} 如果對你沒什么意義的話可以在controller中省略掉它.PHP實例
public function indexAction($first_name, $color) { // .. }
反之,如果你在Controller簽名中定義了變量,并且不是可選變量,那么必須在route中有與之對應的參數(shù)被定義.PHP實例
在route定義中有一個特殊參數(shù) _route, 它匹配route的名稱(如上例中的hello).雖然不常用,但是它也可以作為controller辦法的一個參變量使用.PHP實例
Request作為一個Controller辦法簽名變量PHP實例
為了方便,你可能會讓symfony傳遞你的Request對象作為參數(shù)到你的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()辦法是一個幫助函數(shù),用于根據(jù)給定的route生成相應的URL.默認情況下,redirect()辦法執(zhí)行一個302重定向.如果要執(zhí)行301重定向,那么需要修改第二個參數(shù)如下: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內部.它執(zhí)行的是一個內部子哀求,來調用指定的controller,所以不會產(chǎn)生用戶客戶端瀏覽器的重定向.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配置中相同的字符串參數(shù).這里傳入數(shù)組參數(shù)會作為目標調用controller的參數(shù).當將controller嵌入到模板時,也會使用同樣的接口.目標調用的controller辦法應該是如下定義:PHP實例
public function fancyAction($name, $color) { // ... create and return a Response object }
就像為一個route創(chuàng)建一個controller一樣,跟參數(shù)的順序沒關系.symfony2 會匹配索引鍵名稱name到辦法參數(shù)名稱$name,即使順序打亂也沒關系.跟其它Controller基類辦法一樣,forward辦法也僅僅是一個symfony2核心函數(shù)的快捷寫法.一個跳轉可以直接通過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()辦法會渲染一個模板并返回它的內容.這個返回內容可以用作創(chuàng)建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中還有無數(shù)的可用服務,同時也鼓勵你定義自己的服務.要查看所有的服務,可以使用container:debug 命令行工具PHP實例
$ php app/console container:debug
管理錯誤和404頁面PHP實例
當一些東西沒有找到,你應該重置HTTP協(xié)議返回一個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()辦法創(chuàng)建一個特定的NotFoundHttpException對象,它最終觸發(fā)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實例
//創(chuàng)建一個簡單的Response對象,默認狀態(tài)碼為200 $response = new Response('Hello ' .$name, 200); //創(chuàng)建一個基于JSON的Response對象,狀態(tài)碼也為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 參數(shù) $request->request->get('page'); //獲取$_POST參數(shù)
跟Response對象一樣,Request對象的頭也保存在HeaderBag對象中,可以很方便的被訪問.PHP實例
總結思考:PHP實例
無論何時,你創(chuàng)建一個頁面,你最終需要為它寫一些包含邏輯的代碼.在Symfony中,這叫一個controller, 它是一個PHP的函數(shù),它可以為了最后返回一個Response對象給用戶可以做需要的任何事情.簡單的說,你可以選擇繼承一個Controller基類,它包含了許多執(zhí)行controller通用任務的快捷辦法.比如,你不想把HTML代碼寫入你的controller, 你可以使用render()辦法來渲染并返回一個模板內容.PHP實例
希望本文所述對大家基于Symfony框架的PHP程序設計有所贊助.PHP實例
《PHP實例:Symfony2學習筆記之控制器用法詳解》是否對您有啟發(fā),歡迎查看更多與《PHP實例:Symfony2學習筆記之控制器用法詳解》相關教程,學精學透。維易PHP學院為您提供精彩教程。
轉載請注明本頁網(wǎng)址:
http://www.snjht.com/jiaocheng/7334.html