創建你的第一個Symfony頁面
建立一個新頁面- 無論是HTML或JSON輸出- 都是一個簡單的「兩個步驟」操作:
##建立一個路由:路由(route)是一個指向你的頁面URL(例如/about
),同時映射到一個控制器。
建立一個控制器##:控制器( controller)是你為了構造頁面而寫的功能。你要拿到傳送來的請求請求訊息,用它建立一個Symfony的Response
對象,令其包含HTML內容,JSON字串或是其他
如同在網路上每一次互動都是從HTTP請求開始,你的任務單純而簡單:理解請求,回傳回應。
建立一個頁面:路由與控制器 ¶
在開始之前,確保你已經閱讀了安裝和設定Symfony 章節,同時已經可以存取瀏覽器中的Symfony程式。
假設你要新一個/lucky/number頁面,用於產生一個隨機的幸運數字並且輸出它。那麼,要先建立一個類別並新增方法,用於在某人存取/lucky/number
時執行:#
// src/AppBundle/Controller/LuckyController.phpnamespace AppBundle\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Symfony\Component\HttpFoundation\Response; class LuckyController{
/**
* @Route("/lucky/number")
*/
public function numberAction()
{
$number = rand(0, 100); return new Response(
'<html><body>Lucky number: '.$number.'</body></html>'
);
}}
#在開始之前測試一下
http:// localhost:8000 / lucky / number
Apache或Nginx#上正確設定了虛擬主機,就可以把http:// localhost:8000部分替換為自己的主機名,例如
http://symfony.dev/app_dev.php/lucky/number。
#
如果你看到一個幸運數字被輸出,那麼恭喜你!不過在玩樂透之前,先了解它是如何運作的。
numberAction
上的@Route
被稱為註解#,它定義了URL符合。你也可以在YAML(或其他格式)寫路由:請參考路由##章節。實際上,文件中的多數路由例程都有“標籤”,以顯示每種格式的配置
註解下面的方法- numberAction- 被稱為控制器,這是你控制頁面的地方。這個唯一的原則是:一個控制器必須回傳一個Symfony的 回應物件(你最終將學習到活用這個原則)。
建立一個JSON回應 ¶
在控制器中傳回的Response物件可以包含HTML,JSON甚至二進位檔案例如圖片或PDF。你可以輕鬆設定HTTP頭資訊或HTTP狀態碼。
假設你要建立一個JSON回傳值,則只需要##LuckyController
再新增一個方法:
// src/AppBundle/Controller/LuckyController.php // ...class LuckyController{ // ... /** * @Route("/api/lucky/number") */ public function apiNumberAction() { $data = array( 'lucky_number' => rand(0, 100), ); return new Response( json_encode($data), 200, array('Content-Type' => 'application/json') ); }}
#在瀏覽器中測試
http:// localhost:8000 / api / lucky / number
##你更可將程式碼精簡為超好用的JsonResponse:
// src/AppBundle/Controller/LuckyController.php // ...// --> don't forget this new use statement 别忘了这行新的use声明use Symfony\Component\HttpFoundation\JsonResponse; class LuckyController{ // ... /** * @Route("/api/lucky/number") */ public function apiNumberAction() { $data = array( 'lucky_number' => rand(0, 100), ); // calls json_encode and sets the Content-Type header // 自动调用json_encode并设置Content-Type头 return new JsonResponse($data); }}# ##############動態URL符合:/ lucky / number / {count} ###############¶######### #############窩,你做得很好但Symfony的路由還可以做得更多假設你希望用戶可以到#######! #########/lucky/number/5#########來立即產生幸運數字5,更新路由,在使其擁有尾部一個#########{ wildcard}#########通配符:#########
注释:// src/AppBundle/Controller/LuckyController.php // ...class LuckyController{ /** * @Route("/lucky/number/{count}") */ public function numberAction() { // ... } // ...}
YAML:# app/config/routing.ymllucky_number: path: /lucky/number/{count} defaults: { _controller: AppBundle:Lucky:number }
XML:<!-- app/config/routing.xml --><?xml version="1.0" encoding="UTF-8" ?><routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> <route id="lucky_number" path="/lucky/number/{count}"> <default key="_controller">AppBundle:Lucky:number</default> </route></routes>
PHP:// app/config/routing.phpuse Symfony\Component\Routing\RouteCollection;use Symfony\Component\Routing\Route; $collection = new RouteCollection();$collection->add('lucky_number', new Route('/lucky/number/{count}', array( '_controller' => 'AppBundle:Lucky:number',))); return $collection;
因為{count}
佔位符,頁面URL變成不一樣了。現在它要求URL匹配/lucky/number/*
#,例如/lucky/number/5
#。這樣一來你可以在控制器中收到並使用這個值:
// src/AppBundle/Controller/LuckyController.php// ... class LuckyController{ /** * @Route("/lucky/number/{count}") */ public function numberAction($count) { $numbers = array(); for ($i = 0; $i < $count; $i++) { $numbers[] = rand(0, 100); } $numbersList = implode(', ', $numbers); return new Response( '<html><body>Lucky numbers: '.$numbersList.'</body></html>' ); } // ...}
#去/lucky/number/ xx
測試一下,把xx換成# 任意## 數字:
http:// localhost:8000 / api / lucky / number / 7
#你應該看到幸運數字7被輸出!在控制器中增加一個$placeholder參數,你就可以得到路由中任何一個##{placeholder}
佔位符的值只要確保它們的名字相同即可。
系統-路由也可以做更多#,像是支援多個佔位符(例如/blog/{category}/{page}),令佔位符可選以及強制佔位符匹配一個正規表示式(例如
{count}必須為數字)。
在
#章節中尋找更多,即可成為路由專家。
渲染模板(利用容器) ¶ ##如果你在控制器中回傳HTML,你可能需要渲染模板。幸運的是,Symfony擁有Twig:一種易學的模板語言,強大卻相當有趣。
目前,
LuckyController#沒有繼承任何基底類別。此時引用Twig(或其他Symfony工具)最簡單的方式,就是繼承Symfony的Controller##基底類別:
// src/AppBundle/Controller/LuckyController.php // ... // --> add this new use statement use Symfony\Bundle\FrameworkBundle\Controller\Controller; class LuckyController extends Controller { // ...}#########使用模板服務 ############¶############
這些並不會改變任何東西,但把你帶入Symfony的#容器/容器 :這是一個數組模樣的對象,允許你從中取出系統級的#每一個##有用對象這些有用的物件稱為服務(服務) ,其中Symfony送出了一個專門用於渲染範本的服務對象,還有一個用來記錄日誌的,以及許多許多。
渲染Twig模板,要求到的服務名稱為templating:
// src/AppBundle/Controller/LuckyController.php // ...class LuckyController extends Controller{ /** * @Route("/lucky/number/{count}") */ public function numberAction($count) { // ... $numbersList = implode(', ', $numbers); $html = $this->container->get('templating')->render( 'lucky/number.html.twig', array('luckyNumberList' => $numbersList) ); return new Response($html); } // ...}
#「服務容器」十分重要,學習過程中你會掌握大量相關知識。現在,你只需了解它擁有很多對象,然後你可以通過「暱稱」(例如templating或logger
)利用get()
#來得到其中的任何一個。 templating
服務,是#TwigEngine
的實例,裡面有個 render()
方法。
但還可以再簡單一點!透過繼承Controller基類,你可以使用很多快捷方法,例如render()
:
// src/AppBundle/Controller/LuckyController.php // .../** * @Route("/lucky/number/{count}") */public function numberAction($count){ // ... /* $html = $this->container->get('templating')->render( 'lucky/number.html.twig', array('luckyNumberList' => $numbersList) ); return new Response($html); */ // render: a shortcut that does the same as above 快捷方法 return $this->render( 'lucky/number.html.twig', array('luckyNumberList' => $numbersList) ); }關於控制器中的快速方法是如何運作的請參閱控制器章節。
進階使用者請參考#如何定義控制器為服務 。
建立範本 ¶
#如果你現在重新整理頁面,會得到一個報錯:
#無法找到範本「lucky / number.html.twig」
修復它要靠建立一個新的app/Resources/views/lucky
目錄,再將number.html.twig
都置於其中:
枝条:{# app/Resources/views/lucky/number.html.twig #} {% extends 'base.html.twig' %} {% block body %} <h1>Lucky Numbers: {{ luckyNumberList }}</h1> {% endblock %}
PHP:<!-- app/Resources/views/lucky/number.html.php --> <?php $view->extend('base.html.php') ?> <?php $view['slots']->start('body') ?> <h1>Lucky Numbers: <?php echo $view->escape($luckyNumberList) ?> <?php $view['slots']->stop() ?>
Twig歡迎你!這個簡單的檔案已經展示了基本功能:像是{{ variableName }}
語法被用來列印一些東西。而luckyNumberList
這個變數就是你在控制器中的render()
方法中將其傳遞進來。
% extends 'base.html.twig' %
對應的是一個佈局文件,它們位於app / Resources / views / base.html.twig#,這個檔案隨Symfony專案的建立而存在。它相當地#單純(只是一個未經樣式處理的HTML結構),供你自訂。 {% block body %}
部分則是使用了嫩枝模板的##繼承系統/繼承系統,將來的其間置於內容父模板base.html.twig佈局中的對應位置。
立即重新整理頁面
#http:// localhost:8000 / lucky / number / 9
#如果你查看頁面原始碼,你會看到完整的HTML骨架,多虧了#base.html.twig。
這只是Twig威力的極小部分。若你希望精通Twig的語法,數組循環,輸出其他模板甚至更多超酷功能,應該參閱創建並使用模板。
瀏覽整個專案 #¶
你已經創建了一個彈性的URL,渲染了一個「使用了繼承功能」的模板,並且輸出了JSON回應。
是時候瀏覽你的專案中的檔案並且去掉它們的神秘光環了。之前你已經在兩個極為重要的資料夾中進行作業:
#app/
內容設定檔和範本。大體上,只要不是# PHP程式碼的材質都放在這裡。
src/
#
你的PHP程式之所在99%的時間你都會工作在src/
(PHP檔案)或app/
(其他東東)之下。隨著你的技術實力高大上起來,你會學到每個文件夾下都發生了什麼事。
app/
目錄也存在其他內容,app/AppKernel.php
像是,你要用它來開啟新捆綁(它是app/
#下面很少的PHP檔案之一)。
src/
目錄下暫時只有一個目錄- src/AppBundle
- 所有的東西都在這裡面。一個包,像一個“插件”,你可以找到開源捆綁#,然後把它們安裝到你的專案中,但就算是你自己的程式碼,也是處理束之中- 典型的就是AppBundle(儘管這捆毫無特殊之處)。為了深入了解捆綁,以及為何你應該建立多個捆綁(提示:在專案之間共用程式碼),請參閱Bundle系統章節。
那麼專案中的其他資料夾又是什麼情況呢?
web/
#它是整個專案的文檔根目錄,存在可公開訪問的文件,例如CSS,圖片以及用於執行應用程式(app_dev.php
和app.php
)的Symfony的前端控制器(前端控制器)。
tests/
#你程式的自動測試(如單元測試/單元測試)被存放在這裡。
bin/
#是用來存放二進位(binary)檔案。最重要的是console
文件,它被用來控制中執行Symfony指令。
var/
#這是那些自動產生的檔案被存放的地方,例如快取檔案(var/cache/
)和日誌檔案(var/logs/
)。
vendor/
透過依賴管理器Composer,第三方類別庫,包,bundles被下載到這裡。你應該不去編輯這個目錄下的東西。
Symfony是彈性化的。如果需要,你可以覆寫預設的目錄結構。參考如何覆寫Symfony的預設#目錄結構。
程式層級的設定 ¶
#Symfony內建了幾款原生束(打開你的app/AppKernel.php
#檔案檢視),你可以安裝更多.bundles的主要設定檔是 app/config/config.yml
:
YAML:# app/config/config.yml # ...framework: secret: '%secret%' router: resource: '%kernel.root_dir%/config/routing.yml' # ...twig: debug: '%kernel.debug%' strict_variables: '%kernel.debug%' # ...
XML:<!-- app/config/config.xml --><?xml version="1.0" encoding="UTF-8" ?><container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:framework="http://symfony.com/schema/dic/symfony" xmlns:twig="http://symfony.com/schema/dic/twig" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd http://symfony.com/schema/dic/twig http://symfony.com/schema/dic/twig/twig-1.0.xsd"> <!-- ... --> <framework:config secret="%secret%"> <framework:router resource="%kernel.root_dir%/config/routing.xml" /> <!-- ... --> </framework:config> <!-- Twig Configuration --> <twig:config debug="%kernel.debug%" strict-variables="%kernel.debug%" /> <!-- ... --></container>
PHP:// app/config/config.php// ... $container->loadFromExtension('framework', array( 'secret' => '%secret%', 'router' => array( 'resource' => '%kernel.root_dir%/config/routing.php', ), // ...)); // Twig Configuration$container->loadFromExtension('twig', array( 'debug' => '%kernel.debug%', 'strict_variables' => '%kernel.debug%',)); // ...
framework
##根鍵配置的是FrameworkBundle,twig根鍵配置的是TwigBundle,諸如此類.Symfony中的許多行為都可以被控制,只需改變設定檔的一些選項即可。要搞清原因,請閱讀配置參考。
或者,透過超好用的#bin/console指令,取得一個根鍵下被剝離出的完整配置樣板:
$ php bin/console config:dump-reference framework
Symfony配置系統的威力絕大,包括環境,導入和參數等。為了掌握所有這些,參考配置#章節。
下一步? ¶
#恭喜你!你已經開始掌握Symfony,並將學到以全新方式來打造美麗的,功能性的,快速的,可維護的程序。
好了,你還需要熟悉下面這些章節,才能完成對基礎架構的掌握:
#控制器
##建立並使用範本
#然後,在#中文書,也要學習#服務容器, 表單系統,使用Doctrine (如果你需要查詢資料庫的話)以及更多! #
還有一本中文食譜#,打包了更深的「如何」文章以解決更多#問題。
祝各位學得高興!