Thursday, April 23

Drupal 7 Bootstrap Process ( drupal_bootstrap ) - Part 2


This is the second part of my Drupal 7 Line by Line series. In the first part I walked through Drupal 7 index.php. As you recall there are only four lines of code and two function calls that display all the pages on your Drupal 7 site.
In this post I'll start walking through one of those functions: drupal_bootstrap(). If you recall from Part 1 I said this function is starts up (bootstraps) all of Drupal's mechanisms required to handle a page request. This is only part of the story and only half the truth. A more accurate description would be that it loads up only as much of Drupal's functionality a php script needs so that the php script can uses that functionality to do something.
When drupal_bootstrap is called from index.php it is passed a single argument: BOOTSTRAP_FULL. In order for index.php (a php script) to display a web page (what the script does) it needs Drupal to bootstrap all of its mechanisms (i.e. a full bootstrap).
Lets see what the phpDoc comment and function signature for drupal_bootstrap() have to say:
<?php/**
* A string describing a phase of Drupal to load. Each phase adds to the
* previous one, so invoking a later phase automatically runs the earlier
* phases too. The most important usage is that if you want to access the
* Drupal database from a script without loading anything else, you can
* include bootstrap.inc, and call drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE).
*
* @param $phase
*   A constant. Allowed values are the DRUPAL_BOOTSTRAP_* constants.
* @param $new_phase
*   A boolean, set to FALSE if calling drupal_bootstrap from inside a
*   function called from drupal_bootstrap (recursion).
* @return
*   The most recently completed phase.
*
*/
function drupal_bootstrap($phase = NULL, $new_phase = TRUE) { ?>
This basically tells us that when we call this function we have to tell it which bootstrap phase to run by passing a value to the $phase variable. The function accepts a second argument $new_phase which by default is "TRUE".

Executing drupal_bootstrap(BOOTSTRAP_FULL)

So the first thing that the function does when its run is define a static variable called $phases. That variable is assigned an array that is populated with the constants that represent the 7 phases of the bootstrap process.

<?php
 
static $phases = array(
   
DRUPAL_BOOTSTRAP_CONFIGURATION,
   
DRUPAL_BOOTSTRAP_PAGE_CACHE,
   
DRUPAL_BOOTSTRAP_DATABASE,
   
DRUPAL_BOOTSTRAP_VARIABLES,
   
DRUPAL_BOOTSTRAP_SESSION,
   
DRUPAL_BOOTSTRAP_PAGE_HEADER,
   
DRUPAL_BOOTSTRAP_LANGUAGE,
   
DRUPAL_BOOTSTRAP_FULL,
  );
?>
The function then defines two more static variables $final_phase and $stored_phase (given an initial value of -1).

<?php
 
// When not recursing, store the phase name so it's not forgotten while
  // recursing.
 
if ($new_phase) {
   
$final_phase = $phase;
  }
?>
$new_phase is TRUE by default - therefore the $final_phase is assigned the value of $phase which in this case is BOOTSTAP_FULL which has an integer value of 7.

<?php
 
if (isset($phase)) {
   
// Call a phase if it has not been called before and is below the requested
    // phase.
   
while ($phases && $phase > $stored_phase && $final_phase > $stored_phase) {?>
If $phase has a value (it does) the function enters a while loop. The conditions of the while loop are:
if the $phases array has something in it (it currently does)
AND $phase (currently BOOTSTRAP_FULL or 7)
is greater than $stored_phase (currently -1)
AND $final_phase (also currently 7)
is greater than $stored_phase (currently -1)
do stuff.
In more general terms, the function is going to keep looping until each bootstrap phase is complete and it reaches the bootstrap phase that was first passed to the function.

<?php
      $current_phase
= array_shift($phases);       // This function is re-entrant. Only update the completed phase when the
      // current call actually resulted in a progress in the bootstrap process.
     
if ($current_phase > $stored_phase) {
       
$stored_phase = $current_phase;
      }
?>
Once inside the while loop the function 'shifts off' the first value of the $phases array and assigns the value to $current_phase.
If you look back, you'll see that the first element of the $phases array was DRUPAL_BOOTSTRAP_CONFIGURATION. Therefore $current_phase gets assigned that value once the array is shifted.
After that, the function then checks if $current_phase is greater than the $stored_phase and if so assigns the value of $current_phase to $stored_phase. This is all about keeping track of what the current bootstrap phase is and what the phase was. Remember, this function is going to be looping through all the phases. In each loop drupal_bootstrap could be called again recursively.

Meat and Potatoes

We arrive at the part that actually starts doing the bootstrapping (starting up) of the individual parts of Drupal.

<?phpswitch ($current_phase) {
        case
DRUPAL_BOOTSTRAP_CONFIGURATION:
         
_drupal_bootstrap_configuration();
          break;         case
DRUPAL_BOOTSTRAP_PAGE_CACHE:
         
_drupal_bootstrap_page_cache();
          break;         case
DRUPAL_BOOTSTRAP_DATABASE:
         
_drupal_bootstrap_database();
          break;         case
DRUPAL_BOOTSTRAP_VARIABLES:
         
_drupal_bootstrap_variables();
          break;         case
DRUPAL_BOOTSTRAP_SESSION:
          require_once
DRUPAL_ROOT . '/' . variable_get('session_inc', 'includes/session.inc');
         
drupal_session_initialize();
          break;         case
DRUPAL_BOOTSTRAP_PAGE_HEADER:
         
_drupal_bootstrap_page_header();
          break;         case
DRUPAL_BOOTSTRAP_LANGUAGE:
         
drupal_language_initialize();
          break;         case
DRUPAL_BOOTSTRAP_FULL:
          require_once
DRUPAL_ROOT . '/includes/common.inc';
         
_drupal_bootstrap_full();
          break;
      }
?>
There is a switch/case statement that checks what the $current_phase is and then executes the code in the appropriate case.
At this stage in this line by line journey the $current_phase is DRUPAL_BOOTSTRAP_CONFIGURATION so
_drupal_bootstrap_configuration() gets called.

What happens next

Good question, but the answer will have to wait. This is a good time to stop for now since each phase in the bootstrap process requires its own post. Next time we'll take a look at _drupal_bootstrap_configuration.
While you are waiting, and if you are at all curious about the origins of the bootstrap process, you can check out http://drupal.org/node/18213 where drupal_bootstrap was born.

No comments:

Post a Comment