As pointed out by Mołot trying to get variable_set to write into a different database would be complicated - it may be achievable by implementing your own database adapter, but there are simpler alternatives.
After some thoughts I realised that while Drupal did not offer a way to hook into the changes made by variable_set, PHP itself did.
This relies on the fact variable_get, variable_set and variable_del all use a global variable (on top of the database) to store the variable values - $conf. Whenever a value is read, added, changed or removed from the variables, the global $conf is modified accordingly. A solution would be to replace the $conf global variable by a custom object that implements ArrayAccess. This way you could monitor every time $conf is accessed or modified. Here is an example:
class MyGlobalConf implements ArrayAccess{
private $conf;
function __construct($conf = array()) {
$this->conf = $conf;
$this->loadMySharedVariables();
}
public function offsetExists($offset) {
return isset($this->conf[$offset]);
}
public function offsetGet($offset) {
return $this->conf[$offset];
}
public function offetSet($offset, $value) {
if ($this->isASharedVariable($offset)) {
$this->saveSharedVariable($offset, $value);
}
$this->conf[$offset] = $value;
}
public function offsetUnset($offset) {
if ($this->isASharedVariable($offset)) {
$this->unsetSharedVariable($offset);
}
unset($this->conf[$offset]);
}
private function loadMySharedVariables() {
// Populate $this->conf with the shared variables
}
private function isASharedVariable($offset){
// Return TRUE if $offset is a shared variable
}
private function saveSharedVariable($offset, $value) {
// Save the shared variable
}
private function unsetSharedVariable($offset, $value) {
// Unset the shared variable
}
}
Then in settings.php you could replace $conf with your own:
$conf = new MyGlobalConf($conf);
While I like the creativity of this approach, I fear the performance impact would be noticeable. So if I was to implement a solution to this problem, I would probably try to synchronize the variables rather than share them.
You could do this, for instance, by implementing hook_exit :
function mymodule_exit($destination = NULL) {
global $conf;
// The variables to share
$shared_vars = array('shared_var_1', 'shared_var_2');
// The table prefix for each of the site we want to share with.
$all_prefix = array('myprefix_1', 'myprefix_2');
// Synchronize...
foreach ($shared_vars as $var) {
foreach ($all_prefix as $prefix) {
$table_name = $prefix . "variable";
db_query("
UPDATE $table_name
SET value = :value
WHERE name = :name
", array(
':value' => serialize($conf[$var]),
':name' => $var
));
}
}
}
This should probably be improved:
If only logged in users could cause variables to be changed, then add a
test to not do anything for anonymous users:
global $user;
if ($user->uid == 0) {return;}
Cache the shared variables in hook_boot
, so that you only update them when they change.