Drupal 是如何工作的? [关闭]

Posted

技术标签:

【中文标题】Drupal 是如何工作的? [关闭]【英文标题】:How Drupal works? [closed] 【发布时间】:2010-11-07 07:14:03 【问题描述】:

谁能提供 Drupal 7 控制流的架构概览?也许在关于如何生成页面的流程图的意义上。关于 Drupal 的工作原理,您会建议咨询哪些其他资源?

【问题讨论】:

【参考方案1】:

Drupal 在这方面可能会令人困惑,部分原因是它具有相对较深的函数堆栈。尽管它是程序 php,但它在其架构中纯粹是事件/侦听器驱动的,并且在主 PHP 脚本中没有简单的“流程”供您查看。我最近做了a presentation on this very subject,幻灯片发布在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。'

【讨论】:

FWIW,在 D7 中有点不同(theme('page') 消失了,符号现在缓存在代码注册表中),但整体过程保持不变。 很好的解释伊顿,感谢您在这里闲逛。我的问题是,除了将 var_dump 放在每个模块中以找出发生了什么之外,您如何调试所有这些? 好问题。这取决于您要调试的内容。安装开发模块可以为您提供一些有用的工具。该步骤(在大多数情况下)是确定负责构建给定页面的模块。 hook_menu() 将 urls/paths 映射到模块,这样可以提供帮助。然后确定它的菜单回调在做什么——调用 drupal_get_form() 来构建表单,或者调用 theme('some_custom_thing') 来构建 html 等。注意使用诸如 drupal_alter() 或 module_invoke_all() 之类的函数来触发其他事件模块也是... 我发现这非常有用。你知道 Drupal 7 有何不同吗? D7 更新:(另见) drupal.org/node/350780【参考方案2】:

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

简而言之,所有的调用/urls/requests 都由 index.php 提供服务,它通过包含各种包含文件/模块来加载 Drupal,然后调用模块中定义的适当函数来服务 request/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 客户端)。

【讨论】:

【参考方案3】:

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

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

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

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

【讨论】:

【参考方案4】:

这取决于您所寻求的理解深度;如果您对 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 文件。

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

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

【讨论】:

【参考方案7】:

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

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

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

【讨论】:

【参考方案8】:

这里是新的贡献者,迟到了 2 年 ;-)

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

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

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

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

【讨论】:

以上是关于Drupal 是如何工作的? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

DRUPAL:Spamspan 模块……它是如何工作的?

初学者 Drupal 用户最常见的陷阱是啥? [关闭]

如何在Drupal 8中使用Dompdf? [关闭]

使用 Drupal 或 PHP 的身份证阅读器 [关闭]

如何将背景音乐添加到 Drupal 7 [关闭]

Drupal:最好的论坛模块? [关闭]