您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“Symfony2中模板怎么用”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Symfony2中模板怎么用”這篇文章吧。
具體如下:
我們知道,controller負(fù)責(zé)處理每一個(gè)進(jìn)入Symfony2應(yīng)用程序的請(qǐng)求。實(shí)際上,controller把大部分的繁重工作都委托給了其它地方,以使代碼能夠被測(cè)試和重用。當(dāng)一個(gè)controller需要生成HTML,CSS或者其他內(nèi)容時(shí),它把這些工作給了一個(gè)模板化引擎。
模板:
一個(gè)模板僅僅是一個(gè)文本文件,它能生成任意的文本格式(HTML,XML,CSV,LaTex...)。最著名的模板類(lèi)型就是PHP模板了,可以被PHP解析的文本文件,它混合了文本和PHP代碼。
<!DOCTYPE html> <html> <head> <title>Welcome to Symfony!</title> </head> <body> <h2><?php echo $page_title ?></h2> <ul id="navigation"> <?php foreach ($navigation as $item): ?> <li> <a href="<?php echo $item->getHref() ?>"> <?php echo $item->getCaption() ?> </a> </li> <?php endforeach; ?> </ul> </body> </html>
但是Symfony2包中擁有一種更加強(qiáng)大的模板化語(yǔ)言叫Twig。 它允許你寫(xiě)簡(jiǎn)潔,可讀法模板語(yǔ)言。對(duì)頁(yè)面設(shè)計(jì)師更友好,在許多方面比PHP模板更加強(qiáng)大。
<!DOCTYPE html> <html> <head> <title>Welcome to Symfony!</title> </head> <body> <h2>{{ page_title }}</h2> <ul id="navigation"> {% for item in navigation %} <li><a href="{{ item.href }}">{{ item.caption }}</a></li> {% endfor %} </ul> </body> </html>
在這個(gè)Twig文件中,定義了三個(gè)類(lèi)型的特別語(yǔ)法
{{...}} : "說(shuō)某些事", 打印一個(gè)變量或者一個(gè)表達(dá)式的值到模板。
{%...%} : "做某些事",控制模板邏輯的標(biāo)簽,它用于執(zhí)行比如for循環(huán)語(yǔ)句等。
{# 這是一個(gè)注釋 #}, "注釋"。
Twig也包含filters,在渲染之前修改內(nèi)容。下面的語(yǔ)句顯示把title變量全部渲染為大型。
{{ title|upper }}
Twig默認(rèn)情況下有一大群的標(biāo)簽(tags)和過(guò)濾器(filters)可以使用。當(dāng)然你也可以根據(jù)需要添加擴(kuò)展。注冊(cè)一個(gè)Twig擴(kuò)展非常容易,創(chuàng)建一個(gè)新服務(wù)并把它標(biāo)記為T(mén)wig.extension 標(biāo)簽。就跟你看到的一樣,Twig也支持功能和新功能的添加。比如,下面使用一個(gè)標(biāo)準(zhǔn)的for標(biāo)簽和cycle功能函數(shù)來(lái)打印10個(gè)div 標(biāo)簽,用odd,even 類(lèi)代替。
{% for i in 0..10 %} <div alss="{{ cycle(['odd','even'],i) }}"> <!--一些其它HTML --> </div> {% emdfor %}
Twig模板緩存
Twig很快。 每個(gè)Twig模板被編譯到原生的PHP類(lèi),它將在運(yùn)行時(shí)被渲染。編譯過(guò)的類(lèi)被保存在app/cache/{environment}/twig 目錄下并在某些情況下,對(duì)整個(gè)調(diào)試非常有用。當(dāng)debug模式可用時(shí),一個(gè)twig模板如果發(fā)生改變將會(huì)被自動(dòng)重新編譯。這就意味著你可以在開(kāi)發(fā)過(guò)程中隨意的修改模板,而不必?fù)?dān)心需要去清除內(nèi)存了。當(dāng)debug模式被關(guān)閉時(shí),你必須手動(dòng)的清除Twig緩存目錄,以便能夠重新生成Twig模板。
模板繼承和布局
大多數(shù)的時(shí)候,模板在項(xiàng)目中用來(lái)共享通用的元素,比如header,footer,sidebar等等。在Symfony2中,我們將采用不同的思考角度來(lái)對(duì)待這個(gè)問(wèn)題。一個(gè)模板可以被另外的模板裝飾。這個(gè)的工作原理跟PHP類(lèi)非常像,模板繼承讓你可以創(chuàng)建一個(gè)基礎(chǔ)"layout"模板,它包含你的站點(diǎn)的所有通用元素并被定義成blocks。這里的block可以類(lèi)比為PHP基類(lèi)的方法。 一個(gè)字模板可以繼承基礎(chǔ)layout模板并重寫(xiě)它任何一個(gè)block。
現(xiàn)在首先創(chuàng)建一個(gè)base layout文件:
Twig:
{# app/Resources/views/base.html.twig #} <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>{% block title %}Test Application{% endblock %}</title> </head> <body> <div id="sidebar"> {% block sidebar %} <ul> <li><a href="/">Home</a></li> <li><a href="/blog">Blog</a></li> </ul> {% endblock %} </div> <div id="content"> {% block body %}{% endblock %} </div> </body> </html>
PHP代碼格式:
<!-- app/Resources/views/base.html.php --> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title><?php $view['slots']->output('title', 'Test Application') ?></title> </head> <body> <div id="sidebar"> <?php if ($view['slots']->has('sidebar')): ?> <?php $view['slots']->output('sidebar') ?> <?php else: ?> <ul> <li><a href="/">Home</a></li> <li><a href="/blog">Blog</a></li> </ul> <?php endif; ?> </div> <div id="content"> <?php $view['slots']->output('body') ?> </div> </body> </html>
這個(gè)模板定義了基本的HTML初始文檔是一個(gè)簡(jiǎn)單的兩列式頁(yè)面。在這個(gè)頁(yè)面中有三處{% block %}定義,分別定義了title,sidebar和body。每個(gè)block都可以被繼承它的子模板重寫(xiě)或者保留它現(xiàn)在的默認(rèn)實(shí)現(xiàn)。該模板也能被直接渲染,只不過(guò)只是顯示基礎(chǔ)模板的定義內(nèi)容。
下面定義一個(gè)子模板:
Twig格式:
{# src/Acme/BlogBundle/Resources/views/Blog/index.html.twig #} {% extends '::base.html.twig' %} {% block title %}My cool blog posts{% endblock %} {% block body %} {% for entry in blog_entries %} <h3>{{ entry.title }}</h3> <p>{{ entry.body }}</p> {% endfor %} {% endblock %}
PHP代碼格式:
<!-- src/Acme/BlogBundle/Resources/views/Blog/index.html.php --> <?php $view->extend('::base.html.php') ?> <?php $view['slots']->set('title', 'My cool blog posts') ?> <?php $view['slots']->start('body') ?> <?php foreach ($blog_entries as $entry): ?> <h3><?php echo $entry->getTitle() ?></h3> <p><?php echo $entry->getBody() ?></p> <?php endforeach; ?> <?php $view['slots']->stop() ?>
父模板被一個(gè)特殊的字符串語(yǔ)法表示 ::base.html.twig ,它表示該模板在項(xiàng)目的 app/Resources/views 目錄下。
模板繼承的關(guān)鍵字 {% extends %}標(biāo)簽。 該標(biāo)簽告訴模板化引擎首先評(píng)估父模板,它會(huì)設(shè)置布局和定義多個(gè)blocks。然后是子模板,上例中父模板中定義的title和body 兩個(gè)blocks將會(huì)被子模板中的定義所取代。依靠blog_entries的值,輸出的內(nèi)容如下:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>My cool blog posts</title> </head> <body> <div id="sidebar"> <ul> <li><a href="/">Home</a></li> <li><a href="/blog">Blog</a></li> </ul> </div> <div id="content"> <h3>My first post</h3> <p>The body of the first post.</p> <h3>Another post</h3> <p>The body of the second post.</p> </div> </body> </html>
在此我們注意到,因?yàn)樽幽0逯袥](méi)有定義sidebar這個(gè)block,所以來(lái)自父模板的內(nèi)容被顯示出來(lái),而沒(méi)有被子模板替代。位于父模板中的{% block %}標(biāo)簽是默認(rèn)值,如果沒(méi)有被子模板重寫(xiě)覆蓋,它將作為默認(rèn)值使用。
你可以根據(jù)你的需要進(jìn)行多層繼承。 Symfony2項(xiàng)目中一般使用一種三層繼承模式來(lái)組織模板和頁(yè)面。當(dāng)我們使用模板繼承時(shí),需要注意:
如果在模板中使用{% extends %},那么它必須是模板的第一個(gè)標(biāo)簽。
你基礎(chǔ)模板中{% block %}越多越好,記住,子模板不必等一父模板中所有的block。你父模板中block定義的越多,你的布局就越靈活。
如果你發(fā)現(xiàn)在多個(gè)模板中有重復(fù)的內(nèi)容,這可能就意味著你需要為該內(nèi)容在父模板中定義一個(gè){% block %}。有些時(shí)候更好的解決方案可能是把這些內(nèi)容放到一個(gè)新模板中,然后在該模板中include它。
如果你需要從父模板中獲取一個(gè)block的內(nèi)容,你可以使用{{ parent() }}函數(shù)。
{% block sidebar %} <h4>Table of Contents</h4> ... {{ parent() }} {% endblock %}
模板的命名和存儲(chǔ)位置
默認(rèn)情況下,模板可以被保存到兩個(gè)位置:
app/Resources/views 目錄下,可以存放整個(gè)應(yīng)用程序級(jí)的基礎(chǔ)模板以及那些重寫(xiě)bundle模板的模板。
path/to/bundle/Resources/views 目錄下,每個(gè)bundle自己的模板。
Symfony2使用bundle:controller:template 字符串語(yǔ)法表示模板。這可以表示許多不同類(lèi)型的模板,每種都存放在特定的路徑下:
AcmeBlogBundle:Blog:index.html.twig 用于指定一個(gè)特定頁(yè)面的模板。
AcmeBlogBundle 表示bundle,說(shuō)明模板位于AcmeBlogBundle,比如src/Acme/BlogBundle。
Blog 表示BlogController,指定模板位于Resourcs/views的Blog子目錄中,index.html.twig為模板名字。
假設(shè)AcmeBlogBundle位于src/Acme/BlogBundle, 最終的路徑將是:src/Acme/BlogBundle/Resources/views/Blog/index.html.twig
AcmeBlogBundle::layout.html.twig 該表示法指向AcmeBlogBundle的基模板。沒(méi)有controller部分,所以模板應(yīng)該位于AcmeBlogBundle的Resources/views/layout.html.twig
::base.html.twig 表示一個(gè)應(yīng)用程序級(jí)的基模板或者布局文件。注意,該語(yǔ)句兩個(gè)冒號(hào)開(kāi)頭,意味著沒(méi)有bundle和controller部分,這說(shuō)明該文件不在某個(gè)bundle中,而是位于根目錄下 app/Resources/views
在重寫(xiě)B(tài)undle模板一節(jié),你將發(fā)現(xiàn)位于AcmeBlogBundle的模板是如何被位于app/Resources/AcmeBlogBundle/views/目錄下的所有模板同名重寫(xiě)的,
這種方式給了我們一個(gè)有力的途徑來(lái)重寫(xiě)供應(yīng)商提供的bundle的模板。
模板后綴(suffix)
bundle:controller:template 句法說(shuō)明了每個(gè)模板文件的存放位置。每個(gè)模板名字也有兩個(gè)擴(kuò)展名來(lái)指定格式和模板引擎。
AcmeBlogBundle:Blog:index.html.twig HTML格式,Twig引擎
AcmeBlogBundle:Blog:index.html.php HTML格式,PHP引擎
AcmeBlogBundle:Blog:index.css.twig CSS格式,Twig引擎
默認(rèn)情況下,Symfony2的任何模板都可以被寫(xiě)成Twig或者PHP引擎的,它由后綴決定。其中后綴的前一部分(.html,.css)表示最終生成的格式。
標(biāo)簽和助手類(lèi)
你已經(jīng)基本了解了模板,它們?nèi)绾蚊绾问褂媚0謇^承等。最難理解的部分已經(jīng)過(guò)去。接下來(lái)我們將了解大量的可用工具來(lái)幫助我們執(zhí)行最通用的模板任務(wù)比如包含另外一個(gè)模板,鏈接一個(gè)頁(yè)面或者包含一個(gè)圖片等。
Symfony2 中包含了血多序列化的Twig標(biāo)簽和功能函數(shù)來(lái)幫助設(shè)計(jì)者更容易的完成工作。在PHP中,模板系統(tǒng)提供了一個(gè)可擴(kuò)展的helper系統(tǒng),它可以在模板上下文中提供許多有用的內(nèi)容。我們已經(jīng)看過(guò)一些內(nèi)建的Twig標(biāo)簽,比如{% block %}{% extends %}等,還有PHP 助手$view['slots']。
包含其它模板:
你可能經(jīng)常想在多個(gè)不同的頁(yè)面中包含同一個(gè)模板或者代碼片段。比如一個(gè)應(yīng)用程序中有"新聞文章",模板代碼在顯示一片文章時(shí)可能用到文章詳細(xì)頁(yè)面,一個(gè)現(xiàn)實(shí)最流行文章的頁(yè)面,或者一個(gè)最新文章的列表頁(yè)面等。
當(dāng)你需要重用一些PHP代碼,你通常都是把這些代碼放到一個(gè)PHP類(lèi)或者函數(shù)中。同樣在模板中你也可以這么做。通過(guò)把可重用的代碼放到一個(gè)它自己的模板中,然后把這個(gè)模板包含到其他模板中。比如我們創(chuàng)建一個(gè)可重用模板如下:
Twig格式:
{# src/Acme/ArticleBundle/Resources/views/Article/articleDetails.html.twig #} <h3>{{ article.title }}</h3> <h4 class="byline">by {{ article.authorName }}</h4> <p> {{ article.body }} </p>
PHP代碼格式:
<!-- src/Acme/ArticleBundle/Resources/views/Article/articleDetails.html.php --> <h3><?php echo $article->getTitle() ?></h3> <h4 class="byline">by <?php echo $article->getAuthorName() ?></h4> <p> <?php echo $article->getBody() ?> </p>
然后我們把它包含到其它模板定義中:
Twig格式:
{# src/Acme/ArticleBundle/Resources/Article/list.html.twig #} {% extends 'AcmeArticleBundle::layout.html.twig' %} {% block body %} <h2>Recent Articles<h2> {% for article in articles %} {% include 'AcmeArticleBundle:Article:articleDetails.html.twig' with {'article': article} %} {% endfor %} {% endblock %}
PHP代碼格式:
<!-- src/Acme/ArticleBundle/Resources/Article/list.html.php --> <?php $view->extend('AcmeArticleBundle::layout.html.php') ?> <?php $view['slots']->start('body') ?> <h2>Recent Articles</h2> <?php foreach ($articles as $article): ?> <?php echo $view->render('AcmeArticleBundle:Article:articleDetails.html.php', array('article' => $article)) ?> <?php endforeach; ?> <?php $view['slots']->stop() ?>
模板的包含使用{% include %}標(biāo)簽。模板的名稱(chēng)要使用通用方式。在articleDetails.html.twig模板中使用article變量,這里通過(guò)在list.html.twig模板中使用with命令傳入。{'article':article}語(yǔ)法是標(biāo)準(zhǔn)Twig哈希映射的寫(xiě)法。如果我們需要傳遞多個(gè)元素,可以寫(xiě)成{'foo': foo, 'bar': bar}。
嵌入Controllers
有些情況下,你需要比包含簡(jiǎn)單模板做到更多。假設(shè)你有一個(gè)菜單欄sidebar在你的布局文件中來(lái)顯示最新的文章。獲取三篇最新文章可能需要查詢(xún)數(shù)據(jù)庫(kù)或者執(zhí)行其它包含很多邏輯的操作,這樣就不能在一個(gè)模板中進(jìn)行了。這種情況的解決方案是簡(jiǎn)答鍵入一個(gè)完整的controller到你的模板。首先創(chuàng)建一個(gè)controller來(lái)渲染特定數(shù)量的最近文章:
//src/Acme/ArticleBundle/Controller/ArticleController.php class ArticleController extends Controller { public function recentArticlesAction($max = 3) { //生成一個(gè)數(shù)據(jù)庫(kù)調(diào)用或者其它邏輯來(lái)獲取$max個(gè)最新文章的代碼 $articles = ...; return $this->render('AcmeArticleBundle:Article:recentList.html.twig',array('articles'=>articles)); } }
而recentList模板則相當(dāng)簡(jiǎn)單:
Twig格式:
{# src/Acme/ArticleBundle/Resources/views/Article/recentList.html.twig #} {% for article in articles %} <a href="/article/{{ article.slug }}"> {{ article.title }} </a> {% endfor %}
PHP代碼格式:
<!-- src/Acme/ArticleBundle/Resources/views/Article/recentList.html.php --> <?php foreach ($articles as $article): ?> <a href="/article/<?php echo $article->getSlug() ?>"> <?php echo $article->getTitle() ?> </a> <?php endforeach; ?>
為了能包含controller,你需要使用一個(gè)標(biāo)準(zhǔn)的字符語(yǔ)法來(lái)表示controller,格式類(lèi)似bundle:controller:action
Twig格式:
{# app/Resources/views/base.html.twig #} ... <div id="sidebar"> {% render "AcmeArticleBundle:Article:recentArticles" with {'max': 3} %} </div>
PHP代碼格式:
<!-- app/Resources/views/base.html.php --> ... <div id="sidebar"> <?php echo $view['actions']->render('AcmeArticleBundle:Article:recentArticles', array('max' => 3)) ?> </div>
無(wú)論什么時(shí)候,你需要一個(gè)變量或者一些列信息時(shí),你不必在模板中訪(fǎng)問(wèn),而是考慮渲染一個(gè)controller。因?yàn)镃ontroller能夠更快的執(zhí)行并且很好的提高了代碼的組織和重用。
鏈接到頁(yè)面:
在你的應(yīng)用程序中創(chuàng)建一個(gè)鏈接到其它頁(yè)面對(duì)于一個(gè)模板來(lái)說(shuō)是再普通不過(guò)的事情了。我們采用path Twig函數(shù)基于路由配置來(lái)生成URL而非在模板中硬編碼URL。以后如果你想修改一個(gè)特定頁(yè)面的URL,你只需要改變路由配置即可,模板將自動(dòng)生成新的URL。比如我們打算鏈接到"_welcome"頁(yè)面,首先定義其路由配置:
YAML格式:
_welcome: pattern: / defaults: { _controller: AcmeDemoBundle:Welcome:index }
XML格式:
<route id="_welcome" pattern="/"> <default key="_controller">AcmeDemoBundle:Welcome:index</default> </route>
PHP代碼格式:
$collection = new RouteCollection(); $collection->add('_welcome', new Route('/', array( '_controller' => 'AcmeDemoBundle:Welcome:index', ))); return $collection;
我們可以在模板中使用Twig函數(shù) path來(lái)引用這個(gè)路由鏈接該頁(yè)面。
Twig格式:
<a href="{{ path('_welcome') }}">Home</a>
PHP代碼格式:
<a href="<?php echo $view['router']->generate('_welcome') ?>">Home</a>
上面的內(nèi)容會(huì)生成一個(gè)URL /
我們看另一個(gè)復(fù)雜一些的路由定義:
YAML格式:
article_show: pattern: /article/{slug} defaults: { _controller: AcmeArticleBundle:Article:show }
XML格式:
<route id="article_show" pattern="/article/{slug}"> <default key="_controller">AcmeArticleBundle:Article:show</default> </route>
PHP代碼格式:
$collection = new RouteCollection(); $collection->add('article_show', new Route('/article/{slug}', array( '_controller' => 'AcmeArticleBundle:Article:show', ))); return $collection;
這種情況下你需要指定路由名稱(chēng)(article_show)還要一個(gè)參數(shù)值{slug}。現(xiàn)在讓我們?cè)賮?lái)看上面的recentList模板 ,我們修改以前的硬編碼而使用path來(lái)鏈接正確的文章。
Twig格式:
{# src/Acme/ArticleBundle/Resources/views/Article/recentList.html.twig #} {% for article in articles %} <a href="{{ path('article_show', { 'slug': article.slug }) }}"> {{ article.title }} </a> {% endfor %}
PHP代碼格式:
<!-- src/Acme/ArticleBundle/Resources/views/Article/recentList.html.php --> <?php foreach ($articles in $article): ?> <a href="<?php echo $view['router']->generate('article_show', array('slug' => $article->getSlug()) ?>"> <?php echo $article->getTitle() ?> </a> <?php endforeach; ?>
你也可以通過(guò)url Twig函數(shù)來(lái)生成一個(gè)絕對(duì)路徑的URL:
<a href="{{ url('_welcome') }}">Home</a>
在PHP代碼模板中,你需要給generate()方法傳入第三個(gè)參數(shù)true 來(lái)實(shí)現(xiàn)生成絕對(duì)路徑URL
<a href="<?php echo $view['router']->generate('_welcome', array(), true) ?>">Home</a>
鏈接到資源
模板通常也需要一些圖片,Javascript,樣式文件和其它資產(chǎn)。當(dāng)然你可以硬編碼它們的路徑。比如/images/logo.png。 但是Symfony2 提供了一個(gè)更加動(dòng)態(tài)的Twig函數(shù) asset()。
Twig格式:
<img src="{{ asset('images/logo.png') }}" alt="Symfony!" /> <link href="{{ asset('css/blog.css') }}" rel="stylesheet" type="text/css" />
PHP代碼格式:
<img src="<?php echo $view['assets']->getUrl('images/logo.png') ?>" alt="Symfony!" /> <link href="<?php echo $view['assets']->getUrl('css/blog.css') ?>" rel="stylesheet" type="text/css" />
asset函數(shù)的主要墨筆是讓你的應(yīng)用程序更加輕便。如果你的應(yīng)用程序在你的主機(jī)根目錄下(比如:http://example.com),那么它會(huì)渲染出的路徑為 /images/logo.png 。但是如果你的應(yīng)用程序位于一個(gè)子目錄中(比如:http://example.com/my_app),這時(shí)它會(huì)為你渲染出的路徑變?yōu)?/my_app/images/logo.png 。asset函數(shù)能夠根據(jù)你的應(yīng)用程序來(lái)生成正確的路徑。
另外,如果你使用asset函數(shù),symfony可以自動(dòng)追加一個(gè)查詢(xún)字符串到你的資產(chǎn),以保證被更新的靜態(tài)資源不會(huì)在部署時(shí)被緩存。比如:/images/logo.png 可能看起來(lái)是 /images/logo.png?v2 。
包含樣式表和Javascript文件到Twig模板:
每個(gè)網(wǎng)站中都不可能缺少了樣式表和javascript文件。在Symfony中,這些內(nèi)容可以通過(guò)模板繼承很好的進(jìn)行包含處理。Symfony打包了另外一個(gè)類(lèi)庫(kù)叫做Assetic, 它允許你對(duì)這些資源做更多的有趣操作。首先在你的基模板中添加兩個(gè)blocks來(lái)保存你的資源,一個(gè)叫stylesheets,放在head標(biāo)簽里,另一個(gè)叫javascript,放在body結(jié)束標(biāo)簽上面一行。這些blocks將包含你整個(gè)站點(diǎn)所需要的所有stylesheets和javascripts。
{# 'app/Resources/views/base.html.twig' #} <html> <head> {# ... #} {% block stylesheets %} <link href="{{ asset('/css/main.css') }}" type="text/css" rel="stylesheet" /> {% endblock %} </head> <body> {# ... #} {% block javascripts %} <script src="{{ asset('/js/main.js') }}" type="text/javascript"></script> {% endblock %} </body> </html>
這太簡(jiǎn)單了!但如果你想從子模板中包含一個(gè)額外的stylesheet或者javascript怎么辦呢?比如假設(shè)你有一個(gè)聯(lián)系頁(yè)面需要包含一個(gè)contact.css樣式表只用于該頁(yè)面。在你的contact頁(yè)面模板內(nèi)部,你可以這樣實(shí)現(xiàn):
{# src/Acme/DemoBundle/Resources/views/Contact/contact.html.twig #} {% extends '::base.html.twig' %} {% block stylesheets %} {{ parent() }} <link href="{{ asset('/css/contact.css') }}" type="text/css" rel="stylesheet" /> {% endblock %} {# ... #}
在子模板中你只需要重寫(xiě)stylesheets block并把你新的樣式表標(biāo)簽放到該塊里。當(dāng)然因?yàn)槟阆胩砑拥礁改0逶搲K內(nèi)容中,而不是替代它們所以你需要在此之前
先使用parent()函數(shù)來(lái)獲取父模板中的所有stylesheets。你也可以包含資源位置到你的bundle的Resources/public 文件夾。你需要執(zhí)行如下命令行:
$php app/console assets:install target [--symlink]
它會(huì)把文件移動(dòng)到正確的位置,默認(rèn)情況下的目標(biāo)位置是web文件夾。
<link href="{{ asset('bundles/acmedemo/css/contact.css') }}" type="text/css" rel="stylesheet" />
上面代碼最終結(jié)果是頁(yè)面會(huì)包含main.css和contact.css樣式表。
全局模板變量
在每個(gè)請(qǐng)求中,Symfony2 將會(huì)在Twig引擎和PHP引擎默認(rèn)設(shè)置一個(gè)全局模板變量app。該app變量是一個(gè)GlobalVariables實(shí)例,它將讓你自動(dòng)訪(fǎng)問(wèn)到應(yīng)用程序一些特定能夠的變量。比如:
app.security 安全上下文
app.user 當(dāng)前用戶(hù)對(duì)象
app.request 當(dāng)前Request對(duì)象
app.session Session對(duì)象
app.environment 當(dāng)前應(yīng)用程序的環(huán)境(dev,prod等)
app.debug 如果是true說(shuō)明是調(diào)試模式,false則不是。
當(dāng)然,你也可以向其添加你自己的全局模板變量。其應(yīng)用示例:
Twig格式:
<p>Username: {{ app.user.username }}</p> {% if app.debug %} <p>Request method: {{ app.request.method }}</p> <p>Application Environment: {{ app.environment }}</p> {% endif %}
PHP代碼格式:
<p>Username: <?php echo $app->getUser()->getUsername() ?></p> <?php if ($app->getDebug()): ?> <p>Request method: <?php echo $app->getRequest()->getMethod() ?></p> <p>Application Environment: <?php echo $app->getEnvironment() ?></p> <?php endif; ?>
配置和使用templating 服務(wù)
Symfony2模板系統(tǒng)的核心是模板化引擎。這個(gè)特殊的對(duì)象負(fù)責(zé)渲染模板并返回他們正確的內(nèi)容。當(dāng)你在controller中渲染一個(gè)模板時(shí),其實(shí)你是使用了模板化引擎服務(wù),比如:
return $this->render('AcmeArticleBundle:Article:index.html.twig');
其實(shí)相當(dāng)于:
$engine = $this->container->get('templating'); $content = $engine->render('AcmeArticleBundle:Article:index.html.twig'); return $response = new Response($content);
該模板化引擎服務(wù)在Symfony2內(nèi)部是預(yù)先配置好自動(dòng)工作的。當(dāng)然它也可以在應(yīng)用程序的配置文件中進(jìn)行配置。比如:
YAML格式:
# app/config/config.yml framework: # ... templating: { engines: ['twig'] }
XML格式:
<!-- app/config/config.xml --> <framework:templating> <framework:engine id="twig" /> </framework:templating>
PHP代碼格式:
// app/config/config.php $container->loadFromExtension('framework', array( // ... 'templating' => array( 'engines' => array('twig'), ), ));
重寫(xiě)B(tài)undle模板:
Symfony2社群現(xiàn)在正為他們創(chuàng)建和維護(hù)了很多不同內(nèi)容的高質(zhì)量的Bundle而感到驕傲,一旦你使用第三方的bundle你可能想重寫(xiě)或者個(gè)性化它們的一個(gè)或者多個(gè)模板。假設(shè)你已經(jīng)包含了開(kāi)源AcmeBlogBundle到你的項(xiàng)目中,比如目錄是src/Acme/BlogBundle,你想重寫(xiě)blog列表(list)頁(yè)面來(lái)按照你自己的應(yīng)用程序風(fēng)格個(gè)性化它。我們打開(kāi)AcmeBlogBundle的Blog controller,可以發(fā)現(xiàn)如下內(nèi)容:
public function indexAction() { $blogs = // some logic to retrieve the blogs $this->render('AcmeBlogBundle:Blog:index.html.twig', array('blogs' => $blogs)); }
當(dāng)AcmeBlogBundle:Blog:index.html.twig被渲染時(shí),Symfony2 會(huì)查找兩個(gè)位置來(lái)定位模板:
1. app/Resources/AcmeBlogBundle/views/Blog/index.html.twig
2. src/Acme/BlogBundle/Resources/views/Blog/index.html.twig
要重寫(xiě)該bundle的模板,僅僅從bundle中拷貝index.html.twig 模板到app/Resources/AcmeBlogBundle/views/Blog/index.html.twig。
注意,如果app/Resources/AcmeBlogBundle目錄不存在,可以手工建立。之后你就可以隨心所欲的個(gè)性化處理該模板了。
該邏輯同樣適用于基bundle模板,假設(shè)AcmeBlogBundle中每個(gè)模板都是繼承于基模板AcmeBlogBundle::layout.html.twig。Symfony2 將從下面兩個(gè)地方尋找模板:
1.app/Resources/AcmeBlogBundle/vews/layout.html.twig
2.src/Acme/BlogBundle/Resources/views/layout.html.twig
同樣的,如果要重寫(xiě)該模板,你僅僅需要從bundle中拷貝到app/Resources/AcmeBlogBundle/views/layout.html.twig 就可以輕松個(gè)性化它了。你也可以通過(guò)bundle繼承來(lái)從bundle內(nèi)部重寫(xiě)模版。
重寫(xiě)核心模板:
因?yàn)镾ymfony2 框架本身就是一個(gè)bundle,所以其核心模板也可以按照同樣的方式進(jìn)行重寫(xiě)。比如,核心模板TwigBundle包含很多不同"execption"和"error" 的模板,你可以通過(guò)從Resources/views/Exception 目錄下每一項(xiàng)到app/Resources/TwigBundle/Views/Exception 目錄下 。
三級(jí)繼承:
Symfony2中一般采用三級(jí)繼承來(lái)完成模板創(chuàng)建。它使用三種不同類(lèi)型的模板:
首先,創(chuàng)建一個(gè)app/Resources/views/base.html.twig 文件,它包含你應(yīng)用程序主要的布局,該模板被調(diào)用時(shí)寫(xiě)成 ::base.html.twig。
然后,為你站點(diǎn)的每個(gè)部分section創(chuàng)建一個(gè)模板。比如一個(gè)AcmeBlogBundle, 它有自己的一個(gè)模板AcmeBlogBundle::layout.html.twig。該模板只包含特定的元素,比如body。
{# src/Acme/BlogBundle/Resources/views/layout.html.twig #} {% extends '::base.html.twig' %} {% block body %} <h2>Blog Application</h2> {% block content %}{% endblock %} {% endblock %}
最后,是為每個(gè)頁(yè)面創(chuàng)建一個(gè)單獨(dú)的模板并繼承合適的section模板。比如,為index頁(yè)創(chuàng)建的模板 AcmeBlogBundle:Blog:index.html.twig 用來(lái)列出所有的blog。
{# src/Acme/BlogBundle/Resources/views/Blog/index.html.twig #} {% extends 'AcmeBlogBundle::layout.html.twig' %} {% block content %} {% for entry in blog_entries %} <h3>{{ entry.title }}</h3> <p>{{ entry.body }}</p> {% endfor %} {% endblock %}
注意該模板是繼承了section模板(AcmeBlogBundle:layout.html.twig),而section模板又繼承了應(yīng)用程序基模板(::base.html.twig)。這就是通常說(shuō)的三級(jí)繼承模式。
在你創(chuàng)建你的應(yīng)用程序時(shí),你可以選擇這種模式,也可以為每個(gè)頁(yè)面創(chuàng)建模板時(shí)直接繼承應(yīng)用程序的基模板(比如: {% extends '::base.html.twig' %} 。
三模板模式對(duì)于一個(gè)bundle開(kāi)發(fā)商來(lái)說(shuō)是最好的方法,因?yàn)檫@樣bundle使用者可以很容易的重寫(xiě)bundle的基模板來(lái)適合自己應(yīng)用程序的基本布局。
安全輸出轉(zhuǎn)換:
當(dāng)我們從模板中生成HTML時(shí),總會(huì)有風(fēng)險(xiǎn)存在,比如一些模板變量可能輸出一些意外的HTML或者危險(xiǎn)的客戶(hù)端代碼。結(jié)果這些動(dòng)態(tài)內(nèi)容會(huì)打破結(jié)果頁(yè)面的HTML或者允許一些惡意的訪(fǎng)問(wèn)者執(zhí)行一些頁(yè)面攻擊。舉個(gè)例子:
Twig格式:
Hello {{ name }}
PHP代碼格式:
Hello <?php echo $name ?>
想象一下用戶(hù)輸入下面的代碼作為他們的name時(shí),結(jié)果會(huì)是什么?
<script>alert('hello!')</script>
沒(méi)有任何的輸出安全轉(zhuǎn)義,結(jié)果模板會(huì)觸發(fā)JavaScript彈出框:
Hello <script>alert('hello!')</script>
這種情況看上去,沒(méi)多大害處,如果一個(gè)用戶(hù)知道這一步,它完全有能力寫(xiě)一個(gè)javascript在我們未知的安全區(qū)域來(lái)執(zhí)行一些惡意行為。這個(gè)問(wèn)題的解決辦法是輸出安全轉(zhuǎn)義。 如果添加了輸出安全轉(zhuǎn)義,同樣的模板會(huì)渲染出無(wú)害的內(nèi)容,script標(biāo)簽會(huì)作為普通文本輸出到屏幕上。
Hello <script>alert('helloe')</script>
PHP和Twig模板化系統(tǒng)采用了不同的方式來(lái)解決這個(gè)問(wèn)題。如果你使用Twig,默認(rèn)情況下是輸出安全轉(zhuǎn)義的,你的輸出是受到保護(hù)的。如果是PHP,則輸出安全轉(zhuǎn)義不是自動(dòng)的,需要你手工的進(jìn)行處理。
Twig中的安全輸出
如果你使用Twig模板,那么輸出安全是默認(rèn)的。你不需要對(duì)用戶(hù)提交的輸出內(nèi)容進(jìn)行手動(dòng)保護(hù)。在某些情況下,你需要關(guān)閉輸出安全保護(hù),當(dāng)你渲染某個(gè)可信變量或者包含某個(gè)標(biāo)簽時(shí)。假設(shè)管理員用戶(hù)可以編寫(xiě)一些代碼有HTML標(biāo)簽的文章。默認(rèn)情況下,Twig將轉(zhuǎn)義文章體。為了渲染正常,需要添加一個(gè)raw 過(guò)濾器:
{{article.body | raw }}
你也可以在{% block %}區(qū)域或者整個(gè)模板中關(guān)閉安全保護(hù)。
PHP中的安全輸出保護(hù):
在PHP中安全輸出保護(hù)不是自動(dòng)完成的,這就意味著除非你顯示的選擇來(lái)對(duì)某個(gè)輸出變量進(jìn)行保護(hù),否則輸出都是不安全的。我們使用view的方法escape()來(lái)對(duì)輸出變量進(jìn)行安全輸出保護(hù):
Hello <?php echo $view->escape($name) ?>
默認(rèn)情況下,escape()方法默認(rèn)情況下假設(shè)變量是被渲染在一個(gè)HTML上下文中的。也就是說(shuō)只針對(duì)HTML安全。 它的第二個(gè)參數(shù)讓你能夠改變它針對(duì)的上下文。
比如需要在javascript上下文中輸出某些東西,就是用 js 上下文。
var myMsg = 'Hello <?php echo $view->escape($name, 'js') ?>';
模板調(diào)試
當(dāng)使用php代碼時(shí),我們可以使用var_dump()來(lái)快速的查看一個(gè)值的變量傳遞。同樣在Twig中,我們可以使用debug擴(kuò)展來(lái)達(dá)到相同的效果,只是需要預(yù)先在配置文件中開(kāi)啟。
YAML 格式:
# app/config/config.yml services: acme_hello.twig.extension.debug: class: Twig_Extension_Debug tags: - { name: 'twig.extension' }
XML格式:
<!-- app/config/config.xml --> <services> <service id="acme_hello.twig.extension.debug" class="Twig_Extension_Debug"> <tag name="twig.extension" /> </service> </services>
PHP代碼格式:
// app/config/config.php use Symfony\Component\DependencyInjection\Definition; $definition = new Definition('Twig_Extension_Debug'); $definition->addTag('twig.extension'); $container->setDefinition('acme_hello.twig.extension.debug', $definition);
這時(shí)候,我們就可以使用dump函數(shù)來(lái)查看模板參數(shù)了:
{# src/Acme/ArticleBundle/Resources/views/Article/recentList.html.twig #} {{ dump(articles) }} {% for article in articles %} <a href="/article/{{ article.slug }}"> {{ article.title }} </a> {% endfor %}
模板格式:
模板是一個(gè)渲染任何格式內(nèi)容的通用的方式。大多數(shù)情況下,我們使用模板來(lái)渲染HTML內(nèi)容。模板同樣也能渲染想javascript,CSS,XML以及你能想象到的其它格式內(nèi)容。比如,同一個(gè)資源resource經(jīng)常被渲染為不同的格式。把文章目錄頁(yè)渲染為XML,你需要在模板的名稱(chēng)中包含相應(yīng)的格式即可。
XML 模板名: AcmeArticleBundle:Article:index.xml.twig
XML 模板文件名:index.xml.twig
事實(shí)上,這里只是命名上有了變化,而模板并沒(méi)有真正的基于不同的格式渲染不同。在大多數(shù)情況下,你可能想讓單一的controller根據(jù)請(qǐng)求的格式不同渲染多個(gè)不同的格式。下面是一個(gè)通常的寫(xiě)法:
public function indexAction() { $format = $this->getRequest()->getRequestFormat(); return $this->render('AcmeBlogBundle:Blog:index.'.$format.'.twig'); }
Request對(duì)象的getRequestFormat()方法默認(rèn)返回值為html, request的格式通常是在路由時(shí)決定的。比如/contact 設(shè)置的請(qǐng)求格式是html,而 /contact.xml 設(shè)置的請(qǐng)求格式則是 XML。創(chuàng)建一個(gè)包含請(qǐng)求格式的鏈接,只需要在參數(shù)哈希表中包含 _format鍵值即可。
Twig格式:
<a href="{{ path('article_show', {'id': 123, '_format': 'pdf'}) }}"> PDF Version </a>
PHP代碼格式:
<a href="<?php echo $view['router']->generate('article_show', array('id' => 123, '_format' => 'pdf')) ?>"> PDF Version </a>
總結(jié)思考:
Symfony2中的模板引擎是一個(gè)強(qiáng)大的工具,你可以用它來(lái)根據(jù)需要生成包括HTML,XML以及其它任何格式的內(nèi)容。盡管模板時(shí)controller生成內(nèi)容的通常方式,但是不是必須的。controller返回的Response對(duì)象可以使用模板也可以沒(méi)有模板。
// 使用模板生成Response對(duì)象 $response = $this->render('AcmeArticleBundle:Article:index.html.twig'); // 使用簡(jiǎn)單文本內(nèi)容生成Response對(duì)象 $response = new Response('response content');
Symfony2的模板引起非誠(chéng)靈活,默認(rèn)情況下支持傳統(tǒng)的PHP模板和圓滑強(qiáng)大的Twig模板,他們都擁有非常豐富的幫助函數(shù)來(lái)執(zhí)行一些常見(jiàn)任務(wù),Symfony2推薦使用Twig模板,因?yàn)樗雍?jiǎn)潔,高效,能更好的處理繼承等。
以上是“Symfony2中模板怎么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。