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