当我们访问node/1这个路径的时候,会发生什么呢?首先我们看到的路径,通常是这样的形式:
此时,我们是启用了简洁URL的,如果没有启用的话,可以配置,网上有比较多的教程。不启用简洁URL的路径,则是这样的:
http://www.example.com/?q=node/1
是的,与前者相比,多了一个“?q=”。
这是我们看到的路径,也是Apache看到的路径。可能有人会问,难道Drupal看到的路径不是这个样子的?是的,Drupal看到的路径不是这个样子。那么可能还会有人继续问,Drupal看到的路径是什么?Drupal看到的路径是这个样子的:
http://www.example.com/index.php?q=node/1
别名模式下:
http://www.example.com/index.php?q=aboutus
我们在本地做一个实验,分别访问路径:
http://localhost/snt6/index.php?q=node/1
http://localhost/snt6/?q=node/1
我们看到了什么?我们看到的内容是完全一样的。aboutus和node/1之间是别名关系,可以说是一一对应的关系,Drupal在数据库里面,有张表,用来存储这样的对应关系。当我们访问路径aboutus的时候,它自动的就找到了对应的内部路径node/1。这个我们比较好理解。对于很多人,他刚开始的时候,并不知道Drupal看到的路径是:
http://www.example.com/index.php?q=node/1
很多人可能有个误区,感觉我们看到的路径,就是Drupal看到的路径。这样理解是有问题的。
当我们使用
http://www.example.com/?q=node/1
访问页面时,Apache帮我们做了转换,它将这个路径转为了:
http://www.example.com/index.php?q=node/1
在简洁URL下,apache将路径http://www.example.com/node/1最终也会转为:
http://www.example.com/index.php?q=node/1
有人可能会问,你是怎么知道这个转换的?在Drupal的根目录下,有这样一个文件.htaccess。我们打开这个文件,里面有这行代码:
# Pass all requests not referring directly to files in the filesystem to
# index.php. Clean URLs are handled in drupal_environment_initialize().
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^ index.php [L]
这段代码就是做这个转换的,这段代码里面的RewriteCond %{REQUEST_FILENAME} !-f是什么意思?这个我也不知道。我们只需要知道,这里做了一个路径转换。仅此而已。
我们看到的,几乎所有的Drupal页面,入口程序都是index.php。当然也有例外,比如安装Drupal时,会使用install.php,更新Drupal时,会使用update.php。例外的情况,我们这里就不分析了,我们来分析一下正常的情况。
我们打开Drupal根目录下的index.php程序,我们看到了非常简洁的代码:
<?php
/**
* @file
* The PHP page that serves all page requests on a Drupal installation.
*
* The routines here dispatch control to the appropriate handler, which then
* prints the appropriate page.
*
* All Drupal code is released under the GNU General Public License.
* See COPYRIGHT.txt and LICENSE.txt.
*/
/**
* Root directory of Drupal installation.
*/
define('DRUPAL_ROOT', getcwd());
require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
menu_execute_active_handler();
老外写代码,通常是注释比代码长,这个文件也不例外。上面的注释说,Drupal所有的页面,都走这个入口程序。路由系统,将会把控制权分发给对应的处理器,然后输出对应的页面。我们往下看代码,第一行:
define('DRUPAL_ROOT', getcwd());
这里面定义了一个常量,DRUPAL_ROOT。getcwd,用来获取当前文件所在的目录,比如我们这里就是D:\xampp\htdocs\snt6。
第二行代码:
require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
这段代码的作用,是加载bootstrap.inc文件。
第三行代码:
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
这段代码的作用,是启动Drupal,说的更完整一点就是启用Drupal的完整引导指令。drupal_bootstrap这个函数,位于bootstrap.inc文件中,我们前面加载这个文件,就是为了执行这个函数。这里的引导指令,是每个Drupal页面,都要走过的流程。这就有点类似于,我们打开计算机的时候,点了启动按钮,点过之后,计算机需要一个启动的过程,这个电脑的开机启动过程,就类似于Drupal的引导指令。
第四行代码:
menu_execute_active_handler();
这个函数做了什么?连个参数都没有。前面Drupal已经启动了,跑了起来,这个函数的作用是这样的,根据Drupal看到的路径,找到对应的回调函数,调用对应的回调函数,然后将返回的内容,组装成HTML页面,返回给浏览器。也就是英文注释里面所讲的。
这就是Drupal的组装过程,非常简单。与其它系统不一样,Drupal只有一个入口程序,我见过的一些系统都是这样的:
http://www.example.com/foroum.php
http://www.example.com/login.php
http://www.example.com/user/register.php
只有Drupal,是一个入口程序。
index.php文件的逻辑结构