Drupal 7 The process behind page construction.

Have you ever wondered what is the mechanism involved in building the page content for the given page query on a Drupal 7 website? In this tutorial I will try to dig into the process and provide details on some key steps involved in page construction process.

The process starts with a call to the function "menu_execute_active_handler()" inside "index.php".

Get router item:

From "menu_execute_active_handler" the control goes to the function  "menu_get_item"(menu.inc) to get the router_item for the given path. Inside this function the table "menu_router" is queried to construct the router item.

 $router_item = db_query_range('SELECT * FROM {menu_router} WHERE path IN (:ancestors) ORDER BY fit DESC', 0, 1, array(':ancestors' => $ancestors))->fetchAssoc();

The router item  returned by this function is an associative array with many (key,value) pairs.  Some of the pairs for the homepage query (/?q=node)  are shown bellow.

$router_item[path] = "node"
$router_item[access_callback] = "user_access"
$router_item[page_callback] = "node_page_default"
$router_item[page_arguments] = ""

Execute Page call back and set main page content:

The data available in router item is used to make a call to the page call back function (Implemented by one of the active modules) that returns the main content for the page. In this case for the query "/?q=node" the function "node_page_default" implemented by the "node" module (modules/node/node.module) is called to get the page content. And the returned data ($page_callback_result) is a renderable array.

 $page_callback_result = call_user_func_array($router_item['page_callback'], $router_item['page_arguments']);

After this control goes to the function "drupal_deliver_page"

drupal_deliver_page($page_callback_result, $default_delivery_callback);

From there control goes to the function "drupal_deliver_html_page". From there the function "drupal_render_page" is executed that returns the html content, and this contents is finally delivered to the browser.

print drupal_render_page($page_callback_result);

Execute the hook page_build from all the participating modules:

Any module can contribute to the page content by implementing the hook "page_build", Inside the function "drupal_render_page" this hook from all the modules get's executed and the different page elements are added as a result. For example the module "block" implements this hook and contributes all enabled blocks to the page in this step.  

foreach (module_implements('page_build') as $module) {
    $function = $module . '_page_build';

Render the page:

So far the page that has been constructed is available in the form of a renderable array. Now is the time to call the function "drupal_render($page)", this function converts the structured  array($page) into HTML that can be finally  printed to the browser. From here the control goes to the function "theme". 

if (isset($elements['#theme'])) {
    $elements['#children'] = theme($elements['#theme'], $elements);

The function "theme" in turn executes most of the theming related functions, these functions add more  and more variables to the renderable array. For  the bartik's theme the following preprocess/process functions are executed.

Preprocess functions:

  1. template_preprocess
  2. template_preprocess_page
  3. contextual_preprocess
  4. shortcut_preprocess_page

Process functions:

  1. template_process
  2. template_process_page
  3. rdf_process
  4. bartik_process_page

For example the function "template_preprocess_page"(includes/theme.inc) adds 'main_menu' and 'secondary_menu' to the renderable array.

  $variables['main_menu']         = theme_get_setting('toggle_main_menu') ? menu_main_menu() : array();
  $variables['secondary_menu']    = theme_get_setting('toggle_secondary_menu') ? menu_secondary_menu() : array();

Finally the function "them_render_html" is called with two arguments (1. template file like page.tpl.php 2. structured render able array) to get html content.

$output = $render_function($template_file, $variables);

Inside "page.tpl.php" any call  to the render function (as shown bellow  from bartik's theme) again invokes the "theme" function and the process goes on recursively until all required page elements rendered completely. 

<?php if ($page['sidebar_first']): ?>
      <div id="sidebar-first" class="column sidebar"><div class="section">
        <?php print render($page['sidebar_first']); ?>
      </div></div> <!-- /.section, /#sidebar-first -->
<?php endif; ?>

Call stack:

The following image shows the call stack for the steps describe above.

drupal 7 page building process