Drupal 7 でのデータベース操作 - レッスン 6 - クエリをその場で変更する(hook_query_alter)
動的 SELECT クエリの重要な特徴は、他のモジュールがこれらのクエリをその場で変更できることです。これにより、モジュールは独自の指示をクエリに挿入し、その動作に影響を与えたり、実行時に変更を適用したりできます――たとえばノードアクセス権限を強制するなどです。クエリをその場で変更するには、タグ付け、メタデータ、hook_query_alter() の 3 つの要素が関わります。
タグ付け
任意の動的 SELECT クエリは、1 つ以上の文字列で「タグ付け」できます。これらのタグはクエリの種類を識別するのに役立ち、それに基づいてアクションをトリガーするのに使えます。タグは英数字で、小文字であり、PHP の変数命名規則に従うべきです。クエリにタグを追加するには addTag() メソッドを使います:
addTag('node_access');
?>
これらのメソッドを使って、クエリオブジェクトにタグがあるかどうかを確認できます:
hasTag('example');
// TRUE if query has all listed tags.
$query->hasAllTags('example1', 'example2');
// TRUE if query has any of the listed tags.
$query->hasAnyTag('example1', 'example2');
?>
hasAllTags() と hasAnyTag() はどちらも、順序に関係なく複数の引数を受け取ります。タグは使いやすく、次のようないくつかの標準タグが存在します:
- node_access
- このクエリはノードアクセス権限を強制すべきです。
- translatable
- このクエリには翻訳可能な文字列が含まれます。
- term_access
- このクエリはタクソノミー用語のアクセス権限を強制すべきです。
- views
- このクエリは Views モジュールによって生成されます。
メタデータ
クエリはメタデータ――文字列キーを介して付与される任意の PHP 値――を持つこともできます。メタデータは、クエリの変更のための追加情報を提供します。
addMetaData('node', $node);
?>
メタデータはクエリオブジェクトに直接の影響を与えません。特にタグと一緒に使われる場合に、クエリの変更を助けるためだけに存在します。メタデータには次でアクセスします:
getMetaData('node');
?>
指定したキーが存在しない場合、NULL が返されます。
hook_query_alter()
タグもメタデータも、クエリを直接変更するわけではありません。代わりに、あらゆる動的 SELECT クエリを変更できる hook_query_alter() にコンテキストを提供します。このフックは、クエリがコンパイルされる直前、execute() が呼び出される前に呼ばれます。これにより、モジュールは必要に応じてクエリを操作できます。
hook_query_TAG_NAME_alter() を使って、特定のタグを対象とするフックを書くこともできます。たとえば、このフックは「node_access」でタグ付けされたクエリを処理します:
hook_query_alter() に関する 2 つの重要な注意点:
- $query は参照渡しされません。PHP 5 以降ではオブジェクトなので、参照渡しは不要です。
- パラメーターの型は
SelectQueryではなく、厳密にQueryAlterableInterfaceとして定義されています。これにより将来の互換性が確保されます。
hook_query_alter() は、無限ループを避けるために実行することを除き、クエリオブジェクトに対して任意のアクションを実行できます。タグとメタデータを使って、どのアクションを取るかを判断できます。開発者はフィールド、結合、条件などを追加したり、次のメソッドを使って元のクエリの一部を取り除いたりすることもできます:
getFields();
$expressions =& $query->getExpressions();
$tables =& $query->getTables();
$order =& $query->getOrderBy();
$where =& $query->conditions();
$having =& $query->havingConditions();
?>
これらのメソッドは配列を参照で返し、フックがクエリの内部構造に直接アクセスして変更できるようにします。これらのメソッドの完全なドキュメントは、includes/database/select.inc の SelectQuery クラスにあります。