Можно ли подключиться к событию набора переменных()?
Я хотел бы отслеживать событие системных изменений, чтобы сделать их обратимыми. При проверке variable_set() я вижу, что для этого события не предусмотрен крюк. Есть ли у меня какой-нибудь способ сделать это?
Я могу изменить, чтобы подключиться к формам настроек, но нужно отслеживать множество форм настроек, если я смогу напрямую подключиться к variable_set(), код станет намного проще.
Я также могу отслеживать изменения переменных с помощью модулей features + strongarm, но лучше, если администратор Drupal можно просматривать историю переменных, не касаясь кода.
3 answers
Похоже, что использовать только Drupal невозможно, что означает:
variable_set()
сам по себе не вызывает никаких зацепок, но использует db_merge()
. Эта функция использует MergeQuery
класс. Теперь было бы неплохо зацепиться за hook_query_alter()
, но это работает только для классов запросов, которые реализуют QueryAlterableInterface
интерфейс. К сожалению, этот интерфейс теперь реализован только SelectQuery
и тот SelectQueryExtender
занятия, а не по MergeQuery
класс.
Обратите внимание, что даже если вы найдете способ создать дочерний класс MergeQuery
, это позволит реализовать QueryAlterableInterface
, и заставьте Drupal использовать его. hook_query_alter()
работает только с запросами, имеющими теги, и variable_set()
не помечает свой запрос, поэтому крючок все равно не будет использоваться, если вы не хотите взломать ядро. Но если да, то вам все это не нужно, вы можете просто взломать вызов по телефону.
Если вы чувствуете себя хардкорным, вы можете использовать более косвенный Подход PHP: $conf
- это глобальный массив переменных конфигурации; вы можете написать модуль, который заменит его объектом , действующим как массив, как описано в разделе Переполнение стека. Чтобы сделать его хорошей заменой, вам необходимо реализовать ArrayAccess
. Перенесите все значения из исходного $conf
в свой объект. Затем, в ArrayAccess::offsetSet()
реализуйте свою логику ведения журнала.
Вы могли бы использовать триггер базы данных, который был бы быстрее кода.
-
Создайте таблицу для хранения старых значений
CREATE TABLE variable_backup ( name varchar(128) not null, value longblob, updated datetime not null, primary key (name, updated) );
-
Создайте свои триггеры, один для вставки и один для обновления:
CREATE TRIGGER backup_variable_update BEFORE UPDATE ON variable FOR EACH ROW INSERT INTO variable_backup (name, value, type, updated) VALUES (OLD.name, OLD.value, "update", NOW()); CREATE TRIGGER backup_variable_insert BEFORE INSERT ON variable FOR EACH ROW INSERT INTO variable_backup (name, value, type, updated) VALUES (NEW.name, NEW.value, "insert", NOW());
Теперь все ваши обновления и вставки будут записывать старые значения в variable_backup.
Как вы можете видеть в исходном коде, variable_set()
не запрашивает крючки или изменения, например, нет module_invoke_all()
или drupal_alter()
звонит туда.
function variable_set($name, $value) {
global $conf;
db_merge('variable')->key(array('name' => $name))->fields(array('value' => serialize($value)))->execute();
cache_clear_all('variables', 'cache_bootstrap');
$conf[$name] = $value;
}
Тем не менее, вы можете прослушать запрос db_merge()
с помощью специально размещенного hook_query_alter()
и выполните там некоторую дополнительную обработку, но, как указал Молот, hook_query_alter()
вряд ли сможет настроить таргетинг на запрос db_merge()
.
В качестве альтернативы, вы могли бы, возможно, сделать снимок таблицы переменных, чтобы сравните его с предыдущими версиями этой таблицы или реализуйте какую-либо другую форму хранения переменных версий для сравнения.