はじめに
最近、お仕事でDrupalというオープンソース CMSを使ってWebアプリの開発をしています。
僕の担当はカスタムモジュールの開発です。
開発の際、既存のコアモジュールやコントリビュートモジュールを取り入れて、連携させることも多いです。
その中で既存のモジュールについて調査したことをメモしていたのですが、結構そのまま記事にできそうな感じにまとまってきたので、備忘録も兼ねて少しずつアウトプットしてみようかなと思っています。
ということで、今回はDatabase APIというDrupalのコアモジュールについてまとめてみます。
このモジュール、公式ドキュメントを見ていただいたらわかる通り、結構ボリューミーです。
なので、複数記事に分けてまとめていきます。今回は概要とコンセプトまでです。
※ 英語で書かれているドキュメントを日本語に訳しながらまとめています。よって、翻訳ミスやニュアンスの違い等があるかもしれないことをご承知おきください。
Database APIとは
概要
データベースサーバにアクセスするためのDrupalのコアモジュールです。
標準的でベンダーに依存しない抽象化レイヤーを提供しています。
コアモジュールを開発している場合を除き、DrupalではDBを直接操作することはほぼありません。
そのため、Database APIのようなそれ用のモジュールを使って操作することになります。
データベースを操作する機能をもつモジュールは、他にEntity APIなどがあります(こちらも少し触っていたので、いずれ記事にまとめるかもしれません)。
特徴としては、以下の5つがあります。
- 複数のデータベースサーバを簡単にサポートする
- トランザクションなどのより複雑な機能をサポートする
- 先ほど似た機能を持つとして名前を挙げたEntity APIは、トランザクションをサポートしていません
- クエリを動的に構築するための、構造化されたインターフェースを提供する
- セキュリティチェック等の適切な慣行をサポートする
- サイトのクエリを遮断して修正するための、クリーンなインターフェースをモジュールに提供する
コンセプト
Drupalのデータベースレイヤーは、PHPのPDOライブラリの上に構築されています。
PDOは異なるデータベースにアクセスするための統一されたオブジェクト指向のAPIを提供しますが、異なるデータベースで使用されるSQLの異なる文法を抽象化することはできません。
要するに、複数のデータベースが必要なアプリケーションがあった場合に、データベースAではMySQL、データベースBではPostgreSQLを使って構築する、といった使い方はできないということですね。
データベースへの接続方法
PDOクラスを継承した\Drupal\Core\Database\Connectionクラスのオブジェクトを使うことで、データベースに接続します。
具体的には、以下のように記述します。
$database = \Drupal::database();
// or
$database = \Drupal::service('database');
上記の方法が利用できない場合は、以下のように記述することも可能です。
これで、現在アクティブなデータベースに接続することができます。
$conn = \Drupal\Core\Database\Database::getConnection();
ほとんどの場合、データベース名の指定は不要ですが、複数のデータベースを利用している場合はどれに接続するのか指定してあげる必要があります。
これは、以下のように記述することで可能です。
$conn = \Drupal\Core\Database\Database::setActiveConnection('external');
ステートメントオブジェクト
ステートメントオブジェクトは、Selectクエリを実行した結果として返ってきます。
これは常にDatabaseStatement型かそれのサブクラスとなり、DatabaseStatementはPDOStatementクラスを継承しています。
また、Drupalはすべてのクエリにプリペアドステートメントを使用します。
プリペアドステートメントはクエリのテンプレートであり、実行時に値が挿入されます。
実行時というのは、execute()
メソッドが実行されたときですね。
通常のPDOでは、明示的にステートメントオブジェクトを準備し、クエリ内のプレースホルダーに特定の値をバインドして実行する必要があります。
一方で、Drupalはプリペアドステートメントを直接公開するわけではありません。
その代わり、モジュール開発者はクエリオブジェクトまたは単発のSQLを使ってクエリを実行し、そのクエリのステートメントオブジェクトが返されます。
最後に
今回は、概要からコンセプトまでをまとめました。
次回はStatic Queriesについてを記事にしようと思います。