variable_set()イベントにフックすることは可能ですか?


8

システム変更イベントを追跡して、元に戻せるようにしたいと思います。variable_set()を確認すると、そのイベントにフックが提供されていないことがわかります。これを行う方法はありますか?

設定フォームにフックするように変更できますが、追跡する設定フォームがたくさんあります。variable_set()に直接フックできる場合、コードははるかに単純になります。

また、機能+ strongarmモジュールで変数の変更を追跡することもできますが、Drupal管理者がコードに触れることなく変数の履歴を参照できる方が良いです。

回答:


11

Drupalだけを使用するのは不可能のようです。つまり、

variable_set()それ自体はフックを呼び出しませんが、を使用しdb_merge()ます。その関数はMergeQueryクラスを使用しています。さて、でフックするのは良いことですhook_query_alter()が、それはQueryAlterableInterfaceインターフェースを実装するクエリクラスに対してのみ機能します。残念ながら、このインターフェースはSelectQuerySelectQueryExtenderクラスによってのみ実装され、クラスでは実装されなくなりましたMergeQuery

の子クラスを作成する方法を見つけたとしてもMergeQuery、それはを実装しQueryAlterableInterface、Drupalに使用させることに注意してください。hook_query_alter()タグがあるクエリでのみ機能し、variable_set()そのクエリにタグを付けないため、コアをハックする意思がない限り、フックはとにかく使用されません。しかし、もしそうなら、あなたはそれすべてを必要としません、あなたは単にフックコールをハックすることができます。

筋金入りに感じる場合は、より間接的なPHPアプローチ$confを使用できます。これは、構成変数のグローバル配列です。Stack Overflowで説明されているように、配列のように機能するオブジェクトでそれを置き換えるモジュールを作成できます。これを良い代替品にするには、実装する必要がありますArrayAccess。オリジナルからすべての値を$confオブジェクトにプルします。次に、ArrayAccess::offsetSet()ロギングロジックを実装します。


私はこの古い答えを忘れており$confその当時はほとんど何でもできる方法をすでに見つけていました:D私の更新された答えが誰かを助けることを願っています。
Mołot

私が感銘を受けた!:D
Letharion

@Letharionありがとう:)むかしむかし、私はPHPで「オブジェクトとして動作する...」の魔法が好きでしたが、私はそれについて少し覚えています;)
MołotSep

6

コードよりも高速なデータベーストリガーを使用できます。

こちらがMySQLのドキュメントです。

  1. 古い値を格納するテーブルを作成する

    CREATE TABLE variable_backup
    (
        name varchar(128) not null,
        value longblob,
        updated datetime not null,
        primary key (name, updated)
    );
  2. 1つは挿入用、もう1つは更新用のトリガーを作成します。

    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に記録されます。


私はそれが好きで、端正でシンプルです。おそらく私の方法よりも高速です。より制限されていますが、十分なMySQLアクセス権がある場合は、OPが必要とすることを実行するには十分です。
Mołot

私はこのように好きです。しかし、ユーザーエージェント情報も追跡する必要があると思います
Andy Truong 2013年

データベースで情報が利用できるかどうかは疑問です。
Scott Joudry 2013年

@AndyTruongその情報はデータベースにはありません。申し訳ありません。私は見回そうとしましたが、セッションテーブルのデータでそれを推測することは不可能であり、選択クエリのみが変更可能であるため、追加する方法はありません。だから私の「ハードコア」メソッドはあなたのためにあります。うまくいかなかったとしても、実装に成功したことを願っています。それにリンクする新しい質問をし、そうしたことをコメントしてください。
Mołot

5

あなたがソースコード内で見ることができるように、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スナップショットを作成して、そのテーブルの以前のリビジョンと比較するか、比較するために他の形式の変数リビジョンストレージを実装することもできます。


1
このクエリでhook_query_alterを使用できる場合、その方法を知りたいと思います。QueryAlterableInterface実際に8 はQueryそれ自体で実装されています。しかし、8で構成管理はとにかく再構築されます。7つでは、タグ付けされた選択クエリのみが私が見る限り変更可能です。しかし、何かが足りないのでしょうか?
Mołot

1
いいえ、あなたは正しいです。hook_query_alterは推測でしたが、この場合、D7では実行できませんでした。ありがとうございます。
デビッドトーマス

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.