我想跟踪系统更改事件,使其可恢复。当检查variable_set()时,我看到没有为该事件提供钩子。有什么办法可以做到吗?
我可以更改以挂钩到设置表格,但是要跟踪很多设置表格,如果我可以直接挂钩到variable_set(),则代码将变得更加简单。
我还可以使用功能+ Strongarm模块跟踪变量的更改,但是最好是Drupal管理员可以浏览变量历史记录而无需触摸代码。
我想跟踪系统更改事件,使其可恢复。当检查variable_set()时,我看到没有为该事件提供钩子。有什么办法可以做到吗?
我可以更改以挂钩到设置表格,但是要跟踪很多设置表格,如果我可以直接挂钩到variable_set(),则代码将变得更加简单。
我还可以使用功能+ Strongarm模块跟踪变量的更改,但是最好是Drupal管理员可以浏览变量历史记录而无需触摸代码。
Answers:
似乎仅使用Drupal是不可能的,这意味着:
variable_set()
本身不会调用任何钩子,但会使用db_merge()
。该函数正在使用MergeQuery
该类。现在,很高兴与挂钩hook_query_alter()
,但是它仅适用于实现该QueryAlterableInterface
接口的查询类。遗憾的是,此接口现在仅由SelectQuery
和SelectQueryExtender
类实现,而不是由MergeQuery
类实现。
请注意,即使您找到创建的子类的方法MergeQuery
,该方法也将实现QueryAlterableInterface
,并使Drupal使用它。hook_query_alter()
仅适用于具有标签的查询,并且variable_set()
不为其查询添加标签,因此,除非您愿意破解内核,否则无论如何都不会使用该挂钩。但是,如果您需要的话,则不需要所有这些,您可以简单地进行挂接调用。
如果您感觉很顽固,则可以使用更间接的PHP方法:$conf
配置变量的全局数组;您可以编写一个模块,将其替换为类似于数组的对象,如Stack Overflow所述。要使其成为一个好的替代品,您需要实施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()
那里进行一些其他处理,但是,正如Molot指出的那样,hook_query_alter()
看起来不太可能以db_merge()
查询为目标。
或者,您可以cron快照变量表以将其与该表的先前修订版进行比较,或者实现其他形式的变量修订版存储以进行比较。
QueryAlterableInterface
确实是由Query
自己实现的。但是无论如何,在8配置中都将重建管理。据我所知,只有7个带标签的选择查询是可更改的。但是也许我想念什么?
我在Drupal.org上打开了功能请求票证,以创建用于拦截系统变量的设置和删除的钩子,为此我提交了一个核心补丁供审查!请参阅:
$conf
:D希望我更新的答案能对某人有所帮助。