菜单(Menu)
前面曾经简单提到过Drupal的菜单, 今天稍微深入来探讨一下. 菜单能用来显示导航信息, 我们安装的系统, 默认安装有3个菜单, 让我们查看一下数据库吧, 以menu_开头的总共有三张表: menu_custom, menu_links, menu_router. 其中menu_custom表存放菜单定义信息, 但想知道他们都是由哪个模块定义的麽? 别忘记了菜单如果要显示就是区块哦, 打开区块表(blocks)看看吧. Here it is! 用户模块(User Module)定义了Navigation菜单(没看数据库我以为是系统模块(System Module)定义的呢), 菜单模块(Menu Module)定义了Primary linksSecondary links两个空菜单. 所以从表现层来看, 一个菜单就对应一个区块(Block), 它被放置在页面的某个区域(Region)来显示给用户进行导航.
其实Drupal的菜单机制不仅要能把导航显示给用户, 更重要的是在用户点击这些导航的时候, 能够准确快速定位到相应的业务逻辑. 有人会问, 难道这也是个问题吗? 要知道导航其实都对应他们具体的URI, 而传统的URI的定位是先按目录结构找处理文件, 然后根据Request参数对应业务逻辑,同时还要在业务逻辑中判断用户权限; 而Drupal有一套自己的内部路径, 它是基于模块化构建的, 与目录结构一点关系也没有了, 所以必须要有一套机制能在URI和业务逻辑间进行映射, 而Drupal的菜单机制就是完成这项工作的, 用户点击菜单项链接时, Drupal解析出内部路径, 并根据内部路径找到对应的业务逻辑, 并再完成判断权限后转交给业务逻辑进行处理, 这个过程Drupal称之为分发.
Drupal核心框架中的菜单api(includes/menu.inc文件)实现了上述功能, 它成功地解决了动态URL路径到具体执行函数间映射, 对用户屏蔽了系统预定义的Request参数的复杂处理, 在路径和功能建立了必由之路. 啥也别说了, 看看分发函数的实现:

<?php
>
function menu_execute_active_handler($path = NULL) {
  if (_menu_site_is_offline()) {
    return MENU_SITE_OFFLINE;
  }
  if (variable_get('menu_rebuild_needed', FALSE)) {
    menu_rebuild();
  }
  if ($router_item = menu_get_item($path)) {
    if ($router_item['access']) {
      if ($router_item['file']) {
        require_once($router_item['file']);
      }
      return <strong>call_user_func_array($router_item['page_callback'],$router_item['page_arguments']);</strong>
    }
    else {
      return MENU_ACCESS_DENIED;
    }
  }
  return MENU_NOT_FOUND;
}
?>

用户URL请求到达后, Drupal先进行Bootstrap初始化, 然后调用分发函数menu_execute_active_handler, 该函数根据解析出的内部路径, 在系统构建出的菜单路由表中查找, 如果找到则判断可访问权限, 然后调用路由表中对应路径注册的Pange_callback回调函数, 这样就完成一个URL请求到具体页面逻辑的过程. 流程非常简单清晰, 学过计算机原理, 熟悉中断调用的对这流程应该都非常熟悉.

菜单路由(Menu Router)
Drupal系统主要依据menu_router表构建系统菜单路由, 而menu_router表的内容则是基于各模块的hook_menu钩子来获得, 这个钩子较少被调用, 一般都在模块初始化或其他菜单需要重建的情况. 下面我们选一段Book模块的menu钩子代码来看看:

<?php
function book_menu() {
  $items = array();
  $items['admin/content/book/%node'] = array(               
    'title' => 'Re-order book pages and change titles',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('book_admin_edit', 3),
    'access callback' => '_book_outline_access',
    'access arguments' => array(3),
    'type' => MENU_CALLBACK,
    'file' => 'book.admin.inc',
  );
}
?>

book模块所定义的所有菜单路由表由一个二维数组表示, 其中每一项为一个菜单路由, 下标即为该路由的入口路径, 这里为'admin/content/book/%node'. 菜单路由项的各属性看命名已经比较清晰了, 想了解可以参考Drupal.
我们看上面用的路径中包含一段'%node', 对了这是使用了通配符, 比如你访问admin/content/book/7的时候, 会自动把node7装载进来, 太多细节, 就此打住.

菜单项(Menu Item)
保存在menu _links表中, 定义了每个条目的名字, 条目间父子关系, 对应路径, 所属模块等等很多属性, 它应不像菜单路由项一样隐藏在背后干活, 它是可见的; 同时由于有通配符的存在, 它与菜单路由项并不是一一对应关系. (比较奇怪的是默认的Navigation菜单是用户模块创建的, 但它里面的所有菜单项却是系统模块定义的.) 既然router表的数据从钩子函数而来, 那link表是否也有对应的钩子呢, 实际上菜单项是由菜单模块(Menu Moudle)进行管理, 通过GUI界面直接配置, 当然菜单API也有对应接口,比如menu_link_save(). ( 实在不行你直接写数据库也行, 那不就是hack菜单模块了麽)

Drupal6.x增加了两个alter钩子函数对应这两张表, 它们是hook_menu_alter()<--->menu_router, hook_menu_link_alter()<--->menu_links, 它们主要处理内容变化时的处理逻辑, 由Drupal_alter()函数调用, 看代码注释说这个函数非常Ugly, 要在7中把它解决掉. 头晕了一天, 今天也没有心思再看下去了.

总结:
现在我们有点明白Drupal的菜单机制了吧, 它主要由菜单api和菜单模块组成, 提供一种框架, 使得其他功能模块能过注册菜单路由项, 并在分发过程中, 通过该菜单路由表完成用户页面请求(具体URL)到功能模块业务逻辑的映射. 当然Drupal的菜单机制还有很多复杂特性, 来日方长, 有空继续钻研.

另:有一点不明白的是menu_router为啥要用钩子函数, 不能直接用初始数据库脚本麽, 不过我也没研究过安装过程, 似乎好像没有一个地方用了数据库脚本, 有人清楚这一块麽?

转载于:https://www.cnblogs.com/liuye/archive/2013/01/15/2861199.html

从头学习Drupal--基本架构三相关推荐

  1. 从头学习Drupal--基本架构二

    前面说了, Drupal的逻辑层由一个核心框架和一系列的功能模块(Module,可以看成插件)构成, 框架与模块间的协调就是通过钩子机制来实现, 所以钩子机制是Drupal模块化系统的关键.什么是钩子 ...

  2. 深度学习未来发展的三种学习范式:混合学习,成分学习和简化学习

    深度学习是一个很大的领域,其核心是一个神经网络的算法,神经网络的尺寸由数百万甚至数十亿个不断改变的参数决定.似乎每隔几天就有大量的新方法提出. 然而,一般来说,现在的深度学习算法可以分为三个基础的学习 ...

  3. 入门深度学习,先看看三位顶级大牛Yann LeCun、Yoshua Bengio和Geoffrey Hinton的联合综述

    [编者按]深度学习领域的三位大牛Yann LeCun.Yoshua Bengio和Geoffrey Hinton无人不知无人不晓.此前,为纪念人工智能提出60周年,Yann LeCun.Yoshua ...

  4. 基于实时深度学习的推荐系统架构设计和技术演进

    简介:整理自 5 月 29 日 阿里云开发者大会,秦江杰和刘童璇的分享,内容包括实时推荐系统的原理以及什么是实时推荐系统.整体系统的架构及如何在阿里云上面实现,以及关于深度学习的细节介绍 本文整理自 ...

  5. 学习之模块架构 DotNetNuke 6

    前面的博客介绍了: 如何在本地安装DNN6 如何创建DNN模块 博客园原文地址 :  学习之模块架构 DotNetNuke 6 这篇博客主要是讲模块的架构和加载,以及模块与DotNetNuke门户网站 ...

  6. 从头学习计算机网络_如何从头开始构建三层神经网络

    从头学习计算机网络 by Daphne Cornelisse 达芙妮·康妮莉丝(Daphne Cornelisse) 如何从头开始构建三层神经网络 (How to build a three-laye ...

  7. (转)MyBatis框架的学习(二)——MyBatis架构与入门

    http://blog.csdn.net/yerenyuan_pku/article/details/71699515 MyBatis框架的架构 MyBatis框架的架构如下图:  下面作简要概述: ...

  8. 【自然语言处理】【多模态】OFA:通过简单的sequence-to-sequence学习框架统一架构、任务和模态

    OFA:通过简单的sequence-to-sequence学习框架统一架构.任务和模态 <Unifying Architectures, Task, and Modalities through ...

  9. RT-1052学习笔记 - GPIO架构分析

    RT-1052学习笔记 - GPIO架构分析 一.RT1052之GPIO与IOMUX 二.GPIO架构分析 分析GPIO的外设框架 库函数操作 1.初始化MUX 2.初始化PAD 3.初始化GPIO外 ...

最新文章

  1. 河科大c语言上机实验答案,2016年河南科技学院信息工程学院C语言上机编程考研复试题库...
  2. java多线程aqs实现工具类_Java并发多线程 - 并发工具类JUC
  3. linux 问题 value too large for defined data type 解决方案
  4. WinForm(C#)CheckedlistBox绑定数据,并获得选中的值(ValueMember)和显示文本(DisplayMember...
  5. CentOS7 /etc/profile 添加环境变量重开终端后不生效
  6. 【剑指offer】面试题60:n个骰子的点数(Java)
  7. JEECG - 基于代码生成器的J2EE智能开发框架 续四: 查询条件SQL生成器设计思路
  8. 在IIS8添加WCF服务支持
  9. Hbase PleaseHoldException错误
  10. android程序root权限,android应用程序中应用root权限
  11. 华为WLAN产品命名规范
  12. C++ const和static const的区别
  13. 直播app源码开发,聊天服务器的搭建教程
  14. LU分解法python程序代码
  15. 关于怎么计算某一年的第一天为周几的问题
  16. windows上配置深度学习(李沐-动手学深度学习)
  17. Python实用功能之pdf文件转png图片数据
  18. H5移动端禁止长按保存图片
  19. 读懂 Android 中的代码混淆
  20. 基于ACO蚁群优化的机器人避障算法仿真

热门文章

  1. spring boot 处理自定义注解
  2. Node.js中的不安全跳转如何防御详解
  3. 如何在原生微信小程序中实现数据双向绑定
  4. C# 解析 Json数据
  5. Hadoop MapReduce编程 API入门系列之join(二十六)
  6. 第一周Linux微职位
  7. Hadoop2.x介绍与源代码编译
  8. CGCS2000 VS WGS84
  9. django-dynamic-scraper(DDS)配置中的一些问题
  10. Struts2,在Action中使用session