电脑装配网

Drupal8 Theme Twig主题模板

 人阅读 | 作者xiaolin | 时间:2023-07-23 21:07

Drupal8中的Twig

Drupal8中Twig替换了PHPTemplate作为默认的模板引擎,导致的结果之一就是模版的后缀由原来的.tpl.php变成了.html.twig

搜索Twig模版中的变量

在使用Twig模版的时候,大部分的变量都以注释的形式写在了模版中。然后,当我们新增了变量,我们就需要一个可以搜索到当前模版所有变量的方法。Twig提供了dump函数。

dump函数并不会打印所有的输出,除非开启了debug。

dump函数用于打印单个变量的信息或者模版中的所有变量。

单个变量

如果你的模版中有一个title变量,下面在你的模版中dump出这个变量的内容:

1{{ dump(title) }}

模版中的所有变量

要打印出模版中的所有的变量,你可以:

1{{ dump() }}

要打印出变量的键:

1{{ dump(_context|keys) }}

PS: 这里的_context是一全局变量,指当前模版中所有的上下文和变量,比如通过theme函数传递的变量,preprocess函数处理的变量,或者调用set设置的变量。

全局变量:

_context 当前模版中所有的上下文和变量_charset 只当前的编码方式

慎用dump()

dump()函数虽然可以输出所有的变量,但是却带来了巨大的内存消耗,故你可以循环_context来查看所有的键:

12345<ol> {% for key, value in _context %} <li>{{ key }}</li> {% endfor %}</ol>

接下来再加上一些条件判断,就可以看到你需要的变量了。

Drupal8主题

模版命名惯例

Drupal是按照一定的命名惯例来加载模版的,这就方便开发者可以覆盖原有的模版。当然,记得清除缓存。

HTML

HTML模版提供了包括head,title以及body标签等基础结构的html页面。

基础模版:html.html.twig(位于:core/modules/system/templates/html.html.twig)

下面是一些你可以覆盖的基础模版的例子:

html—internalviewpath.html.twightml—node—id.html.twightml.html.twig

Page

模版名称模式:page—[front|internal/path].html.twig

基础模版:page.html.twig(位于: core/modules/system/templates/page.html.twig)

下面是page模版的模版建议,举个例子“.twigpage—node—1.html.twigpage—node.html.twigpage.html.twig

Regions

模版名称模式:region—[region].html.twig

基础模版:region.html.twig(位于: core/modules/system/templates/region.html.twig)

当一个页面的区域中有内容时,系统会从区块系统或者一个类似于hook_page_build()的方法中调用区域模版。

Blocks

模版名称模式:block—[module|-delta]].html.twig

基础模版:block.html.twig (位于: core/modules/block/templates/block.html.twig)

block—module—delta.html.twigblock—module.html.twigblock.html.twig

这里的module就是模块名,delta是模块给区块设置的内部id标识

Nodes

模版名称模式:node—[type|nodeid]—[viewmode].html.twig基础模版:node.html.twig (位于: core/modules/node/templates/node.html.twig)

模版建议:

node—nodeid—viewmode.html.twignode—nodeid.html.twignode—type—viewmode.html.twignode—type.html.twignode—viewmode.html.twignode.html.twig

Taxonomy terms

taxonomy-term.html.twigtaxonomy-term--<vocab-machine-name>.html.twignode–<nid>.html.twig, ie: node–<nid>.html.twig, ie: taxonomy-term--ingredients.html.twigtaxonomy-term--<tid>.html.twig, ie: taxonomy-term--1.html.twig

Fields

field–<field-type>.html.twig, ie: field–long-text.html.twigfield–<field-name>.html.twig, ie: field–phone-number.html.twig

Comments

comment.html.twigcomment-wrapper.html.twig

Forums

模版名称模式:forums—[[container|topic]—forumID].html.twig

基础模版: forums.html.twig (位于: core/modules/forum/templates/forums.html.twig)

模版建议:

论坛容器:forums—containers—forumID.html.twigforums—forumID.html.twigforums—containers.html.twigforums.html.twig论坛主题内容forums—topics—forumID.html.twigforums—forumID.html.twigforums—topics.html.twigforums.html.twig

PHPTemplate与Twig主题范例的比较

接下来,看下PHPTemplate与Twig的区别。

关于Twig

Twig是基于php的编译模版语言。当你的页面需要渲染显示的时候,Twig引擎会找到对应的模版并把它编译成php模版,存放在sites/default/files/php_storage/目录下。

1.Docblock

PHPTemplate:

123456<?php /** * @file * File description */?>

Twig:

123456{# /** * @file * File description */#}

2.文件和函数名

PHPTemplate文件:node—article.tpl.phpTwig文件:node—article.html.twig

PHPTemplate函数:theme_node_links()Twig文件:node-links.html.twig

3.变量

输出一个变量

PHPTemplate:

1<div class="content"><?php print $content; ?></div>

Twig:

1<div class="content">{{ content }}</div>

输出一个哈希键值

PHPTemplate:

1<?php print $item['#item']['alt']; ?>

Twig:

1{{ item['#item'].alt }}

变量赋值

PHPTemplate:

1<?php $custom_var = $content->comments; ?>

Twig:

1{% set custom_var = content.comments %}

数组初始化

PHPTemplate:

123<?php $args = array('!author' => $author, '!date' => $created);?>

Twig:

1{% set args = {'!author': author, '!date': created} %}

4.条件判断

PHPTemplate:

1<?php if ($content->comments): endif; ?>

Twig:

1{% if content.comments %} {% endif %}

PHPTemplate:

1<?php if (!empty($content->comments)): endif; ?>

Twig:

1{% if content.comments is not empty %} {% endif %}

PHPTemplate:

1<?php if (isset($content->comments)): endif; ?>

Twig:

1{% if content.comments is defined %} {% endif %}

PHPTemplate:

1<?php if ($count > 0): endif; ?>

Twig:

1{% if count > 0 %} {% endif %}

5.控制结构

PHPTemplate:

1<?php foreach ($users as $user) {} ?>

Twig:

1{% for user in users %} {% endfor %}

6.过滤

check_plain:

PHPTemplate:

1<?php print check_plain($title); ?>

Twig:

1{{ title|striptags }}

Translate:

PHPTemplate:

1<?php print t('Home'); ?>

Twig:

1{{ 'Home'|t }}

Translate with substitutions:

PHPTemplate:

123<?php print t('Welcome, @username', array('@username' => $user->name));?>

Twig:

1{{ 'Welcome, @username'|t({ '@username': user.name }) }}

Drupal8 Twig(采用trans标签扩展)

1234{% set username = user.name %}{% trans %} Welcome, {{ username }}{% endtrans %}

implode:

PHPTemplate:

1<?php echo implode(', ', $usernames); ?>

Twig:

1{{ usernames | join(', ') }}

PHPTemplate的例子中$usernames需要是一个字符串数组。原生的Twig也需要$usernames是一个字符串数组。但是Drupal8中的twig还可以是一个可以渲染的数组对象。这就是Drupal8中的twig与原生twig的本质区别。Drupal8中的twig可以“打印”出纯文本和可渲染的数组。

举个例子:

12{% set numbers = [{'#markup': 'One'}, {'#markup':'Two'}, {'#markup':'Three'}] %}{{ numbers }}

在上面的例子中,每一个数据项都是以逗号相隔的。但是,输出的结果却是:

1OneTwoThree

Escape:

PHPTemplate:

1<?php echo check_plain($title); ?>

原生Twig:

1{{ title|e }}

Drupal 8 Twig2:

1{{ title }}

7.空白

123<div class="body"> {{- block.content -}}</div>

类似于

1<div class="body">{{ block.content }}</div>

debug twig模版

twig模版引擎提供了一个debug工具。

启用debugging

在sites/default/services.yml启用Twig Debugging。

设置debug变量为true

123parameters: twig.config: debug: true

自动加载编译的模版

出于性能考虑,Twig模版被编译成一个PHP类存放在磁盘上,但这意味着默认情况下,你的模版不会在你做出更改时发生刷新。为了使Twig模版可以自动刷新,启用services.yml中的deubg选项。欲知详情,参见:.twig| |-node.html.twig

下面,介绍一下主题文件夹中的通用文件。

*.info.yml

主题必须包含*.info.yml文件,此文件定义了meta数据,样式,还有区块和区域信息。

*.libraries.yml

*.libraries.yml文件用于主题启用时需要加载的定义js和css库,详情点击这里

*.breakpoints.yml

响应式设计相关的设置,详见:*.breakpoints.yml设置

*.theme

*.theme文件是一个php文件,包含了所有的逻辑处理代码和输出前的预处理。

css/

一个好的建议就是将css文件存放在“css”自目录下。

js/

存放着主题需要的js文件。

images/

存放主题需要的图片

screenshot.png

主题的预览图

templates/

核心主题Bartik的目录结构:

1234567891011121314151617181920212223242526272829303132333435363738394041|-bartik.breakpoints.yml|-bartik.info.yml|-bartik.libraries.yml|-bartik.theme|-color| |-color.inc| |-preview.css| |-preview.html| |-preview.js|-config| |-schema| | |-bartik.schema.yml|-css| |-base| | |-elements.css| |-components| | |-block.css| | |-book.css| | |-breadcrumb.css...| |-colors.css| |-layout.css| |-maintenance-page.css| |-print.css|-images| |-add.png| |-required.svg| |-tabs-border.png|-logo.svg|-screenshot.png|-templates| |-block--search-form-block.html.twig| |-block--system-branding-block.html.twig| |-block--system-menu-block.html.twig| |-block.html.twig| |-comment.html.twig| |-field--taxonomy-term-reference.html.twig| |-maintenance-page.html.twig| |-node.html.twig| |-page.html.twig| |-status-messages.html.twig

为主题添加区域

为主题添加区域需要两步:

在主题文件.info.yml中添加区域的meta-data编辑page.html.twig文件打印新的区域

info文件中添加区域

区域定义成ragions键的子元素:

12345# Regionsregions: header: 'Header' content: 'Content' footer: 'Footer'

Region 键应是个字符串,可以包含下划线“_”。

模版中添加区域

为了显示区域中的内容,你需要确定新的区域也添加到了page.html.twig模版中。

例如:

1header: 'Header'

模版中输出:

1{{ page.header }}

此外,你可以把它们当成是Twig模版的普通变量,可以在任何需要的地方打印输出。

默认区域

可以在page.html.twig模版文档中查阅默认的区域

page.headerpage.primary_menupage.secondary_menupage.highlightedpage.helppage.contentpage.sidebar_firstpage.sidebar_secondpage.footerpage.breadcrumb

Drupal8主题中添加样式和js

与Drupal7主题的区别

有四个比较重要的区别:

去掉了THEME.info文件,取而代之的是THEME.info.yml文件THEME.info.yml文件中的stylesheets属性不复存在,改为库的方式引入THEME.info.yml文件中的scripts属性不复存在,改为库的方式引入每一个页面的js只在需要时才加载,默认情况下,Drupal对于匿名用户不会需要js。这意味着,jquery不会再在每个页面自动加载了。因此,如果你的主题需要jquery或者其它的js,你需要通过“声明依赖关系”来告诉Drupal这个js需要加载

加载css/js的步骤:

将css或者js保存到一个文件定义一个包含js和css文件的“library”在钩子中,把这个库追加给渲染数组

定义一个库

在主题文件夹中创建*.libraries.yml文件来添加库(假设你的主题名称是fluffiness,那么文件名就是fluffiness.libraries.yml)。每一个库,都是css和js文件的详情列表:

1234567cuddly-slider: version: 1.x css: theme: css/cuddly-slider.css: {} js: js/cuddly-slider.js: {}

这个例子中,假设cuddly-slider.js文件位于主题的js子目录中。

然后,需要记住的是,默认情况下,Drupal8不会在每一个页面加载jquery;只在需要时加载。因此,我们需要自己声明,主题的cuddly-slider库依赖jQuery。

因此,为了保证上例的js/cuddly-slider.js可用,我们需要更新下:

123456789cuddly-slider: version: 1.x css: theme: css/cuddly-slider.css: {} js: js/cuddly-slider.js: {} dependencies: - core/jquery

当然,库也可以只包含css,或者只包含js。大部分的主题可能会有一个global-styling库,用于全局加载样式文件:

12345678global-styling: version: 1.x css: theme: css/layout.css: {} css/style.css: {} css/colors.css: {} css/print.css: { media: print }

而且,正如你所想,库中定义的css的顺序就是将来加载的顺序。

在Drupal7中,你可以把媒体查询属性(screen, print, all)作为stylesheets属性的子键,而现在你可以把它当作值定义,例如:

1css/print.css: { media: print }

现在默认情况下,所有的js文件都在页脚加载。

12345678js-header: header: true js: header.js: {}js-footer: js: footer.js: {}

你得设置header属性为true。

覆盖扩展库

那些定义在*.libraries.yml文件中的库可以通过主题的*.info.yml文件中的libraries-override和libraries-extend项进行覆写和扩展。

libraries-override

libraries-override是定义在库中,主题用来操作css/js的一种方式,包括删除、替换或者删除css/js。

123456789101112131415161718libraries-override: # Replace an entire library. core/drupal.collapse: mytheme/collapse # Replace an asset with another. subtheme/library: css: theme: css/layout.css: css/my-layout.css # Remove an asset. drupal/dialog: css: theme: dialog.theme.css: false # Remove an entire library. core/modernizr: false

libraries-extend

libraries-extend为主题提供了一种可以修改库的方式。比如,添加额外的主题依赖的库。

12345# Extend drupal.user: add assets from classy's user libraries.libraries-extend: core/drupal.user: - classy/user1 - classy/user2

追加库到页面中

在Twig模版中追加库

通过调用twig的方法,attach_library()可以在twig模版中追加库,例如:

12{{ attach_library('fluffiness/cuddly-slider') }}<div>Some fluffy markup {{ message }}</div>

追加给所有的页面

为了所有页面都加载这个库,需要在主题的*.info.yml文件中,libraries键的下面声明:

12345name: Exampletype: themecore: 8.xlibraries: - fluffiness/cuddly-slider

为一组页面添加库

在大部分情况下,你可能不希望所有的页面加载你的库,而是部分页面加载。举个例子来说,你可能只想在某个特定的区块中加载,或者用户访问某个节点类型时加载。

主题可以通过实现THEME_preprocess_HOOK()方法达到这个效果。

例如,你想要在维护页面追加你的库,“HOOK”就是“maintenance_page”,然后你的方法就是:

12345<?phpfunction fluffiness_preprocess_maintenance_page(&$variables) { $variables['#attached']['library'][] = 'fluffiness/cuddly-slider';}?>

你也可以为主题的其它hook做同样的事情,当然你的函数中也可以包含逻辑处理。

重要提示:最通用的用法是根据当前的路由来加载库:

12345678<?phpfunction fluffiness_preprocess_page(&$variables) { $variables['#cache']['contexts'][] = 'route'; if (\Drupal::routeMatch()->getRouteName() === 'entity.node.preview') { $variables['#attached']['library'][] = 'fluffiness/node-preview'; }}?>

添加可定制的js

在某些情况下,你可能想要根据某些php计算信息来加载js。

在这种情况下,像之前一样,创建一个js文件并追加进来,再通过drupalSettings(替换Drupal7中的Drupal.settings)追加一些js设置项并由追加的js文件读取这些设置项。然后,为了使drupalSettings在我们的js文件中生效,我们得像引入jQuery一样操作:我们得在依赖中定义。

就像这样:

1234567cuddly-slider: version: 1.x js: js/cuddly-slider.js: {} dependencies: - core/jquery - core/drupalSettings

以及

123456<?phpfunction fluffiness_page_attachments_alter(&$page) { $page['#attached']['library'][] = 'fluffiness/cuddly-slider'; $page['#attached']['drupalSettings']['fluffiness']['cuddlySlider']['foo'] = 'bar';}?>

这样cuddly-slider.js就可以访问drupalSettings.fluffiness.cuddlySlider.foo了(这里 === ‘bar’)。

在模版中使用attributes

attributes是一个在每个twig模版中都有效的对象。attributes用来存储所有的父容器的相关属性,并提供有用的方法给开发者处理这些数据。

Attribute的方法

attributes.addClass()

单个类:

1<div{{attributes.addClass('my-class')}}></div>

多个类:

1234567{% set classes = [ 'red', 'green', ]%}<div{{ attributes.addClass(classes) }}></div>

将会输出:

1<div class="red green"></div>.

html标签与twig语法之间不能有任何空格!

attributes.removeClass()

123{#classes = [ 'red', 'green', 'blue' ] #}<div{{ attributes.addClass(classes).removeClass('green') }}></div>

将会输出:

1<div class="red blue"></div>

attributes.setAttribute($attribute, $value)

1<div{{ attributes.setAttribute('id', 'myID') }}></div>

将会输出:

1<div id="myID"></div>

attributes.removeAttribute($attribute, $value)

1<div{{ attributes.removeAttribute('id') }}></div>

attributes.hasClass($class)

123{% if attribute.hasClass(‘myClass') %} {# do stuff #}{% endif %}

其它有用的代码片段

链式

123{% set classes = ['red', 'green', 'blue'] %}{% set my_id = 'specific-id' %}{% set image_src = 'https://www.drupal.org/files/powered-blue-135x42.png' %}1<img{{ attributes.addClass(classes).removeClass('green').setAttribute('id', my_id).setAttribute('src', image_src) }}>

将会输出:

1<img id="specific-id" class="red blue" src="https://www.drupal.org/files/powered-blue-135x42.png">

使用without filter

1<div class=”myclass {{ attributes.class }}”{{attributes|without(‘class’) }}></div>

Drupal6, 7, 8主题区别

这里列出的是比较重要的Drupal8中的主题变化

Drupal8默认输出html5除了jQuery2.x之外,Drupal8还引入更多的前端框架,例如:Modernizr,Underscore.js,以及Backbone.js。Drupal8引入了Twig,替换了原来的默认模板引擎PHPTemplate。Drupal8处于性能考虑,默认启用了类似css、js合并之类的默认特性。在drupal6和drupal7中,可以调用drupal_add_css()和drupal_add_js()函数添加css或者js,现在替换成了在渲染数组中追加#attached属性调用库的方法。Drupal8不再支持IE6、7、8,启用jQuery2.0,支持现代HTML5/CSS3浏览器。Drupal8不支持那些不支持SVG的浏览器(包括IE8和安卓浏览器2.3)。Drupal8的css中,减少了id的使用。Drupal8的css结构(文件结构)基于SMACSS和BEMDrupal8将预处理函数中的css类移到了Twig模版中。

文章标签:

本文链接:『转载请注明出处』