第一章:Symfony2和HTTP基本原理

恭喜你!經過學習Symfony2,你將用你本身的方式開發出更加高效、全面和流行的Web應用(固然,要受到用人單位或同行的歡迎,仍是得靠你本身)。Symfony2的存在是爲了要解決最根本的問題:即提供一個開發工具,使開發者能以本身的方式更快速地開發出更爲健壯的應用程序。Symfony2集成了許多技術的優勢,包括工具和概念,你將學到大多數人多年來努力的方向。換句話說,你不僅是在學習Symfony2,你還將學習Web基礎原理、最佳開發實踐以及如何使用許多新的、優秀的PHP開發庫。因此,請作好準備!
php

本章將從解釋Web開發過程當中最常接觸的基礎概念開始:HTTP協議。不管技術背景或首選編程語言是什麼,本章的內容對於全部人來講都是必需要了解的。html

HTTP很簡單

HTTP(超文本傳輸協議)是一個容許兩個機器相互通訊的文本語言。舉例來講,當你要去 xkcd 網站查看最新的漫畫時,下列會話(近似地)將在你的瀏覽器和服務器之間發生:前端

雖然實際使用的語言將更加正規,但它依然是很簡單的。HTTP定義了這種簡單文本語言的語義和語法。而不管你從事何種的Web開發,你的服務器老是要理解基於文本的請求,並返回基於文本的響應。git

Symfony2是基於現實構建的,不管你是否意識到這一點,HTTP都是你天天所需的。隨着對Symfony2學習的深刻,你將學會如何掌握它。github

第一步:客戶端發送一個請求

Web上的每一個會話都是從一個請求開始的,這個請求是由客戶端(如:網頁瀏覽器、iPhone應用程序等)建立的一種特殊格式的文本消息,該格式符合HTTP協議規範。客戶端將該請求發送到服務端,而後等待服務端響應。數據庫

下圖體現的是,瀏覽器與xkcd服務器之間交互的第一階段(請求):編程

以HTTP的方式來講,HTTP請求就象下面這個樣子:數組

GET / HTTP/1.1
Host: xkcd.com
Accept: text/html
User-Agent: Mozilla/5.0 (Macintosh)

這個簡單的消息準確地描述了客戶端所請求的究竟是哪一個資源。HTTP請求的第一行是最重要的,它包含了兩項信息:URI和HTTP方法。瀏覽器

URI(如:/、/contact等)代表了客戶端所請求資源的惟一地址或位置。HTTP方法(如:GET)則是向服務器說明你想對資源作什麼,HTTP方法是請求的「動詞」,用以定義你對資源的操做:緩存

GET 從服務器上檢索資源
POST 在服務器上建立一個資源
UPDATE 更新服務器上的資源
DELETE 刪除從服務器上該資源

按照這個規則,你能夠發送一條要求刪除指定博文的請求,如:

DELETE /blog/15 HTTP/1.1

註釋:實際上,HTTP協議裏一共定義了9種HTTP方法,但它們中的大部分並無獲得普遍的使用和支持。實際上,許多現代的瀏覽器並不支持PUT和DELETE方法

除了第一行,HTTP請求所包含其餘行的信息被稱爲HTTP請求頭,頭信息還包含:主機、客戶端接受響應的格式、客戶端所用代理的應用程序等。還有許多其它的HTTP請求頭存在,你能夠在維基百科的 List of HTTP header fields 中找到它們。

第二步:服務端返回響應

服務端獲得請求,它就明確地知道客戶端須要哪一個資源(經過URI)以及但願對該資源進行什麼操做(經過HTTP方法)。例如,對於一個GET請求,服務端將準備資源,並在HTTP響應中將其返回給客戶端。如,xkcd服務端返回的響應:

 

按照HTTP協議的格式,被返回給客戶端的響應以下所示:

HTTP/1.1 200 OK
Date: Sat, 02 Apr 2011 21:05:05 GMT
Server: lighttpd/1.4.19
Content-Type: text/html
 
<html>
  <!-- HTML for the xkcd comic -->
</html>

HTTP響應包含了客戶端所請求的資源(在這個例子裏是HTML),以及與響應相關的信息。與請求頭相似,第一行也最重要,它給出的是HTTP狀態碼(在 上面的例子裏是200)。狀態碼報告了響應的狀態,如,請求是否成功?是否存在錯誤?不一樣的狀態碼錶示着成功、錯誤或者通知客戶端須要作其它一些事(如重 定向到另外一頁)。完整的列表能夠在維基百科的 HTTP狀態代碼列表 中找到。

全部這些響應信息,組成了響應頭。其中一個重要的HTTP響應頭消息被稱爲Content-Type。服務器上的每一個資源均可以以不一樣的格式返回給客戶端,如HTML、XML或JSON等;經過在Content-Type裏設置如text/html這樣的互聯網媒體類型碼,能夠告知客戶端,服務器給出的響應格式是什麼。常見的媒體類型能夠在維基百科的互聯網媒體類型列表 裏找到。

還存在不少其餘的HTTP響應頭,其中有些能夠起到很重要的做用。好比,某些響應頭能夠用來維護HTTP緩存。

請求響應和Web開發

「請求-響應」對話是驅動Web上全部通訊的基礎,它是如此的強大和重要,它又是如此的簡單。

最重要的事實是,無論你使用哪一種開發語言,構建哪一種應用(Web、手機、JSON應用程序接口等),遵循哪一種開發理論,應用程序的最終目標老是一致的:理解每一個請求,建立並返回相應的響應。

Symfony2就是來完成這一「使命」的:

要更瞭解HTTP協議規範,能夠參考 HTTP 1.1 RFC 或者 HTTP Bis (用更直白明瞭方式的來講明HTTP協議規範)。另外,有一款叫作 Live HTTP Headers 的Firefox瀏覽器擴展能夠用來查看上網過程當中請求、響應頭的內容。

PHP是如何處理請求和返回響應的

那麼,怎麼用PHP來獲知「請求」,並建立「響應」呢?PHP對實際的操做進行了封裝,你要作的,相對還算簡單:

從請求到響應

同HTTP同樣,Request和Response對象也很簡單。應用程序最複雜的部分是在二者之間寫些什麼。換句話說,真正的工做來自於編寫解釋請求並建立響應的代碼。

你的應用程序可能作了諸如發送電子郵件、處理提交表單、向數據庫寫入數據、渲染HTML頁面和確保內容安全性等諸多事情,但你如何來管理這一切,同時還要保持你代碼的組織性和可維護性呢?

Symfony2就是用來解決上述問題,而無須讓你所以分心。

前端控制器

傳統方式中構建的應用程序,網站中的每一「頁」都是它自身的物理文件。

  index.php 
    contact.php 
    blog.php

使用這種方式存在幾個問題:不靈活的URL(你是否能夠將blog.php文件更名爲news.php,而無須破壞你全部的連接?)、每一個文件都必須手工包含一些核心文件集以確保安全性(數據庫鏈接和網站外觀必須保持一致)。

更好的解決方案是使用前端控制器:單一的PHP文件,該文件用來處理進入應用程序的全部請求。例如:

/index.php 執行index.php
/index.php/contact 執行index.php
/index.php/blog 執行index.php

使用Apache的mod_rewrite模塊(或其它Web服務器的類似模塊),URL能夠很方便地被清理成諸如:/、/contact、/blog 這樣的連接。

如今,全部請求的處理都徹底同樣。前端控制器將被始終執行,不一樣的URL將被內部路由到你應用程序的不一樣部分,而無須根據不一樣的URL執行不一樣的PHP文件。這樣就解決了前面傳統方式所帶來的問題。幾乎全部現代應用程序均可以作到這一點,其中包括相似WordPress這樣的應用程序。
保持代碼的組織性
前端控制器又是如何知道哪一個頁面要被渲染,如何正確渲染呢?這須要判斷傳入的URI,針對性地調用不一樣的代碼。這也不是容易的差事:

// index.php
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
 
$request = Request::createFromGlobals();
$path = $request->getPathInfo(); // the URI path being requested
 
if (in_array($path, array('', '/'))) {
    $response = new Response('Welcome to the homepage.');
} elseif ($path == '/contact') {
    $response = new Response('Contact us');
} else {
    $response = new Response('Page not found.', Response::HTTP_NOT_FOUND);
}
$response->send();

幸運的是,這正是Symfony2被設計來解決的問題之一。

Symfony2執行流程

讓Symfony2來處理請求,開發工做就會變得簡單不少。Symfony2在每次處理,都會遵循下面的模式:

傳入的請求經路由,會由具體的控制器函數進行處理,並返回Response對象。

你網站的每一頁都被定義在路由配置文件中,在那裏不一樣的URL被映射到不一樣的PHP函數。每一個PHP函數(又名 controller)的工做就是獲得請求的信息(也可使用Symfony2中有許多其它的工具)去建立並返回一個Response對象。

就是這麼簡單,讓咱們回顧一下:

一、每一個請求執行前端控制器文件;
二、根據你的路由配置和請求信息,路由系統決定應該執行哪一個PHP函數;
三、正確的PHP函數被執行,在那裏你的代碼將建立並返回相應的Response對象。

Symfony2處理請求的實例

先不考慮太多的細節,舉一個請求處理實例。假設你要在Symfony2應用裏增長一個/contact頁面。首先,修改路由配置文件:

contact:
    pattern:  /contact
    defaults: { _controller: AcmeDemoBundle:Main:contact }

這個例子使用 YAML來定義路由的配置,你也能夠用XML或PHP來寫。

當有人訪問/contact頁時,該路由條目被匹配,同時執行指定的控制器。

你在 routing chapter 裏將會了解到,AcmeDemoBundle:Main:contact是簡寫法,指向的是MainController類裏的contactAction方法函數。

class MainController
{
    public function contactAction()
    {
        return new Response('<h1>聯繫咱們!</h1>');
    }
}

這個控制器很是簡單,僅僅建立了一個內容爲HTML「<h1>聯繫咱們!</h1>」的Response。參考controller chapter你能夠了解到控制器如何渲染模板,從而使你的「表現層」代碼能夠被寫在單獨的模板文件裏。控制器不須要考慮一些複雜的工做,如:讀寫數據庫,處理由用戶提交的數據,發送電子郵件等。

Symfony2讓你構建應用,而不是寫工具

如今你知道任何應用的目的都是處理傳入的請求,建立相應的響應。當應用程序的規模逐漸增加,要保持代碼的結構和易維護性就變得愈來愈困難。畢竟,有不少事情是你不得不反覆作的:寫數據庫,渲染和重用模板,處理表單提交,發送電子郵件,驗證用戶的輸入和保證安全性。

好消息是,這些事情都不是發射神舟飛船,並不特殊。Symfony2提供了你構建應用所需的幾乎所有工具,因此你能夠專心於創造應用,而不是「從新發明輪子」。Symfony2還有一點值得表揚,就是你能夠選擇是使用整個框架,仍是隻使用它部分的功能。

獨立的工具:Symfony2的組件

那Symfony2到底是什麼?首先,Symfony2是一個由20多個獨立的開發庫組成的工具集,你能夠在任何PHP項目裏使用這些代碼。這些開發庫,被稱做Symfony2組件,功能涵蓋了絕大部分的開發需求。舉一些例子:

  • HttpFoundation – 包含Request和 Response相關的類,以及處理會話和文件上傳的類;
  • Routing – 強大、快速的URL路由系統,你能夠指定對於特定的URI(如:/contact),請求該如何處理(如:執行contactAction()方法);
  • Form – 一個靈活的、全功能的建立表單和處理表單提交的框架;
  • Validator - 建立數據規則,並能夠驗證數據(不只是用戶提交的數據)是否符合所創規則的系統;
  • ClassLoader – 類的自動加載器,無需在使用PHP類時寫require來包含對應的源文件;
  • Templating – 一個渲染模板、處理模板繼承關係(即模板嵌套)和執行其餘通用模板任務的工具包;
  • Security – 一個功能強大的,能處理應用程序內全部安全任務的庫;
  • Translation – 一個用來翻譯應用程序內字符串的框架。

每個組件都是獨立的,可用於任何PHP項目中,而無論你是否使用了Symfony2框架。它們的每個既能夠在須要時使用,也能夠在必要時被替換。

完整的解決方案:Symfony2框架

那麼,什麼Symfony2框架呢?Symfony2框架是個PHP庫,它實現兩個功能:

  1. 提供經選擇的組件(如:Symfony2組件)和第三方庫(如:用Swiftmailer發送電子郵件);
  2. 提供合理的配置以及將這一切都粘合起來的「膠水」庫。

這個框架的目標是整合許多獨立的工具,以期給開發人員一致的體驗。甚至就連Symfony2框架自己也是一個Bundle(相似插件),在必要時也能夠被從新配置甚至替換掉。

Symfony2爲快速開發應用程序提供了強大的工具集,普通用戶能夠經過Symfony2的發行版(缺省提供了合理的項目架構)迅速上手,對於更高級的用戶而言,只有想不到,沒有作不到(The sky is the limit.)。

相關文章
相關標籤/搜索