Drupal 是如何工作的?

有人能提供 Drupal 7控制流的架构概述吗?也许是关于如何生成页面的流程图。关于 Drupal 如何工作,您建议咨询哪些额外的资源?

34824 次浏览

通过将 drupal.php 代码导入 NetBeans 项目,我学到了很多东西。 然后,您可以运行 netbeans 调试器,并观察页面的不同阶段是如何组合在一起的。

这个 (对于 Drupal 6)和 这个(对于 Drupal 7)是一个非常好的 Drupal 架构概述。如果你想要更多的细节,然后我会开始写一些 大部分的文档是好的。如果没有具体的东西去实现,试图从高层次的细节去学习它将比尝试一些东西要困难得多。

Drupal 在这方面可能会令人困惑,部分原因是它有一个相对较深的函数堆栈。尽管它是过程式 PHP,但它的架构是纯事件/侦听器驱动的,而且在主 PHP 脚本中没有简单的“流”可供查看。我最近做了 关于这个问题的报告,幻灯片发布在幻灯片共享,但一个快速的高级摘要可能是有用的。

  • Drupal 的 index.php 文件充当前端控制器。所有页面都通过管道传递,用户请求的“实际”url/path 作为参数传递给 index.php。
  • Drupal 的路径路由器系统(MenuAPI)用于将请求的路径与给定的插件模块匹配。该插件模块负责构建页面的“主要内容”。
  • 一旦构建了主页面内容,index.php 就调用主题(‘ page’,$content) ,将内容传递给 Drupal 的主题/皮肤系统。在那里,它被包装在侧栏/标题/小部件等中。.
  • 呈现的页面然后交还给 apache,并将其发送回用户的浏览器。

在整个过程中,Drupal 和第三方插件模块发出事件,并监听它们的响应。Drupal 称之为“钩子”系统,它是使用函数命名约定实现的。例如,“ blog”模块可以通过实现一个名为 blog _ user ()的函数来拦截与之相关的“ user”。用 Drupal 的说法,就是 Hook _ user ()

它有点笨重,但是由于 PHP 的特殊性(它保存了所有加载函数的内部哈希表) ,它允许 Drupal 通过迭代已安装的插件列表来快速检查监听器。对于每个插件,它可以在适当命名的模式上调用 function _ vis () ,并在函数存在时调用它。(“我正在触发‘ login’事件。“ mymodule _ login”函数是否存在?我宣布死亡。“ yourmodule _ login”是否存在?没有吗?‘ nextmodule _ login’怎么样?”等等)再一次,有点笨重,但它工作得很好。

在 Drupal 中发生的所有 都是因为触发了其中一个事件。MenuAPI 只知道不同的插件模块处理哪些 urls/路径,因为它触发“ menu”事件(hook _ menu)并收集所有响应的元数据插件模块。(“我会处理 url‘ news/recent’,这里是需要构建页面时调用的函数... ...”)内容只能被保存,因为 Drupal 的 FormAPI 负责构建页面,并触发‘ a form was  表单被提交’事件,以便模块作出响应。每小时一次的维护是因为 hook _ cron ()被触发,任何以 mymodulename _ cron ()作为函数名的模块都会调用它的函数。

其他的一切最终都只是细节——重要的细节,但这个主题的变化。Php 是控制器,菜单系统决定“当前页面”是什么,在构建该页面的过程中会触发许多事件。插件模块可以连接到这些事件并改变工作流/提供额外的信息等。这也是许多 Drupal 资源专注于制作模块的部分原因。如果没有模块,Drupal 实际上不会做任何事情,只会说,‘有人请求一个页面!’!它真的存在吗?没有吗?好吧,我给你404。'

伊顿的回答提供了一个很好的概述

对我来说,这个残酷的“啊哈”时刻是意识到一切都是通过 index.php,然后通过模块瀑布(先是核心,然后是站点)发生的。要扩展核心功能,不要重写它。取而代之的是将模块复制到/site/all/module/或/site/[你的主页]/module 中并扩展 THAT,或者在这些位置创建一个新模块。主题也一样。模块目录也可以包含显示代码,如 tpl、 css 等。

如果你已经习惯了更严格的 MVC 类型框架,比如 Rails,Django 等等,那么所有这些都会让你感到困惑。模块可以混合许多显示代码,如果您正在查看其他人的模块或模板,那么最终将在堆栈中向后遍历。这就是在 PHP 中工作的美妙之处/痛苦之处。

具有讽刺意味的是,“仅仅构建一个应用程序”可能是最糟糕的学习方式。Drupal 做了这么多开箱即用的工作,在您弄清楚控制流之前,这些工作都很模糊。例如,tpl 文件中没有任何内容告诉您具有像 l ()这样有趣名称的函数来自哪里。

关于这个主题最好的书是《 Pro Drupal Development 》和《使用 Drupal 》

“ Pro Drupal Development”包括几个不错的流程图和每个 Drupal API 的全面总结(表单、主题等)。它对于制作自己的模块和主题的开发人员特别具有指导意义,但对于想要了解 Drupal 的普通 PHP 开发人员来说,它具有很大的价值。除此之外,我已经为我建立的每个网站创建了一个自定义模块,只是为了获得额外的控制权,比如在各种表单上选择性地隐藏字段(你通常想要这样做是为了简化最终用户的节点表单) ,所以有这些知识在你的帽子下面是很好的。

“使用 Drupal”针对的是那些想知道如何构建像图库、博客和社交网站这样的好东西的站点开发人员。本文介绍了几个用例,并展示了如何配置现有模块来完成每个任务。在这个过程中,它让你熟悉基本的附加模块“ Content Construction Kit”(CCK)和“ View”,如何制作自定义块和模板,以及维护 Drupal 站点的详细信息。我推荐这本书,特别是对于那些想赶上进度并立即使用 Drupal 的人。在这个过程中,您了解了 Drupal 的内部组织。

这取决于你需要多深的理解; 如果你对 php 有很好的了解,我建议通读代码本身,从 index.php 开始,然后进入 include/bootstrap.inc,然后是该目录中的其他一些脚本。

关键包括文件:

  • Menu.inc 对于理解整个系统是如何工作的非常重要,因为它处理了很多 URL 到内容的隐式映射。
  • Inc 拥有构成 API 基础的大多数神秘函数。
  • Inc 处理 Eaton 提到的 hook 调用
  • Inc 处理表单显示、提交和处理
  • 主题公司处理演示文稿。

模块/目录中还有一些关键功能; 特别是,模块/node/node.module 构成了节点系统的基础,节点系统通常用于封装站点内容。

一般来说,这段代码的注释非常清晰。在注释中使用 Doxygen 标记意味着代码实际上是规范文档。

使用能够快速跳转到函数定义的编辑器也有助于实现这一点。将 vim 与 ctag 结合使用对我来说很有用; 您必须告诉 ctag 建立索引。公司。模块等文件作为 php 文件。

新的贡献者在这里,2年后的谈话; -)

回复 https://stackoverflow.com/a/1070325/1154755

要扩展核心功能,不要重写它,而是复制模块 扩展至/网站/所有/模组/或/网站/[你的主页]/模组 或者在这些地方创建一个新的模块。主题也是一样的。

事实上,我从来没有复制一个核心模块来更新它。 Drupal 钩子应该是你所需要的全部。

对于主题,是的,有时候这是唯一的方法,但是通常,你可以建立一个子主题来得到你需要的结果。

Drupal Page Serving Mechanism

要了解 Drupal 的工作原理,您需要了解 Drupal 的页面服务机制。

简而言之,所有调用/urls/request 都由 index.php 提供,它通过包含各种包含文件/模块来加载 Drupal,然后调用在模块中定义的适当函数来提供 request/url。

这里是书中的摘录,Pro Drupal Development,它解释了 Drupal 的引导过程,

引导过程

Drupal 通过一系列引导阶段在每个请求上自我引导。这些阶段在 bootstrap.inc 中定义,并按照以下部分中的描述继续进行。

初始化配置

这个阶段填充 Drupal 的内部配置数组并建立基本 URL ($base _ url).Php 文件通过 include _ once ()解析,并应用在其中建立的任何变量或字符串重写。有关详细信息,请参阅文件 site/all/default/default.setings.php 的“变量覆盖”和“字符串覆盖”部分。

早期页面缓存

在需要高可伸缩性的情况下,缓存系统可能需要 在尝试数据库连接之前调用 包含(使用 include ())一个 PHP 文件,该文件包含一个名为 page _ cache _ 的函数 快速路径() ,它接管并返回内容到浏览器 通过将 page _ cache _ fastpath 变量设置为 TRUE 以及要包含的文件来启用 是通过将 cache _ inc 变量设置为文件的路径来定义的 举个例子。

初始化数据库

在数据库阶段,确定数据库的类型,初始连接为 将用于数据库查询的。

基于主机名/IP 的访问控制

Drupal 允许在每个主机名/IP 地址的基础上禁止主机 阶段,快速检查请求是否来自被禁主机; 如果是, 拒绝访问。

初始化会话处理

Drupal 利用了 PHP 的内置会话处理,但是覆盖了一些处理程序 实现数据库支持的会话处理。会话被初始化 表示当前用户的全局 $user 对象 也在这里初始化,不过为了提高效率,并非所有属性都可用(它们是在需要时通过显式调用 user _ load ()函数添加的)。

延迟页面缓存

在后期页面缓存阶段,Drupal 加载足够的支持代码,以确定是否 不为页缓存中的页提供服务。这包括将数据库中的设置合并到初始化配置阶段创建的数组中,以及加载或解析模块代码。如果会话指示请求是由匿名用户发出的,并且启用了页缓存,则从缓存返回该页并停止执行。

语言决定

在语言确定阶段,Drupal 的多语言支持被初始化,并根据站点和用户设置决定使用哪种语言为当前页面提供服务。Drupal 支持几种确定语言支持的替代方案,例如路径前缀和域级语言协商。

路径

在路径阶段,加载处理路径和路径别名的代码 解析并处理内部 Drupal 路径缓存和 查找。

满了

这个阶段通过加载一个公共函数主题库来完成引导过程 支持,并支持回调映射,文件处理,Unicode,PHP 图像工具包,表单 创建和处理、邮件处理、自动排序表和结果集分页。设置了 Drupal 的自定义错误处理程序,并加载了所有启用的模块。最后,Drupal 触发 init 钩子,这样模块就有机会在正式处理请求开始之前得到通知。

一旦 Drupal 完成了引导,框架的所有组件就可以使用了。 现在是时候接收浏览器的请求并将其传递给 PHP 函数 URL 和处理它们的函数之间的映射是使用 同时处理 URL 映射和访问控制的回调注册表 他们的回调使用菜单钩子(更多细节,见第4章)。

当 Drupal 确定存在一个回调时,浏览器的 URL Request 成功映射,并且用户具有访问该回调的权限时,控制权交给回调函数。

处理要求

回调函数执行处理和累积完成请求所需的数据所需的任何工作。例如,如果一个内容请求,比如 < a href = “ http://example.com/”rel = “ norefrer”> http://example.com/ 接收到 q = node/3后,URL 被映射到 node.module 中的函数 node _ page _ view ()。 进一步的处理将从数据库中检索该节点的数据,并将其放入数据结构中。那么,主题化时间到了。

数据主题化

主题化涉及到转换已经检索、操作或创建的数据 转换为 HTML (或 XML 或其他输出格式)。 Drupal 将使用管理员的主题 已经选择给网页正确的外观和感觉。然后,结果输出被发送到 Web 浏览器(或其他 HTTP 客户端)。