Multi-site variables table for shared variables (extending variable_set) I have a multi-site setup with some shared tables using db_prefix. The variables table is NOT shared. Sharing ALL variables would cause lot of trouble, but sharing only some selected variables wont.

The picture below visualizes my problem:


The entries in the green box are shared and available on all multi-sites. Whereas the selected entry information is part of the config and stored in variables. Changes in the red box are not shared and lead to inconsistency when changed on one multi-site.

At the moment I use "drush @sites variable-set ..." to make consistent changes on all multi-sites. But to keep it more simple, I want to integrate it into Drupal's backend.

I found out that there was a failed patch request already. See issue here. The patch modifies variable_get() and variable_set() with an extended query-statement, if a defined variable is set in an array. I am aware of the fact, that the patch is for drupal 5, but it could be easily adapted to drupal 7.

The workaround in the patch modifies the core, but i cannot touch it. Overwriting variable_get() functionality is quite an easy job. You just have to hook_boot() or hook_init() and replace the desired values in $conf array with your custom values.

Whats the deal?

I need to extend variable_set() and variable_del() functionality without touching core. Any ideas how i get into that?
Reading is possible, but may be costly

Code for variable_get() is:

function variable_get($name, $default = NULL) {
  global $conf;
  return isset($conf[$name]) ? $conf[$name] : $default;
}


So you need to set:

global $conf;
$conf['shared_variable'] = your_function_to_obtain('shared_variable');


Where to put it?

If your function uses other site variables, including ones provided via UI, best place seems to be a hook_boot(). You need to make sure your hook_boot() is called first. To get your module to run first, use hook_module_implements_alter() or easier and less reliable way - Modules weight module.

If you don't use any values provided via UI, you can (maybe should) put it in settings.php instead. You don't need to use global in settings.php.

Writing is way more trickier

Code for variable set() is:

function variable_set($name, $value) {
  global $conf;

  db_merge('variable')-&gt;key(array('name' =&gt; $name))-&gt;fields(array('value' =&gt; serialize($value)))-&gt;execute();

  cache_clear_all('variables', 'cache_bootstrap');

  $conf[$name] = $value;
}


As you can see, there are no hook calls, nothing. It just saves data altogether. variable_del() shares that problem.

What you can do is to override very forms, providing your own save handler that will copy data to shared table. This will not solve the issue of saves and deletes outside form submits, if they happen in module in question. Other approach would be to use triggers directly in RDBMS to synchronize tables - more reliable, but harder to maintain.

Advanced PHP debugger

A bit hardcore approach is to override built-in functions. Yes, you can do it without touching core.

You need PECL apd >= 0.2

In your settings.php (or in your module's *.inc, but include in settings.php) implement override_function($function_name, $function_args, $function_code) for variable_del and variable_set. Do not attempt this for reads, unless you want huge performance hit.