153

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

4

8 回答 8

164

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

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

在整个过程中,Drupal 和第三方插件模块正在触发事件,并监听它们的响应。Drupal 将此称为“钩子”系统,它是使用函数命名约定实现的。例如,“博客”模块可以通过实现名为 blog_user() 的函数来拦截“用户”相关的内容。在 Drupal 中,这称为hook_user()

它有点笨拙,但是由于 PHP 的一个怪癖(它保留了所有加载函数的内部哈希表),它允许 Drupal 只需遍历已安装插件的列表即可快速检查侦听器。对于每个插件,它可以在适当命名的模式上调用 function_exists(),如果存在则调用该函数。(“我正在触发 'login' 事件。'mymodule_login' 函数存在吗?我会调用它。'yourmodule_login' 存在吗?不存在吗?'nextmodule_login' 怎么样?”等等)再一次,有点笨拙,但它效果很好。

Drupal 中发生的一切都是因为其中一个事件被触发。MenuAPI 只知道不同插件模块处理哪些 url/路径,因为它会触发 'menu' 事件 (hook_menu) 并收集所有响应的元数据插件模块。(“我会处理 url 'news/recent',这是在需要构建该页面时调用的函数......”)内容只会被保存,因为 Drupal 的 FormAPI 负责构建页面并触发模块要响应的“表单已提交”事件。每小时维护一次是因为 hook_cron() 被触发,并且任何以 mymodulename_cron() 作为函数名的模块都会调用它的函数。

其他一切最终都只是细节——重要的细节,但该主题的变化。index.php 是控制器,菜单系统确定“当前页面”是什么,并且在构建该页面的过程中会触发许多事件。插件模块可以挂钩这些事件并更改工作流程/提供附加信息/等。这也是如此多的 Drupal 资源专注于制作模块的部分原因。没有模块,Drupal 实际上除了说‘有人要页面!它存在吗?不?好的,我会提供 404。

于 2009-07-01T14:58:03.613 回答
63

Drupal 页面服务机制

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

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

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

引导过程

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

初始化配置

此阶段填充 Drupal 的内部配置数组并建立站点的基本 URL ($base_url)。settings.php 文件通过 include_once() 进行解析,并应用在那里建立的任何变量或字符串覆盖。有关详细信息,请参阅文件 sites/all/default/default.settings.php 的“变量覆盖”和“字符串覆盖”部分。

早期页面缓存

在需要高度可扩展性的情况下,可能需要在尝试连接数据库之前调用缓存系统。早期页面缓存阶段允许您包含(使用 include())一个 PHP 文件,该文件包含一个名为 page_cache_fastpath() 的函数,该函数接管并将内容返回给浏览器。通过将 page_cache_fastpath 变量设置为 TRUE 来启用早期页面缓存,并且通过将 cache_inc 变量设置为文件的路径来定义要包含的文件。有关示例,请参阅有关缓存的章节。

初始化数据库

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

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

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

初始化会话处理

Drupal 利用 PHP 的内置会话处理,但用自己的覆盖一些处理程序来实现数据库支持的会话处理。会话在会话阶段被初始化或重新建立。代表当前用户的全局 $user 对象也在此处初始化,但为了提高效率,并非所有属性都可用(它们是在需要时通过显式调用 user_load() 函数来添加的)。

后期页面缓存

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

语言确定

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

小路

在路径阶段,会加载处理路径和路径别名的代码。这个阶段能够解析人类可读的 URL,并处理内部 Drupal 路径缓存和查找。

满的

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

一旦 Drupal 完成引导,框架的所有组件都可用。是时候接受浏览器的请求并将其交给处理它的 PHP 函数了。URL 和处理它们的函数之间的映射是使用一个回调注册表来完成的,该注册表负责 URL 映射和访问控制。模块使用菜单挂钩注册它们的回调(更多详细信息,请参阅第 4 章)。

当 Drupal 确定存在浏览器请求的 URL 成功映射到的回调并且用户有权访问该回调时,将控制权交给回调函数。

处理请求

回调函数执行处理和累积满足请求所需的数据所需的任何工作。例如,如果接收到http://example.com/q=node/3等内容请求 ,则将 URL 映射到 node.module 中的函数 node_page_view()。进一步的处理将从数据库中检索该节点的数据并将其放入数据结构中。然后,是时候进行主题化了。

主题化数据

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

于 2013-01-21T07:38:54.270 回答
20

伊顿的回答提供了一个很好的概述。(我是新来的,所以我不能修改他,因此评论。)

对我来说残酷的“啊哈”时刻是通过 index.php 实现一切,然后通过模块的瀑布(首先是核心,然后是站点)。扩展核心功能不要重写它。而是将模块复制到 /sites/all/modules/ 或 /sites/ [yoursite] /modules 并扩展它,或者在这些地方创建一个新模块。主题也一样。模块目录也可以包含显示代码,形式为 tpl、css 等。

如果您习惯于更严格的 MVC 类型框架,例如 Rails、Django 等,那么这一切都会变得有些混乱。模块可以混入大量显示代码,如果您正在查看其他人的模块或模板,您最终会在堆栈中倒退。这就是使用 PHP 工作的美妙/痛苦。

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

于 2009-07-01T17:18:31.017 回答
7

这取决于您正在寻找的理解有多深;如果您对 php 有很好的了解,我建议您通读代码本身,从 index.php 开始,然后继续阅读 include/bootstrap.inc,然后是该目录中的一些其他脚本。

关键包含文件:

  • menu.inc 对于理解整个系统的工作方式非常重要,因为它处理了很多 URL 到内容的隐式映射。
  • common.inc 具有构成 API 基础的大部分原本神秘的函数。
  • module.inc 处理伊顿提到的钩子调用
  • form.inc 处理表单显示、提交和处理
  • theme.inc 处理演示。

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

总的来说,该代码的注释非常好且清晰。在注释中使用 Doxygen 标记意味着代码实际上是规范文档。

使用可以快速跳转到函数定义的编辑器也有助于执行此操作。将 vim 与 ctags 结合使用对我有用;您必须告诉 ctags 将 .inc、.module 等文件索引为 php 文件。

于 2010-03-21T00:12:56.760 回答
6

This (for Drupal 6) & this (for Drupal 7) 是一个非常好的drupal 架构概述。如果您想要更多详细信息,那么我将开始编写大多数文档都不错的东西。试图在没有具体目标的情况下以高层次的细节学习它比尝试一些东西要困难得多。

于 2009-07-01T14:30:32.530 回答
5

我通过将 drupal .php 代码导入 NetBeans 项目来了解负载。然后,您可以运行 netbeans 调试器并观察页面的不同阶段。

于 2009-07-01T11:39:38.567 回答
5

关于该主题的最佳书籍是“Pro Drupal Development”和“Using Drupal”。

“Pro Drupal 开发”包括几个漂亮的流程图和对每个 Drupal API(表单、主题等)的全面总结。它旨在对制作自己的模块和主题的人特别有指导意义,但对想要了解 Drupal 的普通 PHP 开发人员具有很大的价值。除此之外,我为我构建的每个站点都创建了一个自定义模块,只是为了获得对诸如选择性隐藏各种表单上的字段之类的额外控制(您通常希望这样做是为了简化节点表单以供结束-用户),因此最好掌握这些知识。

“使用 Drupal”面向想要了解如何构建画廊、博客和社交网站等好东西的网站开发人员。它介绍了几个用例,并展示了如何配置现有模块来完成每项工作。在此过程中,它使您熟悉基本的附加模块“内容构建工具包”(CCK)和“视图”,如何制作自定义块和模板,以及维护 Drupal 站点的细节。我特别推荐这本书给那些想要快速上手并立即使用 Drupal 的人。在此过程中,您将了解 Drupal 的内部组织。

于 2009-07-08T02:06:10.400 回答
4

这里的新贡献者,对话晚了 2 年 ;-)

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

扩展核心功能不要重写它。而是将模块复制到 /sites/all/modules/ 或 /sites/ [yoursite] /modules 并扩展它,或者在这些地方创建一个新模块。主题也一样。

实际上,我从来不需要复制核心模块来更新它。Drupal Hooks 应该是你所需要的。

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

于 2012-01-17T19:57:06.550 回答