Question

What is the correct way to change the active Drupal theme programmatically?

Was it helpful?

Solution

Drupal 6 solution:

You want to make sure you change the global $custom_theme variable fairly early in page execution.

global $custom_theme;
$custom_theme = 'garland';

OTHER TIPS

I know you asked how to do it programattically, but in case that's your solution, not the actual problem, you can also use the ThemeKey module. This allows you to set conditions which, when met, changes the theme. You can make conditions based on paths, taxonomy, content type, create or edit date and more. You can also add in the Themekey Properties module module to get even more options.

Again, I know this isn't programmattically, but I'm not sure if the real question behind your question is how to change themes based on conditions.

The best way to do this is to create an update hook in a module:

function yourmodule_update_N() {
  variable_set('theme_default','yourtheme');
}

Changing the active theme via Drush

drush vset theme_default garland
drush vset admin_theme garland
drush cc all

Changing the active theme via a module

The basics of changing the default theme and administration theme:

// Changes the theme to Garland
variable_set('theme_default', $theme_default);
// Changes the administration theme to Garland
variable_set('admin_theme', $admin_theme);

Here's a small function to set back the themes safely to default Drupal themes like Bartik or Garland (tested in Drupal 6 and 7):

/**
 * Set the active Drupal themes (the default and the administration theme) to default ones.
 * Tested in Drupal 6, 7 (but possibly working in version 8 too according to the documentations [some similarities between 7 and 8]).
 */
function TESTMODULE_set_active_theme_to_default($affect_admin_theme = TRUE) {

  // Provides a list of currently available themes.
  $list_themes = list_themes(TRUE);
  // 6, 7, 8, etc.
  $major_version = (int)VERSION;

  $theme_default = isset($list_themes['bartik']) ? 'bartik' : 'garland';
  $admin_theme   = isset($list_themes['seven']) ? 'seven' : 'garland';

  // Changes the theme to Garland
  variable_set('theme_default', $theme_default);

  // Changes the administration theme to Garland if argument is TRUE
  if($affect_admin_theme){
    variable_set('admin_theme', $admin_theme);
  }

  // if Switchtheme module (https://drupal.org/project/switchtheme) is enabled, use it
  if (module_exists('switchtheme')) {
    if (empty($_GET['theme']) || $_GET['theme'] !== $theme_default) {
      $query = array(
        'theme' => $theme_default
      );
      // in D6, drupal_goto's second argument is the query string,
      // in >=D7, a more general $options array is used
      if($major_version < 7){
        $options = $query;
      }
      else{
        $options = array('query' => $query);
      }

      drupal_goto($_GET['q'], $options);
    }
  }

  drupal_set_message(t('Default theme has been changed to %theme_default, administration theme has been changed to %admin_theme.', array(
    '%theme_default' => $theme_default,
    '%admin_theme' => $admin_theme
  )));

}

You can call it in a hook_init() implementation (comment it out after it's not needed):

/**
 * Implements hook_init()
 */
function TESTMODULE_init() {  
  // ATTENTION! Comment out the following line if it's not needed anymore!
  TESTMODULE_set_active_theme_to_default();
}

In Drupal 7, use hook_custom_theme():

/**
 * Implements hook_custom_theme()
 * Switch theme for a mobile browser
 * @return string The theme to use
 */
function mymodule_custom_theme()  {
    //dpm($_SERVER['HTTP_USER_AGENT']);
    $theme = 'bartik'; // core theme, used as fallback
    $themes_available = list_themes(); // get available themes
    if (preg_match("/Mobile|Android|BlackBerry|iPhone|Windows Phone/", $_SERVER['HTTP_USER_AGENT'])) {
        if (array_key_exists('custommobiletheme', $themes_available)) $theme = 'custommobiletheme';
        else { drupal_set_message("Unable to switch to mobile theme, because it is not installed.", 'warning'); }
    }
    else if (array_key_exists('nonmobiletheme', $themes_available)) $theme = 'nonmobiletheme';
    // else, fall back to bartik

    return $theme;
}

Adapted from <emoticode />

Return the machine-readable name of the theme to use for the current page.

The comments for this function may be worth reading:

This hook can be used to dynamically set the theme for the current page request. It should be used by modules which need to override the theme based on dynamic conditions (for example, a module which allows the theme to be set based on the current user's role). The return value of this hook will be used on all pages except those which have a valid per-page or per-section theme set via a theme callback function in hook_menu(); the themes on those pages can only be overridden using hook_menu_alter().

Note that returning different themes for the same path may not work with page caching. This is most likely to be a problem if an anonymous user on a given path could have different themes returned under different conditions.

Since only one theme can be used at a time, the last (i.e., highest weighted) module which returns a valid theme name from this hook will prevail.

For Drupal 8:

In settings.php

$config['system.theme']['default'] = 'my_custom_theme';

Update config programatically:

\Drupal::configFactory()
->getEditable('system.theme')
->set('default', 'machine_name')
->save();
Licensed under: CC-BY-SA with attribution
Not affiliated with drupal.stackexchange
scroll top