Drupal line by line : part 4

来源:互联网 发布:微信网络答题系统 编辑:程序博客网 时间:2024/05/21 22:22

Welcome to the fourth part of the Drupal 7 Line by Line seriesof articles.

In this series I've been going through the Drupal page loadprocess by going through the code line by line. So far I've coveredindex.php, the logic of the drupal_bootstrap function and the firstbootstrap phase. (see the links at the bottom of this article ifyou want to catch up).

Today I'm going to cover phase two of the bootstrap process.This is where things start to get a bit more interesting as we seehow Drupal handles page caching and how it supports pluggablecaching backends.

Phase two starts with a call to _drupal_bootstrap_page_cache() from thedrupal_bootstrap function.

_drupal_bootstrap_page_cache()

<?php

function _drupal_bootstrap_page_cache() {
?>

The first thing that Drupal does is declare the global $uservariable which is used throughout the page load to represent the$user which is requesting the page. At this point it is completelyempty. In fact, at this stage Drupal has no idea who or what isrequesting the page.

Drupal then includes cache.inc. As you might guess this filecontains Drupal caching functions. But, it also includes Drupal'sfirst Class found during the page loading. Yes,real honestto goodness object oriented code. The file defines theDrupalCacheInterface and a class that implements that interface:DrupalDatabaseCache.

<?php

class DrupalDatabaseCacheimplements DrupalCacheInterface{
?>

This object isn't created at this point in the page load, I justwanted to point out that the class and interface exist.

Cache Backends

Back to _drupal_bootstrap_page_cache:

<?php
 
foreach(variable_get('cache_backends',array()) as$include){
   require_once
DRUPAL_ROOT.'/' .$include;
  }
?>

In this snippet, Drupal loops through the configured cachebackends and includes the file that defines the class thatimplements DrupalCacheInterface. This code requires a bit ofexplaining.

variable_get() is a wrapperfunction for reading the global $conf variable. As you'll recall $conf was defined in drupal_settings_initialize() as an array. Ifyou read the settings.php file and paid close attention to the codecomments you'll also recall that you may assign certainconfiguration values to the $confarray in your settings.php file.

One such configuration value you might set in settings.php is$conf['cache_backends'][] ='path/to/caching_include_file.inc';

So, if you've installed and configured an alternative cachingsystem on your Drupal site its caching code gets included here.

<?php
 
// Check fora cache mode force from settings.php.
 
if(variable_get('page_cache_without_database')){
   
$cache_enabled = TRUE;
  }
  else {
   
drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES,FALSE);
   
$cache_enabled = variable_get('cache');
  }
 
drupal_block_denied(ip_address());
 
// If thereis no session cookie and cache is enabled (or forced), try
  // to serve a cachedpage.
?>

Now the code checks to see if $conf['page_cache_without_database'] was set insettings.php. If that setting exists the code carries on. If on theother hand that setting doesn't exist, Drupal has to find out if asite administrator has turned on caching. In order to find that outDrupal has to bootstrap more of itself to get the job done. This isdone with a call todrupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES,FALSE) Note, that this is a recursive call!We got to this stage in the code execution via a call from withindrupal_bootstrap() and Drupal iscallingdrupal_bootstrap()again.

This is where things are a little tricky to follow. You'llremember that drupal_bootstrap()will go through all the bootstrap phases up to and including theone you are asking for (here: DRUPAL_BOOTSTRAP_VARIABLES). Thatmeans that this one call todrupal_boostrap() is actually going to completetwo 2 bootstrap phases right here. Both DRUPAL_BOOTSTRAP_DATABASEand DRUPAL_BOOTSTRAP_VARIABLES.

I'm going to cover both bootstrap phase 3 (database) and phase 4(variables) in separate articles. Just know that at this stage bothneeded to be run in order to be able to callvariable_get('cache');

Blocking IP Addresses

drupal_block_denied(ip_address());
Before Drupal bothers to do anything else it checks to see if theIP address requesting the page is blocked.

The ip_address() function eitherreturns $_SERVER['REMOTE_ADDR']; orif the site administrator has configured a reverse proxy like squidor varnish, ip_address checks the configuration to determine whichhttp header contains the real requesting IP address and returns itinstead.

drupal_block_denied() actuallycalls drupal_is_denied() todetermine if the IP is blocked. This normally means querying thedatabase, but see this comment in thedrupal_is_denied() function:

<?php
 
// Onlycheck if database.inc is loaded already. If
  // $conf['page_cache_without_database'] = TRUE;is set in settings.php,
  // then the database won't be loaded here so theIPs in the database
  // won't be denied. However the user askedexplicitly not to use the
  // database and also in this case it's quitelikely that the user relies
  // on higher performance solutions like afirewall.
?>

This should make sense if you could follow what I have writtenin this article to this point.

If Drupal discovers that an IP address is blocked:

<?php
   header
($_SERVER['SERVER_PROTOCOL'] .' 403Forbidden');
    print
'Sorry, ' . check_plain(ip_address()).' has beenbanned.';
   exit();
?>

A 403 header is sent to the requester and a non translatable,non themeable page is sent back. Finally exit() is called, whichmeans we are done. No more of Drupal is run. The page load iscomplete with very little code executed.

Serving a Cached Page

Most of the time the requester isn't going to be blocked, so thenext thing that Drupal tries to do at this stage is to load acached page. If a user is logged in or if caching is disabled thisbootstrap phase is complete and no cached page will bedisplayed.

if (!isset($_COOKIE[session_name()])&& $cache_enabled) {translates to: if this user isn't logged in and page caching isenabled continue on and try to load a cached page.

I am not going to go into the code that actually gets the cachedpage because that is worthy of its own article. Just know that ifDrupal can find a cached page it returns it and the page load iscomplete.

Summary

The whole point of the page cache bootstrap phase is to keepDrupal from running any more code than it needs to. If a requestingIP addresses is banned very little code is run in order for Drupalto let the requester know they've been banned. If caching isenabled and the site is configured to load a cached page and NOTload the Drupal database system two whole bootstrap phases areavoided. If caching does require the database. two more bootstrapphases are run, but cached page is displayed if possible and codeexecution stops.

Of course, even with caching enabled it is possible that acached version of a page is not found or the cached version of thepage has expired. In those cases Drupal must carry on through thebootstrap process which I will cover in upcoming articles.

原创粉丝点击