템플릿 생성 및 사용
<img src="{{absolute_url(asset('images/logo.png')) }}" alt="Symfony!" />
아시다시피 controller(컨트롤러)가 책임을 집니다. 심포니 프로그램에 들어가는 모든 요청. 실제로 컨트롤러는 코드를 테스트하고 재사용할 수 있도록 대부분의 무거운 작업을 다른 곳에 위임합니다. 컨트롤러가 HTML, CSS 또는 기타 콘텐츠를 생성해야 하는 경우 템플릿 엔진에 작업을 제공합니다. 이 장에서는 사용자에게 콘텐츠 반환, 이메일 채우기 등을 위한 강력한 템플릿을 작성하는 방법을 배웁니다. 또한 단축키, 템플릿을 확장하는 영리한 방법, 템플릿 코드를 재사용하는 방법도 알아봅니다.
템플릿 렌더링 방법은 "프레임워크 시작" 컨트롤러를 참조하세요.
템플릿 ¶
템플릿은 텍스트 형식(html, xml, csv, LaTex...)을 기반으로 모든 텍스트 파일을 생성하는 데 사용됩니다. 우리에게 가장 친숙한 템플릿 유형은 php 템플릿입니다 - PHP 엔진에 의해 구문 분석되는 텍스트와 PHP 코드가 포함된 텍스트 파일입니다:
<!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>
그러나 Symfony 프레임워크에는 다음과 같은 더 강력한 템플릿 언어가 있습니다. 작은 가지. Twig를 사용하면 간결하고 읽기 쉽고 디자이너 친화적인 템플릿을 작성할 수 있으며 이는 여러 측면에서 PHP 템플릿보다 훨씬 강력합니다.
<!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>
Twig는 세 가지 특수 구문을 정의합니다.
{{ ... }}
- “说些什么”:输出一个变量值或者一个表达式的结果到模板。
{% ... %}
- “做些什么”:控制模板逻辑的*tag(标签)*,用于执行声明,如for循环语句等。
{# ... #}
- “进行注释”:它相当于php的
/* comment */
语法。它用于注释单行和多行。注释的内容不作为页面输出。
{{ ... }}
twig也包含filters,它可以在模板渲染之前改变输出内容。下例让title变量在被渲染之前全部大写:
{{ title|upper }}
Twig内置了大量的标签(tags)和变量调节器(filters),默认就可以使用。你甚至可以利用Twig扩展来添加你自己的自定义 调节器和函数(乃至更多)。
注册一个Twig扩展非常容易,创建一个新服务并打上Twig.extension
"Say Something": 변수 값 또는 결과를 출력합니다. 템플릿에 대한 표현식입니다.
{% ... %}
{# ... #}
🎜"Comment": PHP의 /* 주석과 동일합니다 * /
구문. 단일 및 여러 줄의 주석을 달 때 사용됩니다. 댓글 내용은 페이지로 출력되지 않습니다. 🎜twig에는 템플릿이 렌더링되기 전에 출력 콘텐츠를 변경할 수 있는 🎜filters🎜도 포함되어 있습니다. 다음 예에서는 렌더링되기 전에 제목 변수를 모두 대문자로 만듭니다. 🎜{% for i in 0..10 %} <div class="{{ cycle(['odd', 'even'], i) }}"> <!-- some HTML here --> </div>{% endfor %}🎜Twig에는 기본적으로 사용할 수 있는 수많은 내장 태그와 변수 필터가 있습니다. Twig 확장 기능을 활용하여 자신만의 🎜맞춤형🎜 조절기 및 기능 등을 추가할 수도 있습니다. 🎜🎜
Twig.extension
태그로 태그를 지정하세요. 🎜🎜🎜Twig 코드는 PHP 코드와 매우 유사하지만 둘 사이에는 미묘한 차이가 있습니다. 다음 예에서는 표준 for
태그와 cycle
함수를 사용하여 odd
, even
을 사용하여 10개의 div 태그를 출력합니다. > CSS 클래스가 번갈아 표시됩니다. for
标签和cycle
函数来输出10个div 标签,用odd
、even
css类交替显示。
<ul> {% for user in users if user.active %} <li>{{ user.username }}</li> {% else %} <li>No users found</li> {% endfor %}</ul>
本章的模板例程,将同时使用twig和php来展示。
如果你不使用Twig或者禁用它,你需要使用kernel.execption
事件来实现一个你自己的异常处理。
为什么使用twig?
twig模板就是为了简单而不去处理php标签。设计上即是如此:twig模板只负责呈现,而不去考虑逻辑。你用twig越多,你就越会欣赏它,并从它的特性中受益。当然,你也会被普天下的网页设计者喜欢。
还有很多twig可以做但是php不可以的事,如空格控制、沙盒、自动html转义、手动上下文输出转义,以及包容“只会影响模板”的自定义函数和调节器。twig包含一些小功能,使得写模板时更加方便快捷。请看下例,它结合了逻辑循环和if
Twig:{# app/Resources/views/base.html.twig #}<!DOCTYPE html> <html> <head> <meta 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>이 장의 템플릿 루틴은 twig와 php를 모두 사용하여 표시됩니다.
twig를 사용하는 이유는 무엇인가요?
#🎜🎜#twig 템플릿은 단순성을 위한 것이며 PHP 태그를 처리하지 않습니다. 이것이 디자인의 경우입니다. 나뭇가지 템플릿은 논리를 고려하지 않고 프리젠테이션만 담당합니다. Twig를 더 많이 사용할수록 Twig에 대해 더 감사하게 되고 그 기능의 혜택을 누릴 수 있습니다. 물론 전 세계의 웹 디자이너들도 당신을 좋아할 것입니다. #🎜🎜##🎜🎜# 공간 제어, 샌드박싱, 자동 HTML 이스케이프, 수동 컨텍스트 출력 이스케이프, 템플릿에만 영향을 미칠 수 있는 사용자 정의 등 Twig는 할 수 있지만 PHP는 할 수 없는 일이 많습니다. 나뭇가지에는 템플릿 작성을 더욱 편리하고 빠르게 만들어주는 몇 가지 작은 기능이 포함되어 있습니다. 논리 루프와if
문을 결합한 다음 예를 고려해 보세요. #🎜🎜#PHP:<!-- app/Resources/views/base.html.php --> <!DOCTYPE html> <html> <head> <meta 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>#🎜🎜##🎜🎜#
Twig 템플릿 캐싱 ¶
Twig는 빠르며, 각 Twig 템플릿은 기본 PHP 클래스로 컴파일되어 캐시됩니다. 컴파일된 클래스는 var/cache/{environment}/twig
디렉터리에 저장됩니다(여기서 {environment}
는 환경입니다. 예: dev
및 prod
), 경우에 따라 동시에 디버깅할 수 있어 매우 유용합니다. 환경에 대한 자세한 내용은 다음을 참조하세요. 환경 var/cache/{environment}/twig
目录下(其中{environment}
是环境,如dev
和prod
),并在某些情况下可以同时调试,非常有用。关于环境的更多细节请参考:环境
当debug
模式可用时(dev
环境),如果一个twig模板发生改变,将会被自动重新编译。这意味着你可以在开发过程中随意修改模板,而不必担心要去清除缓存了。
当debug
模式被关闭时(prod
环境),你必须手动的清除Twig缓存目录,以便重新生成Twig模板。记得在部署程序时一定要做到这一点。
模板继承和布局 ¶
大多数的时候,模板在项目中都有通用的元素,比如header,footer,sidebar等等。在Symfony中,我们将采用不同的思考角度来对待这个问题。一个模板可以被另外的模板装饰。这个的工作原理跟PHP类非常像,模板继承让你可以创建一个基础“layout”模板,它包含你的站点所有通用元素,并被定义成blocks(如同一个“包含基础方法的PHP基类”)。一个子模板可以继承layout基础模板并覆写它的任何一个block(就像“PHP子类覆写父类中的特定方法”)。
首先创建一个layout基础文件:
Twig:{# app/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:<!-- app/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() ?>
虽然讨论的是关于Twig的模板继承,但在思维方式上twig和php模板之间是相同的。
该模板定义了一个简单的两列式html页面。在本例中,三处 {% block %}
区域被定义了(即title
,sidebar
和body
)。每个block都可以被继承它的子模板覆写,或者保留现在这种默认实现。该模板也能被直接渲染(输出)。只不过此时只是显示基础模板所定义的内容,title
, sidebar
和 body
都将保持默认值。
一个子模板看起来是这样的:
<!DOCTYPE html><html> <head> <meta 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>
{% block sidebar %} <h3>Table of Contents</h3> {# ... #} {{ parent() }}{% endblock %}
父模板以一个特殊的字符串语法来表示 base.html.twig
,这个路径是相对于整个项目的app/Resources/views
目录而言的。你也可以使用逻辑名称相同的::base.html.twig
디버그
모드를 사용할 수 있는 경우(< code>dev 환경), 나뭇가지 템플릿이 변경되면 자동으로 다시 컴파일됩니다. 즉, 캐시 삭제에 대해 걱정할 필요 없이 개발 중에 템플릿을 수정할 수 있습니다.
debug
모드가 꺼진 경우(prod
환경) Twig 템플릿을 다시 생성하려면 Twig 캐시 디렉터리를 수동으로 지워야 합니다. 프로그램을 배포할 때 이 작업을 수행하는 것을 잊지 마세요. 템플릿 상속 및 레이아웃 ¶🎜
🎜대부분의 경우 템플릿에는 헤더와 같은 프로젝트의 공통 요소가 있습니다. , 바닥글, 사이드바 등 Symfony에서는 이 문제를 다른 관점에서 접근할 것입니다. 템플릿은 다른 템플릿으로 꾸며질 수 있습니다. 이는 PHP 클래스와 매우 유사하게 작동하며, 템플릿 상속을 통해 사이트의 모든 공통 요소를 포함하고 블록으로 정의되는 기본 "레이아웃" 템플릿을 생성할 수 있습니다(예: "기본" 템플릿 PHP 포함) 메소드의 기본 클래스"). 하위 템플릿은 레이아웃 기본 템플릿을 상속하고 해당 블록을 재정의할 수 있습니다("PHP 하위 클래스가 상위 클래스의 특정 메서드를 재정의"하는 것처럼). 🎜🎜먼저 레이아웃 기본 파일을 만듭니다: 🎜app/Resources/views
path/to/bundle/Resources/views🎜논의는 Twig의 템플릿 상속에 관한 것이지만, 나뭇가지와 PHP 템플릿 사이의 생각은 동일합니다.
🎜🎜🎜🎜이 템플릿은 간단한 2열 HTML 페이지를 정의합니다. 이 예에서는 세 개의
{% block %}
영역이 정의되었습니다(예: 제목
, 사이드바
및 본문
). 각 블록은 이를 상속하는 하위 템플릿으로 재정의되거나 현재 기본 구현을 유지할 수 있습니다. 템플릿을 직접 렌더링(출력)할 수도 있습니다. 단, 이때는 기본 템플릿에서 정의한 콘텐츠만 표시되며, 제목
, 사이드바
, 본문
은 기본값을 유지합니다. 🎜🎜하위 템플릿은 다음과 같습니다: 🎜Twig:{# app/Resources/views/article/article_details.html.twig #}<h2>{{ article.title }}</h2> <h3 class="byline">by {{ article.authorName }}</h3> <p> {{ article.body }}</p>
php:<!-- app/Resources/views/article/article_details.html.php --> <h2><?php echo $article->getTitle() ?></h2> <h3 class="byline">by <?php echo $article->getAuthorName() ?></h3> <p> <?php echo $article->getBody() ?></p>
으로 표시됩니다. base.html.twig
, 이 경로는 전체 프로젝트의 app/Resources/views
디렉토리에 상대적입니다. 동일한 논리적 이름으로 ::base.html.twig
를 사용할 수도 있습니다. 아래 🎜템플릿 이름과 위치🎜를 참고하세요. 🎜🎜🎜템플릿에 상속된 키워드는 {% Extensions %}
태그입니다. 이 태그는 레이아웃을 설정하고 여러 블록을 정의하는 상위 템플릿을 먼저 평가하도록 템플릿 엔진에 지시합니다. 그런 다음 하위 템플릿이 렌더링되고 위 예의 상위 템플릿에 정의된 두 블록 title
및 body
는 하위 템플릿. blog_entries
값에 따라 출력 콘텐츠는 다음과 같을 수 있습니다. {% extends %}
标签。 该标签告诉模板引擎首先评估父模板,它设置了布局并定义了若干blocks。然后子模板被渲染,上例中父模板中定义的title
和body
两个blocks将会被子模板中的同名区块内容所取代。根据blog_entries
的取值,输出的内容可能像下面这样:
Twig:{# app/Resources/views/article/list.html.twig #}{% extends 'layout.html.twig' %} {% block body %} <h1>Recent Articles<h1> {% for article in articles %} {{ include('article/article_details.html.twig', { 'article': article }) }} {% endfor %}{% endblock %}
注意,由于子模板中没有定义sidebar
这个block,来自父模板的内容将被显示出来。父模板中的{% block %}
php:<!-- app/Resources/article/list.html.php --><?php $view->extend('layout.html.php') ?> <?php $view['slots']- >start('body') ?> <h1>Recent Articles</h1> <?php foreach ($articles as $article): ?> <?php echo $view->render( 'Article/article_details.html.php', array('article' => $article) ) ?> <?php endforeach ?><?php $view['slots']->stop() ?>
sidebar
블록이 하위 템플릿에 정의되어 있지 않으므로 상위 템플릿은 표시됩니다. 상위 템플릿의 {% block %}
태그 내의 콘텐츠는 항상 기본값으로 사용됩니다. 템플릿 상속을 사용할 때 다음 사항에 유의하세요.
템플릿에서
{% 확장 %}
를 사용하는 경우 이 태그가 템플릿의 첫 번째 태그여야 합니다.{% extends %}
,它必须是模板中的第一个标签。你的基础(布局)模板中的
{% block %}
标签越多越好,记得,子模板不必定义父模板中的所有block。基础模板中的block定义得愈多,你的布局就愈灵活。如果你发现在多个模板中有重复的内容,这可能意味着你需要为该内容在父模板中定义一个
{% block %}
了。某些情况下,更好的解决方案可能是把这些内容放到一个新模板中,然后在该模板中include
它。(查看下文的:包容其他模板)如果你需要从父模板中获取一个block的内容,可以使用
{{ parent() }}
函数。如果你只是想在父级块上添加新内容,而不是完全覆盖它,这很有用:
Annotations:// src/AppBundle/Controller/WelcomeController.php // ...use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; class WelcomeController extends Controller{ /** * @Route("/", name="_welcome") */ public function indexAction() { // ... }}
模板的命名和存储位置 ¶
默认情况下,模板可以存放在两个不同的位置:
YAML:# app/config/routing.yml_welcome: path: / defaults: { _controller: AppBundle:Welcome:index }
程序级的views目录可以存放整个程序的基础模板(程序布局和bundle模板),以及那些“用于覆写第三方bundle的模板”的模板(如何覆写第三方bundle的模板)。
XAML:<!-- app/config/routing.yml --><?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="_welcome" path="/"> <default key="_controller">AppBundle:Welcome:index</default> </route></routes>
每个第三方bundle的模板都会存放于它自己的Resources/views/
目录(或者子目录)下。当你打算共享你的bundle时,你应该把它放在bundle中,而不是app/
目录。
更多时候你要用到的模板是在app/Resources/views/
目录下。你需要的模板路径是相对于这个目录的。例如,去渲染/继承app/Resources/views/base.html.twig
,你需要使用base.html.twig
的路径,而要去渲染app/Resources/views/blog/index.html.twig
时,你需要使用blog/index.html.twig
路径。
在Bundle中引入模板 ¶
Symfony使用bundle:directory:filename
字符串语法表示模板。这可以表示许多不同类型的模板,每种都存放在一个特定路径下:
AcmeBlogBundle:Blog:index.html.twig
用于指定一个特定页面的模板。字符串分为三个部分,每个部分由冒号(:
)隔开,含义如下:
AcmeBlogBundle
:(bundle)模板位于AcmeBlogBundle,比如src/Acme/BlogBundle
;Blog
:(目录)表明模板位于Resourcs/views
的Blog
子目录中;index.html.twig
:(文件名)文件的实际名称为index.html.twig
。
假设AcmeBlogBundle位于src/Acme/BlogBundle
, 最终的路径将是:src/Acme/BlogBundle/Resources/views/Blog/index.html.twig
{% block %}
태그가 많을수록 좋습니다. 하위 템플릿이 상위 템플릿의 모든 블록을 정의할 필요는 없습니다. 기본 템플릿에 더 많은 블록을 정의할수록 레이아웃이 더 유연해집니다. 🎜🎜🎜여러 템플릿에서 중복된 콘텐츠를 발견하면 상위 템플릿에서 해당 콘텐츠에 대해 {% block %}
를 정의해야 할 수도 있습니다. 어떤 경우에는 콘텐츠를 새 템플릿에 넣고 해당 템플릿 내에 포함
하는 것이 더 나은 해결책일 수 있습니다. (아래 참조: 다른 템플릿 포함)🎜🎜🎜상위 템플릿에서 블록의 내용을 가져와야 하는 경우 {{ parent() }}
함수를 사용할 수 있습니다. 이는 완전히 덮어쓰는 대신 상위 블록 위에 새 콘텐츠를 추가하려는 경우에 유용합니다. 🎜PHP:// app/config/routing.phpuse Symfony\Component\Routing\Route;use Symfony\Component\Routing\RouteCollection; $collection = new RouteCollection();$collection->add('_welcome', new Route('/', array( '_controller' => 'AppBundle:Welcome:index',))); return $collection;
템플릿의 이름을 지정하고 저장하는 위치 ¶
🎜 기본적으로 템플릿은 두 가지 다른 위치에 저장될 수 있습니다. 🎜Twig:<a href="{{ path('_welcome') }}">Home</a>🎜 프로그램 수준 보기 디렉터리는 전체 프로그램(프로그램 레이아웃 및 번들 템플릿)의 기본 템플릿과 "타사 번들을 재정의하는 데 사용되는 템플릿"을 저장할 수 있습니다. 템플릿"(타사 번들의 템플릿을 재정의하는 방법). 🎜
php:<a href="<?php echo $view['router']->path('_welcome') ?>">Home</a>🎜각 타사 번들의 템플릿은 자체
Resources/views/
디렉터리(또는 하위 디렉터리)에 저장됩니다. 번들을 공유하려는 경우 app/
디렉터리가 아닌 번들에 배치해야 합니다. 🎜🎜사용해야 하는 대부분의 템플릿은 app/Resources/views/
디렉터리에 있습니다. 필요한 템플릿 경로는 이 디렉터리에 상대적입니다. 예를 들어 app/Resources/views/base.html.twig
를 렌더링/상속하려면 base.html.twig
경로를 사용해야 하며 를 렌더링해야 합니다. code> app/Resources/views/blog/index.html.twig
의 경우 blog/index.html.twig
경로를 사용해야 합니다. 🎜번들 ¶
에 템플릿 도입🎜Symfony는bundle:directory:filename 코드를 사용합니다. >String 구문은 템플릿을 나타냅니다. 이는 각각 특정 경로에 저장된 다양한 유형의 템플릿을 나타낼 수 있습니다. 🎜🎜🎜AcmeBlogBundle:Blog:index.html.twig
는 특정 페이지에 대한 템플릿을 지정하는 데 사용됩니다. 문자열은 세 부분으로 나누어지며, 각 부분은 콜론(:
)으로 구분되며, 그 의미는 다음과 같습니다: 🎜🎜AcmeBlogBundle code> : (bundle) 템플릿은 AcmeBlogBundle에 있습니다(예: src/Acme/BlogBundle
🎜🎜🎜Blog
). : (디렉터리 ) 템플릿이 Resources/views
🎜🎜🎜의 Blog
하위 디렉터리에 있음을 나타냅니다. index.html.twig
: (파일 이름) 파일의 실제 이름은 index.html.twig
입니다. 🎜
🎜AcmeBlogBundle이 src/Acme/BlogBundle
에 있다고 가정하면 최종 경로는 src/Acme/BlogBundle/Resources/views/Blog/입니다. index.html .twig
🎜AcmeBlogBundle::layout.html.twig
这种语法指向了AcmeBlogBundle的父模板。没有了中间的“目录”部分(如blog
),模板应该位于AcmeBlogBundle的Resources/views/layout.html.twig
。是的,中间的两个冒号意味着“控制器”子目录部分被忽略了。
在如何覆写第三方bundle的模板一文中,你将了解到位于AcmeBlogBundle的模板,是如何被app/Resources/AcmeBlogBundle/views/
目录下的同名模板所覆写的,这种方式给了我们一个有力的途径来覆写bundle作者提供的bundle模板。
模版的命名语法可能看上去比较熟悉——它类似于控制器命名模式中提到的约定。
模版后缀 ¶
每个模版都有两个扩展名,用来指定格式(format) 和模版引擎(engine)。
文件名 Format 引擎 blog/index.html.twig
HTML Twig blog/index.html.php
HTML PHP blog/index.css.twig
CSS 나뭇가지
기본적으로 Symfony의 모든 템플릿은 접미사(.twig
或 .php
)来决定使用哪个引擎。其中后缀的前一部分(.html
,.css
)表示最终生成的格式。不像引擎,它是决定symfony如何解析模板,这是一个很简单的使用策略,你可以使用HTML(index.html.twig
),XML(index.xml.twig
) 또는 기타 형식을 통해 리소스로 렌더링되는 Twig 또는 PHP 엔진으로 작성될 수 있습니다. 자세한 내용은 템플릿 형식 섹션을 참조하세요.
사용 가능한 "엔진" 섹션은 구성 가능하며 새 엔진을 추가하는 것도 가능합니다. 자세한 내용은 템플릿 서비스 구성 및 사용 방법을 참조하세요.
태그 및 도움말 ¶
당신은 이미 템플릿의 기본, 이름 지정 방법, 템플릿 상속 사용 방법을 알고 있습니다. 가장 어려운 부분은 끝났습니다. 다음으로, 다른 템플릿 포함, 페이지 링크, 이미지 포함 등 일반적인 템플릿 작업에 도움이 되는 다양한 도구를 살펴보겠습니다.
Symfony 프레임워크에는 템플릿 디자이너가 작업을 단순화하는 데 도움이 되는 여러 가지 특수 Twig 태그와 기능이 내장되어 있습니다. PHP에서 템플릿 시스템은 템플릿 컨텍스트 내에서 유용한 기능을 제공하기 위해 확장 가능한 helper 시스템을 제공합니다.
({% block %}
& {% extends %}
) 등과 같은 내장 Twig 태그와 PHP 도우미 < 코드>$ 보기['슬롯']
. 이제 더 많은 것을 배우게 될 것입니다. {% block %}
& {% extends %}
)等,还有PHP helper $view[‘slots’]
。现在,你将会学到更多。引入其他模版 ¶
你经常需要在多个不同的页面中包含同一个模板或者代码片段。比如在一个“新闻文章”程序中,用于显示文章的模板代码可能会被用到正文页,或者用到一个显示“人气文章”的页面,乃至一个“最新文章”的列表页等。
当你需要复用一些PHP代码时,你通常都是把这些代码放到一个PHP类或者函数中。同样在模板中你也可以这么做。通过把可复用的代码放到一个它自己的模板中,然后从其他模板中包容这个模板。首先,创建一个可复用模板如下:
Annotations:// src/AppBundle/Controller/ArticleController.php // ...use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; class ArticleController extends Controller{ /** * @Route("/article/{slug}", name="article_show") */ public function showAction($slug) { // ... }}
TAML:# app/config/routing.ymlarticle_show: path: /article/{slug} defaults: { _controller: AppBundle:Article:show }
在其他任何模板中引入这个模板很简单:
PHP:// app/config/routing.phpuse Symfony\Component\Routing\Route;use Symfony\Component\Routing\RouteCollection; $collection = new RouteCollection();$collection->add('article_show', new Route('/article/{slug}', array( '_controller' => 'AppBundle:Article:show',))); return $collection;
XAML:<!-- app/config/routing.xml --><?xml version="1.0" encodin g="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="article_show" path="/article/{slug}"> <default key="_controller">AppBundle:Article:show</default> </route></routes>
这个模板被包容时,使用了{{ include() }}
标签。请注意,模板命名要遵循相同的典型约定。在article_details.html.twig
模板中使用article
变量,这是我们传入模板的。本例中,你也可以完全不这样做,因为在list.html.twig
模板中可用的所有变量也都可以在article_details.html.twig
中使用(除非你设置with_context为false)。
{'article':article}
语法是标准Twig哈希映射(hash maps)的写法(即是一个键值对数组)。如果你需要传递多个元素,可以写成{'foo': foo, 'bar': bar}
다른 템플릿 소개 ¶
동일한 템플릿을 여러 다른 페이지에 포함해야 하는 경우가 많습니다. 또는 코드 짧은 발췌. 예를 들어, "뉴스 기사" 프로그램에서 기사를 표시하는 데 사용되는 템플릿 코드는 텍스트 페이지나 "인기 기사"를 표시하는 페이지, 심지어 "최신 기사" 목록 페이지 등에 사용될 수 있습니다.Twig:{# app/Resources/views/article/recent_list.html.twig #}{% for article in articles %} <a href="{{ path('article_show', {'slug': article.slug}) }}"> {{ article.title }} </a>{% endfor %}
php:<!-- app/Resources/views/Article/recent_list.html.php --><?php foreach ($articles in $article): ?> <a href="<?php echo $view['router']->path('article_show', array( 'slug' => $article->getSlug(), )) ?>"> <?php echo $article->getTitle() ?> </a><?php endforeach ?>🎜이 템플릿을 다른 템플릿에 도입하는 것은 간단합니다.
🎜
Twig:<a href="{{ url('_welcome') }}">Home</a> php:<a href="<?php echo $view['router']->url( '_welcome', array()) ?>">Home</a>
Twig:<img src="{{ asset('images/logo.png') }}" alt="Symfony!" /> <link href="{{ asset('css/blog.css') }}" rel="stylesheet" />🎜이 템플릿이 포함되면
{{ include() }}< /code>를 사용하세요. 꼬리표. 템플릿 이름 지정은 동일한 일반적인 규칙을 따릅니다. 템플릿에 전달하는 article_details.html.twig
템플릿의 article
변수를 사용하세요. 이 경우 list.html.twig
템플릿에서 사용할 수 있는 모든 변수를 article_details.html.twig
에서도 사용할 수 있으므로 이 작업을 전혀 수행할 필요가 없습니다. code> (with_context를 false로 설정하지 않은 경우). 🎜🎜{'article':article}
구문은 표준 Twig 해시 맵( 해시 맵)(즉, 키-값 쌍의 배열)입니다. 여러 요소를 전달해야 하는 경우 {'foo': foo, 'bar': bar}
를 작성하면 됩니다. 🎜🎜🎜페이지 링크 ¶
프로그램에서 다른 페이지에 대한 링크를 만드는 것은 템플릿에서 매우 일반적인 일입니다. 템플릿에 URL을 하드코딩하는 대신 path
Twig 함수(또는 PHP의 router
도우미)를 사용하여 라우팅 구성을 기반으로 URL을 생성하세요. 나중에 특정 페이지의 URL을 변경하려면 라우팅 구성만 변경하면 템플릿이 자동으로 새 URL을 생성합니다. path
Twig函数(或者php中的router
helper)基于路由配置来生成URLs而非在模板中写死URLs。以后,如果你想修改一个特定页面的URL,你只需要改变路由配置即可;模板将自动生成新的URL。
比如我们打算链接到“_welcome”页面,首先定义其路由配置:
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" />
<img src="{{ absolute_url(asset('images/logo.png')) }}" alt="Symfony!" />
Twig:{# app/Resources/views/base.html.twig #}<html>
<head> {# ... #} {% block stylesheets %}
<link href="{{ asset('css/main.css') }}" rel="stylesheet" /> {% endblock %}
</head>
<body> {# ... #} {% block javascripts %}
<script src="{{ asset('js/main.js') }}"></script> {% endblock %}
</body>
</html>
php:// app/Resources/views/base.html.php<html> <head> <?php ... ?> <?php $view['slots']->start('stylesheets') ?> <link href="<?php echo $view['assets']->getUrl('css/main.css') ?>" rel="stylesheet" /> <?php $view['slots']->stop() ?> </head> <body> <?php ... ?> <?php $view['slots']->start('javascripts') ?> <script src="<?php echo $view['assets']->getUrl('js/main.js') ?>"></script>
<?php $view['slots']->stop() ?> </body>
</html>
要链到页面,只需使用Twig的path
函数来指定这个路由即可。
Twig:{# app/Resources/views/contact/contact.html.twig #}{% extends 'base.html.twig' %} {% block stylesheets %}
{{ parent() }}
<link href="{{ asset('css/contact.css') }}" rel="stylesheet" />{% endblock %} {# ... #}
php:// app/Resources/views/contact/contact.html.twig<?php $view->extend('base.html.php') ?> <?php $view['slots']->start('stylesheets') ?>
<link href="<?php echo $view['assets']->getUrl('css/contact.css') ?>" rel="stylesheet" /><?php $view['slots']->stop() ?>
正如预期的那样,它生成了URL /
。现在,处理一个更复杂的路由:
<link href="{{ asset('bundles/acmedemo/css/contact.css') }}" rel="stylesheet" />
<!-- output escaping is on automatically -->{{ description }} <!-- I <3 this product -->
<!-- disable output escaping with the raw filter -->{{ description|raw }} <!-- I <3 this product -->
// creates a Response object whose content is the rendered template$response = $this->render('article/index.html.twig'); // creates a Response object whose content is simple text$response = new Response('response content');
rrreee这种情况下,你需要指定路由名称()以及一个。使用这个路由重新定义前文提到的模板,并正确链入文章。
rrreeerrreee你可以通过Twig的url
예를 들어 "_welcome" 페이지에 링크할 계획이라면 먼저 라우팅 구성을 정의하세요.
rrreeerrreeerrreeerrreee페이지에 링크하려면 Twig의 path
함수를 사용하여 이 경로를 지정하세요. rrreeerrreee🎜🎜🎜예상대로 /
URL이 생성되었습니다. 이제 더 복잡한 경로를 처리해 보겠습니다. 🎜rrreeerrreeerrreeerrreee🎜이 경우 경로 이름()과 . 이 경로를 사용하여 앞서 언급한 템플릿을 재정의하고 기사에 올바르게 연결하세요. 🎜rrreeerrreee🎜Twig의 url
기능을 통해 절대 경로를 생성할 수 있습니다: 🎜rrreee🎜 🎜🎜자산 링크 ¶
템플릿에는 일반적으로 일부 이미지, Javascript, 스타일 파일 및 기타 웹 자산도 필요합니다. 물론 경로를 하드코딩할 수도 있습니다. 예를 들어 /images/logo.png
입니다. 그러나 Symfony는 Twig 함수 asset()
를 통해 보다 동적인 선택을 제공합니다. /images/logo.png
。 但是Symfony通过Twig函数 asset()
,提供了一个更加动态的选择,。
rrreeerrreeeasset
函数的主要目的,是让你的程序更加portable(可移动)。如果你的程序在主机根目录下(如http://example.com
),生成的路径应该是 /images/logo.png
。但是如果你的程序位于一个子目录中(如http://example.com/my_app
),asset路径在生成时应该带有子目录(如 /my_app/images/logo.png
) 。asset
函数负责打点这些,它根据你的程序 “是如何使用的” 而生成相应的正确路径。
另外,如果你使用asset
函数,symfony可以自动追加一个query string(查询字符串)到你的资产,以保证被更新的静态资源不会在部署时被缓存。例如,/images/logo.png
可能看起来是 /images/logo.png?v2
。参考version配置一文以了解更多。
如果你需要assets资源的绝对URL,可以使用absolute_url()
Twig函数:
rrreee在Twig中包容样式表和Javascript ¶
每个网站中都不能完全没有样式表和javascript文件。在Symfony中,这些内容可以利用模板继承来优雅地处理。
本节教给你包容stylesheet和javaScript资源时的背后思想。Symfony支持另外一个类库叫Assetic, 它允许你在遵循这一思想时,对这些资源做更多有趣事情。参考如何使用Assetic 进行资产管理以了解更多细节。
首先在你的基础布局模板中添加两个blocks来保存你的资源,一个叫stylesheets
,放在head
标签里,另一个叫javascript
,放在body
结束标签上面一行。这些blocks将包含你整个站点所需的全部stylesheets和javascripts。
rrreeerrreee这也太简单了!但如果你想从子模板中包容一个额外的stylesheet或者javascript进来该怎么办呢?比如,假设你有一个联系页面需要包容一个contact.css
rrreeerrreee asset
함수의 주요 목적은 프로그램의 이식성을 높이는 것입니다. 프로그램이 호스트 루트 디렉터리(예: http://example.com
)에 있는 경우 생성된 경로는 /images/logo.png
여야 합니다. 그러나 프로그램이 하위 디렉터리(예: http://example.com/my_app
)에 있는 경우 자산 경로는 하위 디렉터리(예: /my_app/images/)를 사용하여 생성되어야 합니다. 로고.png
). asset
함수는 이를 처리하는 역할을 하며 "프로그램이 사용되는 방식"에 따라 올바른 경로를 생성합니다.
또한 asset
함수를 사용하면 Symfony는 자동으로 쿼리 문자열을 자산에 추가하여 업데이트된 정적 리소스가 배포 중에 캐시되지 않도록 할 수 있습니다. 예를 들어 /images/logo.png
는 /images/logo.png?v2
와 유사할 수 있습니다. 자세한 내용은 version
구성 도움말을 참조하세요. 자산 리소스의 절대 URL이 필요한 경우 absolute_url()
Twig 함수를 사용할 수 있습니다. rrreeeTwig에 스타일시트 및 Javascript 포함 ¶🎜
🎜모든 웹사이트는 스타일 시트와 자바스크립트 파일에서 완전히 자유로울 수 없습니다. Symfony에서는 템플릿 상속을 사용하여 이러한 문제를 우아하게 처리할 수 있습니다. 🎜🎜이 섹션에서는 스타일시트 및 JavaScript 리소스를 포함하는 아이디어에 대해 설명합니다. Symfony는 Assetic이라는 또 다른 클래스 라이브러리를 지원합니다. 이를 통해 이 아이디어를 따르면서 이러한 리소스로 더 흥미로운 작업을 수행할 수 있습니다. 자세한 내용은 자산 관리에 Assetic을 사용하는 방법🎜을 참조하세요. 🎜🎜🎜🎜먼저 기본 레이아웃 템플릿에 두 개의 블록을 추가하여 리소스를 저장하세요. 하나는 head
태그에 배치되는 stylesheets
이고 다른 하나는 입니다. < code>javascript는 body
닫는 태그 위 줄에 배치됩니다. 이 블록에는 전체 사이트에 필요한 모든 스타일시트와 자바스크립트가 포함됩니다. 🎜🎜rrreeerrreee🎜너무 쉽네요! 하지만 하위 템플릿에서 추가 스타일시트나 자바스크립트를 포함하려면 어떻게 해야 할까요? 예를 들어, contact.css
스타일 시트를 포함해야 하는 연락처 페이지가 있고 해당 페이지에서만 🎜만🎜 사용된다고 가정해 보겠습니다. 연락처 페이지 템플릿에서 다음과 같이 구현할 수 있습니다.🎜🎜🎜🎜rrreeerrreee🎜하위 템플릿에서는 stylesheets
블록을 재정의하고 새 스타일시트 태그를 블록에 넣으면 됩니다. 물론, (실제로 교체하는 것이 아니라) 상위 블록의 내용에 추가하기를 원하므로 먼저 parent()
함수를 사용해야 합니다. get it 기본 템플릿에 있는 모든 stylesheets
블록의 내용입니다. stylesheets
block并把你新的样式表标签放到该区块里。当然,由于你只是想把它添加到父块儿的内容中(而不是真的替代它们),所以你需要先用parent()
函数来获取基础模板中的所有stylesheets
区块中的内容。
你也可以包容位于你bundle的Resources/public
文件夹下的assets资源。你需要运行php bin/console assets:install target [–symlink]
命令,它会把文件移动到(或symlink到)正确的位置(默认目标位置是“web”文件夹)。
rrreee最终结果是,页面中同时包容了main.css
和contact.css
两个样式表。
引用Request,User或Session对象 ¶
Symfony在Twig中给了你一个全局的app
变量,可以用于访问当前用户、请求以及更多对象。
参考如何在Twig中通过app变量访问到User, Request, Session和更多对象以了解细节。
输出转义 ¶
在渲染任意内容时,Twig自动进行“输出转义(output escaping)”,为的是保护你免受 Cross Site Scripting (XSS)跨站攻击。
假设description
是I <3 this product
번들의 Resources/public
폴더에 있는 자산을 포함할 수도 있습니다. php bin/console 자산:install target [–symlink]
명령을 실행해야 합니다. 이 명령은 파일을 올바른 위치로 이동(또는 심볼릭 링크)합니다(기본 대상 위치는 "웹" 폴더입니다) ). rrreee
Symfony는 Twig 변수에서 전역 앱
을 제공합니다. 현재 사용자, 요청 및 기타 개체에 액세스하는 데 사용할 수 있습니다.
자세한 내용은 Twig의 앱 변수를 통해 사용자, 요청, 세션 및 기타 개체에 액세스하는 방법을 참조하세요. 출력 이스케이프 ¶
콘텐츠를 렌더링할 때 Twig는 자동으로 "출력 이스케이프"를 수행합니다. 크로스 사이트 스크립팅(XSS)으로부터 사용자를 보호합니다. ) 교차 사이트 공격. 설명
이 I <3 this product
라고 가정하면: rrreee
PHP 템플릿은 자동으로 콘텐츠를 이스케이프하지 않습니다.
자세한 내용은 템플릿 출력 이스케이프 방법을 참조하세요. 🎜요약 🎜¶🎜🎜🎜Symfony의 템플릿 엔진은 필요에 따라 HTML, XML 및 기타 형식을 포함한 콘텐츠를 생성하는 데 사용할 수 있는 강력한 도구입니다. 컨트롤러에서 템플릿을 생성하는 것이 일반적이지만 필수는 아닙니다. 컨트롤러가 반환한 응답 개체는 템플릿을 사용할 수도 있고 사용하지 않을 수도 있습니다. 🎜rrreee🎜Symfony의 템플릿은 기본적으로 기존 PHP 템플릿과 세련되고 강력한 Twig 템플릿을 지원합니다. 둘 다 몇 가지 일반적인 작업을 수행하는 데 매우 풍부한 도우미 기능을 제공합니다. Symfony는 Twig 템플릿이 더 간결하고 효율적이며 상속 등을 더 잘 처리할 수 있으므로 사용을 권장합니다. 🎜🎜전반적으로 템플릿 문제를 처리할 때 강력한 도구입니다. 어떤 경우에는 템플릿을 렌더링할 필요가 없을 수도 있으며, 심포니에서는 전혀 문제가 되지 않습니다. 🎜🎜🎜🎜🎜🎜🎜🎜