DBTNGはDrupal7におけるデータベースの新しい抽象化レイヤーです。これはいくつかのオブジェクト指向の原理を使うことで、Drupal6よりもはるかに多くの機能を提供します。
Drupal6のモジュールをDBTNGで動作させるには、多くのクエリーは変更が必要です。ここではその変更点について、最も一般的なものについて説明します。
ほとんどのクエリはさほど多くの作業は必要ありません。通常、2つのことが必要です。
ひとつは、引数の変換です。'%s'、%dなどの引数は、:unique_nameのように変更します。そして引数の配列のキーは、このプレースホルダと同じ名前にします。ここでのルールは次のようなものです。
Example:
<?php // Old code. $result = db_query("SELECT n.nid, u.name FROM {node} n INNER JOIN {users} u ON u.uid = n.uid WHERE n.type = '%s' AND n.status = %d", array('page', 1)); // DBTNG. Note that multiple arguments should be wrapped on seperate lines. $result = db_query("SELECT n.nid, u.name FROM {node} n INNER JOIN {users} u ON u.uid = n.uid WHERE n.type = :type AND n.status = :status", array( ':type' => 'page', ':status' => 1, )); ?>
2つめは、データの取り出しの部分を修正することです。単に結果をループするような場合は、シンプルにforeach構文を使うと良いでしょう。デフォルトの結果セットはオブジェクトの形式になります。別の形式が必要な場合は、2つ方法があります。
例:
<?php // Old code, loop over a result. while ($row = db_fetch_object($result)) { } // DBTNG. foreach ($result as $row) { } // Old code, fetch a single field directly from a query. $nid = db_result(db_query('...')); // DBTNG. $nid = db_query('...')->fetchField(); ?>
静的クエリとデータ取得についての詳しい情報はhttp://drupal.org/node/310072 をご覧ください。
これらのクエリはdb_insert()、 db_update() 、そして db_delete()といったDBTNG仕様の構文に修正する必要があります。
アップデートクエリの例:
<?php // Old code. db_query("UPDATE {profile_field} SET weight = %d, category = '%s' WHERE fid = %d", $weight, $category, $fid); // DBTNG. db_update('profile_field') ->fields(array( 'weight' => $weight, 'category' => $category, )) ->condition('fid', $fid) ->execute(); ?>
クエリのパフォーマンス改善のヒント:
DBTNGは、次のような操作を行うためのフレキシブルなクエリービルダーを提供します。
クエリービルダーはDBTNGの非常にパワフルな機能の一つです。これは最初は複雑に思えるかもしれませんが、クエリを文字列として組み立てるよりはるかに堅牢です。ここではクエリービルダーのコンセプトを簡単に説明します。詳しくはダイナミッククエリをご覧ください。
ダイナミッククエリを構築する場合、それは最初から始めるのがベストですが、以下のようなポイントが参考になるでしょう。クエリオブジェクトの作成を最初に行い、最後に実行するのは明らかなことですが、その他の操作、コマンドの順番はクエリ構築には影響せず、変更が可能です。
<?php $query = db_select('node', 'n'); ?>
<?php $query->join('node_comment_statistics', 'l', 'n.nid = l.nid'); ?>
<?php $query ->addTag('node_access') ->addTag('custom_tag'); ?>
<?php $query ->fields('n', array('nid', 'title', 'body')) // Select the specified fields from the node table. ->orderBy('n.nid', 'DESC') // Adds a ORDER BY n.nid DESC. ->condition('n.type', 'page') // Only load nodes with the type page. ->range(0, 5); // Load the first 5 rows. ?>
<?php if (!empty($uid)) { $query->condition('n.uid', $uid); } ?>
<?php $nodes = $query ->execute() ->fetchAllAssoc('nid'); ?>
これまでの手順をまとめて見てみましょう。なるべくメソッドチェーンで記述できるように、操作の順番を考えています。
<?php $query = db_select('node', 'n'); $query->join('node_comment_statistics', 'l', 'n.nid = l.nid'); if (!empty($uid)) { $query->condition('n.uid', $uid); } $nodes = $query ->addTag('node_access') ->addTag('custom_tag') ->fields('n', array('nid', 'title', 'body')) // Select the specified fields from the node table. ->orderBy('n.nid', 'DESC') // Adds a ORDER BY n.nid DESC. ->condition('n.type', 'page') // Only load nodes with the type page. ->range(0, 5) // Load the first 5 rows. ->execute() ->fetchAllAssoc('nid'); ?>
pager_query() はDrupal7ではクエリーエクステンダーのページャーデフォルトに置き換わりました。ダイナミッククエリで使用することが出来ます。
クエリーエクステンダーは追加機能によってクエリービルダーを拡張します。クエリーエクステンダーは一度に複数使用することが出来ます。
例えばこのようになります。
<?php $query = db_select('node', 'n')->extend('PagerDefault'); ?>
<?php $query->limit(10); ?>
Important: extend() returns a new query object. Because of that, it is adviced to extend the query object early as shown in the example. If that is not possible, overwrite the existing object reference as shown below:
<?php $query = $query->extend('PagerDefault'); // Chaining does still work. $result = $query ->extend('PagerDefault') ->limit(5) ->execute(); ?>
For table based sorting, there is another Query extender. As before, first extend the query object and then use the orderByHeader($header) method.テーブルソートには専用のクエリーエクステンダーがあります。前と同じように最初にクエリーオブジェクトを拡張し、それからorderByHeader($header) メソッドを使うようにします。
<?php $query = db_select('node', 'n')->extend('TableSort'); $query ->orderBy('uid', 'DESC') // Sort by uid first. ->orderByHeader($header) // Then by what has been selected in the table header ->orderBy('changed', 'DESC') // And at last, by the changed date. ?>
コメントをどうぞ。