Drupal如何工作?[关闭]


151

有人可以提供Drupal 7控制流程的体系结构概述吗?也许从关于页面生成方式的流程图的意义上讲。您建议就Drupal的工作方式咨询什么其他资源?


1
题?那你为什么不问自己:-)
liori

我认为当时没有堆栈溢出的方式。:)
杰里米·法兰西

2
Drupal社区一直在寻找帮助文档的人员。如果文档笨拙或教程la脚,为什么不帮忙呢?:)
Rimian

4
文档需要理解..这需要文档或有很多经验
Damon

Answers:


160

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 /路径,因为它会触发“菜单”事件(hook_menu)并收集所有响应的元数据插件。(“我将处理url'news / recent',这是需要构建该页面时要调用的函数...”)内容仅被保存,因为Drupal的FormAPI负责构建页面并触发“表单已提交”事件,模块需要响应。每小时进行维护是因为触发了hook_cron(),并且任何将mymodulename_cron()作为函数名称的模块都将调用其函数。

其他所有内容最终都只是细节-重要细节,只是该主题的变化。index.php是控制器,菜单系统确定“当前页面”是什么,并且在构建该页面的过程中会触发许多事件。插件模块可以插入这些事件并更改工作流/提供其他信息/等。这也是许多Drupal资源专注于制作模块的部分原因。没有模块,Drupal实际上不会做任何事情,只是说:“有人要一页!是否存在?没有?好吧,我将提供404服务。”


1
FWIW,在D7中有所不同(theme('page')消失了,并且符号现在已缓存在代码注册表中),但是整个过程保持不变。
FGM

2
很好的解释伊顿,谢谢你在这里闲逛。我的问题是,除了将var_dump放入每个模块中以了解发生了什么以外,您如何调试所有这些?
Brian G

3
好问题。这取决于您要调试的内容。通过提供一些有用的工具,可以安装devel模块。步骤(在大多数情况下)是确定哪个模块负责构建给定页面。hook_menu()将url /路径映射到模块,以便提供帮助。然后确定其菜单回调在做什么-调用drupal_get_form()来构建表单,或调用theme('some_custom_thing')来构建HTML等。注意使用诸如drupal_alter()或module_invoke_all()之类的函数来触发其他事件模块也一样...
Eaton

我发现这个超级有用。您知道Drupal 7有何不同吗?
高度

D7更新:(另请参见) drupal.org/node/350780
dreftymac 2010年

63

Drupal页面服务机制

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

简而言之,所有调用/ URL /请求均由index.php提供服务,该索引通过包含各种包含文件/模块并随后调用模块中定义的适当函数来服务于请求/ URL,从而加载Drupal。

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

引导过程

Drupal通过执行一系列引导阶段来对每个请求进行引导。这些阶段在bootstrap.inc中定义,并按照以下各节的说明进行。

初始化配置

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

早期页面缓存

在需要高度可伸缩性的情况下,可能甚至在尝试数据库连接之前就需要调用缓存系统。早期的页面缓存阶段使您可以包含一个PHP文件(包括include()),该文件包含一个名为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客户端)。


20

伊顿的答案提供了很好的概述。(我是新来的,所以我无法修改他,因此无法发表评论。)

对我来说,最残酷的“ aha”时刻是通过index.php,然后通过模块的瀑布(首先是核心,然后是站点)来实现所有事情。要扩展核心功能,请不要重写它。而是将模块复制到/ sites / all / modules /或/ sites / [您的站点] / modules中,并扩展该功能,或在这些位置创建一个新模块。主题相同。模块目录也可以包含显示代码,例如tpl,css等形式。

如果您习惯使用更严格的MVC类型框架(如Rails,Django等),那么所有这些都会使您感到困惑。模块可能会混入很多显示代码,如果您正在查看其他人的模块或模板,则最终会倒退遍历整个堆栈。那就是使用PHP的美丽/痛苦。

具有讽刺意味的是,“仅仅构建一个应用程序”可能是最糟糕的学习方法。Drupal开箱即用地做很多事情,直到您弄清楚控制流程为止,它还是很晦涩的。例如,tpl文件中没有任何内容可以告诉您带有有趣名称(例如l())的函数的来源。


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文件。


5

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


5

关于该主题的最佳书籍是“ Pro Drupal开发”和“使用Drupal”。

“ Pro Drupal开发”包括几个不错的流程图以及每个Drupal API(表单,主题等)的详尽摘要。它的目的是对制作自己的模块和主题的人特别有启发性,但对于想要了解Drupal的PHP普通开发人员来说,它具有很大的价值。除此之外,我还为我建立的每个站点创建了一个自定义模块,目的是获得对诸如在各种表单上有选择地隐藏字段的控制(通常为了简化节点表单,用户),因此最好将这些知识放在您的帽子下。

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


5

这个(对于Drupal 6)和这个(对于Drupal 7)是一个很好的Drupal体系结构概述。如果您想了解更多细节,那么我将开始编写大多数文档。尝试高水平的学习而又没有具体的实现要比尝试一些困难得多。


4

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

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

要扩展核心功能,请不要重写它。而是将模块复制到/ sites / all / modules /或/ sites / [您的站点] / modules中,并扩展该功能,或在这些位置创建一个新模块。主题相同。

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.