Drupal8入坑指南
为什么选择 Drupal?
我们先来看看3大开源 CMS 系统各自的主要特点:
WordPress:
- 用户友好,非常适合非开发人员
- 免费和付费的插件、主题数量庞大
- 拥有最活跃的社区(WP市场占有率60%以上)
- 优秀的本地化支持
Joomla:
- 注重用户友好的同时,兼顾了自定义开发,平衡了 WP 和 Drupal 各自的优点
- 优秀的本地化支持
Drupal:
- 强大的自定义开发支持,非常适合开发人员
- 支持CLI命令行工具
其实只要稍微作对比就会发现,如果没有特殊的需求,开发的首选依然是 WordPress。但是也显而易见,用户友好的代价就是缺乏一定的灵活性,比如说我已经规划好了整个网站的架构,然后发现如果需要用 WordPress 来实现的话,需要各种各样的插件支持,这样反而提升了开发的复杂度。这也是为什么我会选择 Drupal。如果说 WordPress 是一台完美组装好的强力赛车,那 Drupal 就是一辆底盘优秀,但是其余部件都要自己选择并组装的赛车,其突出的特点就是可配置性。
从哪里获取资料?
尽管 Drupal 的功能非常强大,但是它所占的市场规模实在是太小了(3%左右),因此国内的相关资料少得可怜,百度直接找到的活跃社区,就是Drupal中国,但是上面的学习资料太散了,不适合入门学习,后来只能回归官方文档。学习了几天之后,感觉非常吃力,不仅仅因为是英文,而且官方的文档就是一本说明书,不是教程。类似的还有社区文档,社区的文档的参考价值比官方文档高,不过依然不够完善,进一步搜索后,才找到了我真正需要的东西:
初探——掌握 Drupal 的使用方法
《Beginning Drupal 8》:Todd Tomlinson 写的一本用来入门 Drupal 的书,Google 搜索 PDF 可以直接找到,有概念有实践。粗略浏览一遍就能对 Drupal 有一个整体的印象,之后再结合 Drupal 的社区文档进行学习,就容易消化多了。
进阶——掌握 Drupal 的开发方法
开发资料,最基础的依然是社区开发文档,比如Theming Drupal 8,然后配合 Packt上的两本书:《Drupal 8 Theming with Twig》和 《Matering Drupal 8》,就可以掌握最基本的开发方法和步骤了。
可惜的是,到目前为止,并没有找到有价值的中文资料,有待补充。当然,除了文档和书籍,官方论坛也是个好地方,一般用来解决开发过程中遇到的各式各样的问题。
上手 Drupal
关于开发环境一类的搭建就不多赘述了,能选择 Drupal 进行开发的,基本也都是老手了。唯一需要注意的一点是,注意 php 和 mysql 的配置,比如我是 Windows 平台上用 XAMPP 搭建的环境,就参考 Quick install Drupal with XAMPP on Windows 进行配置。
Drupal 的目录结构
了解一个项目最好的出发点,就是先了解它的组成结构。前面也说到了,通过 Composer 直接安装的项目,Drupal 的主要文件位于 “/web” 目录下,而 “/vendor” 目录下则是这个 Drupal 发行版所需的各种依赖。Drupal 的主要文件结构如下所示:
1 |
|
安装 Drupal
建议使用 Composer 安装 Drupal,以便随后可以通过 Composer 管理整个项目。
1 |
|
需要注意的是,由于新版本的 Drupal 考虑到安全性,把网站根目录和依赖分别放在两个不同的目录(/web 和 /vendor)中,因此在服务器部署的时候,需要注意文件所在位置,这个坑比较麻烦,这里举个例子:
比如我有一个项目需要部署在一个共享云主机上面,由于只能通过 FTP 访问网站根目录,没法配置 Apache,因此只有两种方法,一是使用官网直接下载的版本(core 和 vendor 在同一目录下),二是通过 RewriteRule 改写当前路径。考虑到安全问题,我们还是使用根目录和依赖分开的目录结构,为此需要配置 .htaccess 文件(假设目前根目录为 drupal):
1 |
|
这样一来,只要我访问 example.com 就相当于访问 example.com/web。不过此时还有可能会遇到问题,需要在 “site/default/setting.php” 种加上一句:
1 |
|
如果不这样的话,"/web/index.php" 就会在根目录被 Rewrite 一次,导致找不到页面,而至于 “/web/.htaccess”,可以完全不用管它。
和 WordPress 一样,通过直接访问站点的方式进行安装,除此之外 Drupal 还支持通过 Drush 进行命令行安装。安装的第一步需要选择语言,建议先默认使用英文安装,中文安装有时候会失败,原因是下载超时,当然也有解决方法:
在 core/lib/Drupal/Core/Http/ClientFactory.php
50行的位置,修改超时或者设置代理即可解决问题:
1 |
|
如果默认使用英文安装,则可以在安装完成后手动启动 Language 和 Interface Translation 两个模块,接着去官网下载语言包,在 Interface Translation 的配置中导入下载的语言包,最后去 Language 配置中设置默认语言为中文即可。
介绍常用功能
为了方便理解,以下演示的语言都设置为英文。安装完成后会自动跳转到首页,此时可以在页头看到一个工具栏,这个工具栏只有登录后才会显示。在 Drupal 中,登录后台最直接的方式就是在 URL 后面加上 “/user”,登录之后会跳转到用户的个人页面,此时便可以通过工具栏访问不同的栏目了。
Drupal 的主要功能区如上图所示:
- Content(内容):管理文章和媒体
- Structure(结构):管理区块、内容类型、菜单、分类、视图
- Appearance(外观):管理主题
- Extend(扩展):管理模块
- Configuration(配置):配置站点、语言等
- People(人员):管理用户
- Reports(报告):查看更新以及日志
- Help(帮助):查看模块帮助
内容类型
作为CMS,首先最关心的应该是如何添加页面和内容。内容的话,首先添加站点所需的内容类型,Drupal 特别优秀的一点就是对内容类型的字段操作。
添加自定义字段后,可以通过 “Manage form display” 管理添加的这些字段在创建内容时显示的可见性、顺序以及格式(Format:用来限定字段的数据类型、显示格式等),而 “Manage display” 则是管理对应内容类型展示给用户的内容的可见性、顺序以及格式。
页面和区块
对于页面,Drupal 有两种常见的创建页面方式:视图(Views) 和页面管理器(Page Manager UI)。二者都调用了 Page Manager 模块,区别在于视图是集成到 Drupal 核心的,安装好 Drupal 之后就可以使用,而页面管理器是一个额外的模块,需要额外安装。无论通过哪种方式创建页面,都需要调用该页面的模板(page–suggestion.html.twig,后面主题开发会介绍),模板上会指定内容显示的区域(Region),光创建好页面是没有用的,还需要指定访问该页面的 URL 以及在页面对应的区域中布置区块(Block):
页面的模板往往是由主题指定的,因此不同的主题会有不同的区块布局(Block Layout)。区块分为系统自带的区块(Core、System、Menus等)和自定义区块(Custom),网页上的所有内容,都是区块,举个列子:在内容(Contnet)中创建的文章,其实都是通过 “Main page content” 这个系统区块添加到页面中的。因此,如果你有一段 HTML 代码需要添加到页面的对应位置,那么在自定义区块库(Custom block library)中添加一个自定义区块即可(补充:由于区块本质也是内容,因此在自定义区块库中也可以创建自己想要的区块类型,比如我可以指定某类区块都是富文本而另一类区块都是纯 HTML。)
至此,Drupal 添加页面和内容的流程就很清晰了:
视图
前面说了,创建页面可以用视图或者页面管理器,实际上视图是页面管理器的超集,因此只需掌握如何使用视图创建页面就够了。
从视图(Views)进来,就可以发现,实际上包括 Drupal 的后台页面在内,都是一个个的视图组成的。创建视图也是学习 Drupal 的路上遇到的第一个硬骨头。选择 “Add view” 来添加一个视图,我们可以指定视图要显示的内容以及视图呈现的形式(Display):作为一个页面或者作为一个区块,之后就会进入视图的详细设置页面。接下来以首页(Frontpage)为例来看看视图中具体的设置。
首先是显示(Display),这是视图最好用的功能,你可以给选定内容不同的显示方式,比如页面(Page)、区块(Block)、摘要(Teaser)这三种最常用的显示方式(除此之外还有附件(Attachment)、嵌入(Embed)、实体引用(Entity Reference)以及信息聚合(Feed)),如果有特殊需要,你还可以自定义一种显示方式( 在 Structure->Display modes ->View modes 中)。这个功能最常见的应用,就是在首页只显示文章的摘要(Teaser),点击标题后进入文章页查看全文(Default)。
注:默认显示(Default)一般是不可见的,如果需要更改默认显示,要先在视图的设置中勾选上:Always show the master (default) display
视图里面一般需要配置的项目有:
- 格式(FORMAT)
- Format:设置内容显示的方式,Unformatied list 就是用
<div>
标签包裹内容; - Show:设置显示具体的内容(Content)还是只显示字段(Field),如果显示具体内容,后面还可以设置内容的显示方式。
- Format:设置内容显示的方式,Unformatied list 就是用
- 字段(FIELDS)
- 如果上面设置只显示字段,那么就可以在这里添加需要显示的字段。
- 过滤器(FILTER)
- 过滤内容,可以多个条件组合使用。
- 排序(SORT)
- 对内容显示进行排序。
- 页面/块设置(PAGE/BLOCK SETTINGS)
- 设置页面的路径(即 URL)、所属菜单等信息。
- 分页(PAGER)
- Use pager:设置是否使用分页器以及分页的样式、每页显示的数量等;
- More link:设置是否在分页器后显示 “more” 链接,点击该链接即查看全部内容。
- 上下文过滤器(CONTEXTUAL FILTERS)
- 配合当前 URL 中提供的信息进行内容过滤。
- 联系(RELATIONSHIPS)
- 和其他实体建立联系,比如和分类(Taxonomy)建立联系,然后便可以配合上下文过滤器实现通过分类名称来过滤内容。
分类和菜单
说到分类(Taxonomy)和菜单(Menus),如果有使用 WordPress 的经验,那么应该对这两个东西不陌生了。同样还是举例子吧,在 Drupal 中,可以使用分类来实现文章标签的功能:
首先在分类页面下新建一个词汇 “标签(Tags)”,之后再这个词汇下建立多个术语(terms),对应不同的文章类型。之后在对应文章的文章类型中,新增一个字段,用来添加这个标签:
最后在创建文章的时候,选择或者填写预先设置好的标签即可。假如还需要给不同的标签创建一个归档页,则利用上面讲到的视图:新建一个视图,过滤器选择对应分类术语即可。(实际上 Drupal 自带归档页视图,只不过没有启用,在视图页的 “Disabled” 栏目下面)
Drupal 默认有 5 个菜单,这 5 个菜单只可以编辑不可以删除:
以管理菜单(Administration )为例:
可以通过 “Add link” 添加菜单项目,然后通过菜单项前面的符号拖动菜单项排序和分级。每个菜单项本质是其对应页面的链接。因此我们现在可以更新一下上面说到的 Drupal 添加页面和内容的流程:
介绍常用模块(不间断更新)
系统管理
- Allowed Formats:添加内容类型的 Body 字段时,指定可用的文本编辑器。
- Business Rules:Drupal 8.X 以上版本对 Rules 模块的替代,用来实现根据不同“条件(Condition)”执行对应的“动作(Action)”,比 Rules 模块好用。
- Structure Sync:允许导出菜单、分类、自定义区块。
- Configuration Partial Export:允许到处单个或者多个配置。
- Admin Toolbar:允许 Toolbar 显示下拉菜单。
- Rename Admin Paths:允许重命名登录和后台管理页面的路径,默认为 “/user” 和 “/admin”。
- Display Suite:允许对内容类型的字段进行分栏,提供多栏显示的功能。
内容创作
- Blazy:提供图片懒加载功能。
- Gutenburg:WordPress 古腾堡编辑器。
- Views Infinite Scroll:无限滚动分页。
- Metatag:提供页面或者内容的元信息,方便 SEO。
- Layout Builder:提供可视化的显示方式编辑(Manage display)
- ImageWidgetCrop:提供图片剪切的功能。
- Background Images Formatter:格式化 CSS 中使用的背景图片。
主题开发
名词解释
- Entity:Drupal 管理的一切内容都是实体(Entity),包括 Nodes、Users 、Comments等;
- Nodes:Drupal 上的所有内容均被存储并视为结点(Node),Node 可以是任何内容,例如页面,文章;
- Field:可以添加到元素的数据字段,例如标题,正文,注释,标签,图像;
- theme hook suggestions:Drupal确定模板文件可以使用的名称的过程,类似于 Wordpress 决定使用哪个页面模板的过程。
主题的文件结构
自定义的主题建议放在 /themes/custom/
下面 (非必须)
1 |
|
编写 *.info.yml
文件
必需属性:
1 |
|
可选属性:
1 |
|
其他还有 hidden
、engine
等可选属性
设置区域块
设置区域块包含两个步骤:
- 将区域元数据添加到 THEMENAME.info.yml 文件;
- 将定义的区域输出到 page.html.twig 文件。
注:如果在主题中声明任何区域,将会使默认区域无效,因此这种情况下需要自己声明所有区域
默认区域:
- page.header
- page.primary_menu
- page.secondary_menu
- page.highlighted
- page.help (dynamic help text, mostly for admin pages)
- page.content (main content of current page)
- page.sidebar_first
- page.sidebar_second
- page.footer
- page.breadcrumb
首先需要在 *.info.yml
中指定所需的 regions
,比如:
1 |
|
之后就需要在 templates/page.html.twig
中添加定义的区域:
1 |
|
page
为所定义区域的命名空间
加载 CSS 和 JS 资源
加载 CSS 和 JS 包含两个步骤:
- 在
* .libraries.yml
文件中定义所有库; - 将库附加到所有页面或者特定页面。
首先在 *.libraries.yml
中声明需要使用的库(CSS/JS),如下所示,{}
内部可以定义各种参数,具体参考:Defining Libraries: Options & Details:
注意:
*.info.yml
中libraries
所定义的库会应用于所有主题页面
1 |
|
在这个例子中,cuddly-slider.js 储存在 js/
目录中,cuddly-slider.css 储存在 css/
目录中。默认情况下,Drupal 8 不再在所有页面上加载 jQuery,因此需要指定 dependencies
,由于 Drupal 的 Core 包含了 jQuery,因此只需要指定 core/jquery
即可,对于其他需要使用的依赖,按照 resource/library
的格式引用即可
关于 css
中的 theme
,表示 css 文件所属的样式类型,共有 5 种不同的样式类型,不同的样式类型有不同的 CSS 权重:
base
: CSS reset/normalize plus HTML element styling. Key assigns a weight ofCSS_BASE = -200
layout
: macro arrangement of a web page, including any grid systems. Key assigns a weight ofCSS_LAYOUT = -100
component
: discrete, reusable UI elements. Key assigns a weight ofCSS_COMPONENT = 0
state
: styles that deal with client-side changes to components. Key assigns a weight ofCSS_STATE = 100
theme
: purely visual styling (“look-and-feel”) for a component. Key assigns a weight ofCSS_THEME = 200
将库应用到所有页面
在 *.info.yml
的 libraries
中添加所需的全局库:
1 |
|
将库应用到部分页面
在 *.theme
文件中使用钩子函数 THEME.preprocess_HOOK()
,其中 THEME
是主题名,HOOK
是需要加载库的页面名:
1 |
|
注意:除了上述方法,还可以在 Twig 模板中使用
attach_library()
函数加载库
设置断点
注意:仅当 Drupal 需要与断点进行交互时才需要将 CSS 断点写到
*.breakpoints.yml
文件中,例如在使用“响应式图像”模块的情况下。
主题和模块可以通过创建一个名为 *.breakpoints.yml
的配置文件来定义断点。该文件中每一块内容代表一个断点,每个断点包括一个标识符,例如 bartik.mobile
,随后是定义这个断点的属性:
label
:断点的标签mediaQuery
:媒体查询语句weight
:断点的权重(顺序)multipliers
:支持的像素分辨率乘数
最小 min-width
的断点应具有最小的权重,而最大 min-width
的断点应具有较大的权重。默认情况下,模块将按从最小到最大的顺序对断点进行排序,即移动端优先的原则。
断点可以进行分组。例如布局断点和图像断点分开,详细使用方法去看文档。
使用 Twig 模板
Twig 模板的使用方法参考:Creating and Using Templates
Twig 基本语法
变量
- 定义变量
1 |
|
调用变量:{{ foo.bar }}
- Filter
变量可以通过过滤器修改,类似于 shell,通过“|”管道符分隔。可以链接多个过滤器,一个过滤器的输出将作为下一个过滤器的输入
1 |
|
函数
1 |
|
注:命名参数还可以用来跳过一些不想更改其默认值的参数
控制结构
1 |
|
引用其他模板
1 |
|
模板继承
模板继承使您可以构建基本的“骨架”模板,该模板包含站点的所有常见元素,并定义子模板可以覆盖的 block
1 |
|
子模版:
1 |
|
调试 Twig 模板
调试 Twig 模板有两种方法:使用 Devel 模块或者使用 twig_xdebug 模块配合 xdebug 调试。Devel 主要用来检查Twig 模板的变量,实际调试过程中,还是 xdebug 好用,因为可以在 IDE 中查看变量和调用栈。因此我选择主要用 xdebug 进行调试,Devel 辅助查看变量。
使用 xdebug 调试 Twig 需要的步骤:
-
安装 xdebug 并在 php.ini 中开启:
- 把
phpinfo()
输出的信息复制到 https://xdebug.org/wizard 获取安装方式
1
2
3
4zend_extension=D:\xampp\php\ext\php_xdebug-2.9.4-7.4-vc15-x86_64.dll
[xDebug]
xdebug.remote_enable=1启动之后,xdebug 默认监听
127.0.0.1:9000
- 把
-
浏览器安装 Xdebug Helper (Google Chrome & Firefox)
-
安装
twig_xdebug
模块并开启1
2composer require --dev drupal/twig_xdebug
drush en -y twig_xdebug -
在 twig 文件中使用
{{ breakpoint() }}
-
如果需要使用
dump()
函数检查变量,则需要本地开启debug
模式:drupal site:mode dev
注意:经过测试,使用
drupal site:mode dev
之后,还是需要drupal cr
才能看到效果,使用 Disable Drupal 8 caching during development 的第一种方法即使用“settings.local.php”的方法在当前版本(version 8.8.5)确认有效
Twig模板命名约定
-
HTML 模板:html.html.twig (core/modules/system/templates/html.html.twig)
提供 HTML 页面基本结构的标记,包括
<head>
,<title>
和<body>
标记 -
Page 模板:page.html.twig (core/modules/system/templates/page.html.twig)
提供每个单独页面的模板,比如首页:
page--front.html.twig
匹配模式:page–[front|internal/path].html.twig
-
Regions 模板:region.html.twig (core/modules/system/templates/region.html.twig)
匹配模式:region–[region].html.twig
-
Blocks 模板:block.html.twig (core/modules/block/templates/block.html.twig)
匹配模式:block–[module|–[delta].html.twig
-
Nodes 模板:node.html.twig (core/modules/node/templates/node.html.twig)
匹配模式:node–[content-type|nodeid]–[viewmode].html.twig
-
Taxonomy terms 模板:taxonomy-term.html.twig (core/modules/taxonomy/templates/taxonomy-term.html.twig)
匹配模式:taxonomy-term–[vocabulary-machine-name|tid].html.twig
-
Fields 模板:field.html.twig (core/modules/system/templates/field.html.twig)
匹配模式:field–[[type|name]|[entity-type]–[field-name|content-type]].html.twig
-
Comments 模板:comment.html.twig (core/modules/comment/templates/comment.html.twig)
匹配模式:comment–[comment-field-name]–[node-type].html.twig
-
Views 模板:views-view.html.twig (core/themes/stable/templates/views/views-view.html.twig)
匹配模式: views-view–[viewid]–[view-display-id].html.twig
views-view–[viewid]–[view-display-type].html.twig
views-view–[view-display-type].html.twig
views-view–[viewid].html.twig
另外还有 Forums、Maintenance Page、Search result 等页面的模板。
注:添加模板后,必须重新构建缓存,以使 Drupal 使用新模板:
drush cr
覆盖模板
为了覆盖已有的模板,需要:
- 找到想要覆盖的模板文件;
- 将模板文件从其原本位置复制到对应主题内;
- 按需修改模板。
有时只需要覆盖模板的某一部分内容,这时可以使用 Theme hook suggestions:
hook_theme_suggestions_HOOK(array $variables)
hook_theme_suggestions_alter(array &$suggestions, array $variables, $hook)
hook_theme_suggestions_HOOK_alter(array &$suggestions, array $variables)
模板中使用属性对象
许多 Twig 模板具有一个或多个作为变量传递的属性对象。默认情况下,以下属性对象变量可用于所有模板:attributes
,title_attributes
和 content_attributes
1 |
|
常用方法:
1 |
|
创建一个新的属性对象:
1 |
|
可以在 .theme
文件中对属性对象进行预处理或者修改:
1 |
|
创建高级主题设置
高级主题设置即在“管理/外观/设置”里面对应主题名的设置页面,通常由 THEME.theme
或者 theme-settings.php
两个文件来进行控制,使用 Forms API 添加需要进行设置的项目。以 THEMENAME_form_system_theme_settings_alter(&$form, $form_state)
为例:
1 |
|
默认值需要定义在 config/install/THEME.settings.yml
文件中:
1 |
|
随后在所有主题的 PHP 文件中,可通过:
1 |
|
获取这个值,如果需要在 Twig 文件中使用,需要先在 THEME.theme
文件中定义:
1 |
|
之后就可以在 Twig 文件中直接使用 {{ foo_example }}
获取变量值
附录1:常用命令
- 安装 Drupal
1 |
|
- 安装 drush
1 |
|
- 更新模块
1 |
|
- 列出已安装模块
1 |
|
- 快速创建 Drupal 实例
1 |
|
附录2:实用技巧
- 在 JS 中判断当前页面是否为主页:
先在 * .libraries.yml
文件中加载 drupalSettings
:
1 |
|
然后在 JS 文件中调用 drupalSettings.path.isFront
:
1 |
|