Developer notes

Last updated on
30 April 2025

The Domain Access module is meant to be the core module for a system of small modules which add functionality.

Extension Modules

Currently, the following modules are included in the download. They are not required, but each adds functionality to the core module.

  • Domain Alias -- Allows advanced handling of domain name matching. Use this module to treat multiple domains as though they were identical.
  • Domain Configuration -- Allows you to change select system variables for each domain, such as offline status, footer message and default home page.
  • Domain Content -- Provides a content administration page for each domain, so that affiliate editors can administer content for their section of the site.
  • Domain Navigation -- Supplies a navigation block with three themes. Creates menu items for each domain, suitable for using as primary or secondary links.
  • Domain Prefix -- A powerful module that allows for selective table prefixing for each domain in your installation.
  • Domain Source -- Allows editors to specify a primary "source" domain to be used when linking to content from another domain.
  • Domain Strict -- Forces users to be assigned to a domain in order to view content on that domain. Note that anonymous users may only see content assigned to "all affiliates" if this module is enabled.
  • Domain Theme -- Allows separate themes for each domain.
  • Domain User -- Allows the creation of specific subdomains for each active site user.
  • Domain Views -- Provides a Views filter for the Domain Access module.

The $_domain Global

NOTE: In Drupal 7, this value is deprecated. You should use domain_get_domain() to return the active domain.

During hook_init(), the Domain Access module creates a new global variable, $_domain, which can be used by other Drupal elements (themes, blocks, modules).

The $_domain global is an array of data taken from the {domain} table for the currently active domain. If no active domain is found, default values are used.

The default domain is marked in the {domain} table 'is_default' column.

Some uses for this global variable might include:

  • Block placement based on active domain (using PHP for block visibility).
  • Ad tags inserted based on active domain.
  • Theme switching based on domain.

The 'error' element is new in 6.x.2 and is used to signal installation problems. Normally the 'error' element should not be set. See the API documentation of hook_domain_bootstrap_ful() for details.

Database Schema

The Domain Access module creates two tables in a Drupal installation. {domain} contains the following structure:

  • domain_id: Integer, unique, auto-incrementing. The primary key for all domain records.
  • subdomain: Varchar, 80, unique (enforced by code). 'Domain' is a sql-reserved word, so subdomain is used. This value must match the url 'host' string derived from parse_url() on the current page request.
  • sitename: Varchar, 80, unique (enforced by code). The name for this affiliate, used for readability.
  • scheme: Varchar, 8 default 'http'. Indicates the URL scheme to use when accessing this domain. Allowed values, are currently 'http' and 'https'.
  • valid: Char, 1 default 1. Indicates that this domain is active and can be accessed by site users.
  • weight: Integer, default 0. The sort value for the domain. Signed integer, with lower being higher in a list.
  • is_default: Char, 1 default 0. Indicates that this domain is the default.

The {domain_access} table is a partial mirror of the {node_access} table and stores information specific to Domain Access. Its structure is:

  • nid: Integer, unsigned NOT NULL default '0'
  • gid: Integer, unsigned NOT NULL default '0'
  • realm: Varchar, 255 NOT NULL default ''

The {domain_editor} table stores information about which users can edit and delete content on specific domains. Its structure is:

  • uid: Integer, unsigned NOT NULL default '0'. A foreign key to the {users} table.
  • domain_id: Integer, unsigned NOT NULL default '0'. A foreign key to the {domain} table.

API

The Domain Access module has an API for internal module hooks. Documentation is included in the download as domain.api.php.

Saving nodes programmatically

To save a $node object with proper domain information, you need to format the data properly.

$node->domains
A keyed array of domain ids to save for this node.

$node->domain_site
A boolean indicating whether the content is marked for "all affiliates" or not.

$node->domain_source
An optional integer flag for the canonical domain. Can be any domain_id or the DOMAIN_SOURCE_USE_ACTIVE constant. Only use when Domain Source module is enabled.

For example, if you have three domains, and want to save a node to two of them (domains 2 and 3) and make the canonical link domain 3, you would use:

$node->domains = array(2 => 2, 3 => 3);
$node->domain_site = 0;
$node->domain_source = 3;

Domain Tokens

The module provides the following replacement tokens:

  • 'current-domain:id' - The current domain ID.
  • 'current-domain:name' - The current domain name, lowercased and with only alphanumeric characters.
  • 'current-domain:url' - The current domain's URL, lowercased and with only alphanumeric characters.
  • 'current-domain:subdomain' - The current subdomain, lowercased and with only alphanumeric characters. Only works with *.example.com formats
  • 'default-domain:id' - The default domain ID.
  • 'default-domain:name' - The default domain name, lowercased and with only alphanumeric characters.
  • 'default-domain:url' - The default domain\'s URL, lowercased and with only alphanumeric characters.
  • 'default-domain:subdomain' - The default subdomain, lowercased and with only alphanumeric characters. Only works with *.example.com formats

Managing Site Development

Development of sites using Domain access can be accomplished using Domain Alias by registering the live server and then aliasing the development boxes.

For our sample use-case, the live site is example.com and the development box is

dev.example.com

In this case, example.com is the registered domain, and we use dev.example.com as an alias.

However, this configuration can cause an issue where links from PROJECT.ME.HOST are sent to the wrong domain. This can be addressed using hook_domain_load() and a custom module:

/**
 * Determine the server / hosting environment based on the HTTP REQUEST.
 *
 * EDIT THESE VALUES AS NEEDED.
 *
 * @return
 * A server identifier string.
 *
 * @see custom_domain_load()
 */
function custom_get_server() {
  $server = '';
  if (isset($_SERVER['HTTP_HOST'])) {
    if (substr_count($_SERVER['HTTP_HOST'], 'localhost') > 0) {
      $server = 'local';
    }
    elseif (substr_count($_SERVER['HTTP_HOST'], 'dev.example.com') > 0) {
      $server = 'dev';
    }
    elseif (substr_count($_SERVER['HTTP_HOST'], 'stage.example.com') > 0) {
      $server = 'stage';
    }
    elseif (substr_count($_SERVER['HTTP_HOST'], 'live.example.com') > 0) {
      $server = 'live';
    }
  }
  return $server;
}

/**
 * Implements hook_domain_load().
 *
 * Ensure proper URLs on test environments.
 */
function custom_domain_load(&$domain) {
  $server = custom_get_server();
  // If not set, do nothing.
  if (empty($server) || !isset($domain['subdomain'])) {
    return;
  }
  // Take the initial element. Your mileage may vary.
  $subdomain = $domain['subdomain'];
  $hostname = explode('.', $subdomain);
  // Map parts of the canonical domain to dev aliases.
  // This logic assumes a foo.example.com => foo.dev.example.com structure.
  $base = $server;
  if (count($hostname) > 2) { 
    $base = $hostname[0];
  }
  switch ($server) {
    case 'local':
      $domain['subdomain'] = "$base.localhost";
      break;
    case 'dev':
      $domain['subdomain'] = "$base.dev.example.com";
      break;
    case 'stage':
      $domain['subdomain'] = "$base.stage.example.com";
      break;
    case 'live':
      $domain['subdomain'] = "$base.live.example.com";
      break;
  }
  $domain['path'] = domain_get_path($domain);
  $domain['canonical'] = $subdomain;
}

/**
 * Alter the domain form to show proper canonical domain information.
 */
function custom_form_domain_form_alter(&$form, &$form_state) {
  if (isset($form['#domain']['canonical'])) {
    $form['subdomain']['#default_value'] = $form['#domain']['canonical'];
    $form['help'] = array(
      '#markup' => '<p>' . t('On this server, the domain URL is !url.', array('!url' => '<strong>' . check_plain($form['#domain']['subdomain']) . '</strong>')) . '</p>',
      '#weight' => -2,
    );
  }
  $new_text = '<strong>' . t('Enter the canonical domain name (e.g. <em>example.com</em>)') . '</strong><br />';
  $form['subdomain']['#description'] = $new_text . $form['subdomain']['#description'];
  if (!isset($form['ignore'])) {
    $form['ignore'] = array(
      '#type' => 'checkbox',
      '#title' => t('Ignore server response warning'),
      '#default_value' => 0,
      '#weight' => 1,
      '#description' => t('<strong>This domain did not respond correctly. It cannot be set as your primary domain unless you select <em>Ignore server response warning</em></strong>.'),
    );
    $form['submit']['#weight'] = 2;
  }
}

/**
 * Alter the domain overview form to show proper canonical domain information.
 */
function custom_form_domain_overview_form_alter(&$form, &$form_state) {
  $active_domain = domain_get_domain();
  $domains = domain_domains();
  foreach ($form['domain'] as $domain_id => $values) {
    if (isset($domains[$domain_id]['canonical'])) {
      $domain = $domains[$domain_id];
      $form['domain'][$domain_id]['subdomain']['#markup'] = ($active_domain['domain_id'] == $domain['domain_id']) ? '<strong>' . l($domain['canonical'], domain_get_uri($domain)) . '</strong>' : l($domain['canonical'], domain_get_uri($domain));
    }
  }
}

This code can be left in place when the site goes live. (If you prefer, the $conf logic can also go in custom_domain_load().

Alternatively, it is also possible to set up separate tables in the db. This requires a {staging_domain} and {staging_domain_alias} table, created through SQL admin, and the following custom code:

/**
 * Special handling for Domain table prefixing.
 */
$db_prefix = array();
if (substr_count($_SERVER['HTTP_HOST'], SERVERNAME) > 0) { // Your SERVERNAME here.
  $db_prefix['domain'] = 'staging_';
  $db_prefix['domain_alias'] = 'staging_';
}

Depending on your workflow, either approach may work best.

Additional programmatic settings

Skip domain checks

The Domain Access module does additional checks on the primary domain to prevent users from accidentally misconfiguring this vitally important domain setting. Errors here can render a site inoperable. However, there are some use-cases where you need to bypass this restriction and the internal site variable flag, domain_skip_domain_check allows you to do this. Set this to TRUE to disable domain validation. Once you have saved the domain, reset this to FALSE to re-enable validation. This setting will be added to version 7.x-3.4

For example, in your settings.php file add the following to disable validation.

$conf['domain_skip_domain_check'] = TRUE;

Help improve this page

Page status: Not set

You can: