Drupal 8でデータベース(RDB)の処理を行う

  •  
 
トビウオ2018年8月15日 - 15:30 に投稿

タグ

概要

 別にPDOでアクセスしても文法上は問題ないのですが、Drupalが使用しているデータベースに情報を読み書きする場合は、より簡単にデータベース処理を書くことができます。なので、その詳細についてまとめました。

使い方

事前準備

 モジュール名をXXXとした際、XXX.info.ymlと同じフォルダにXXX.installファイルを作成します。そして、その中にスキーマ定義を記述します。
 次は入力サンプルですが、おおよそフィーリングで書き方は掴めるでしょう。「$schema['HOGEHOGE']」と書けば、テーブル「HOGEHOGE」が自動生成されます。
 ややこしい点としては、Datetime型の名称がRDBによって多少異なるため、「type」の書き方が若干冗長になってしまっていることがあります( CSSみを感じる)。
 なお、スキーマ定義を変更した場合、モジュールの再インストールが必要になります。再インストールするとそのモジュールが使用していたテーブル情報が消えてしまうため、事前のバックアップが重要です。

<?php

/**
 * スキーマ定義
 */
function simple_chat_schema() {
  $schema['chat_talk_data'] = [
    'description' => 'Logging chat data.',
    'fields' => array(
      'id' => array(
        'description' => 'Talk ID',
        'type' => 'serial',
        'not null' => TRUE,
      ),
      'message' => array(
        'description' => 'Message',
        'type' => 'varchar',
        'length' => 4096,
        'not null' => TRUE,
      ),
      'name' => array(
        'description' => 'User Name',
        'type' => 'varchar',
        'length' => 256,
        'not null' => TRUE,
      ),
      'date' => array(
        'description' => 'Talk DateTime',
        'mysql_type' => 'timestamp',
        'pgsql_type' => 'timestamp',
        'sqlite_type' => 'datetime',
        'length' => 256,
        'not null' => TRUE,
      ),
    ),
    'primary key' => array('id'),
  ];
  return $schema;
}

クエリの叩き方

 事前準備が完了していれば、Drupalが使用するデータベース内に、設定したテーブルが作成されているはずです。後は、テーブル名を指定してRDBを使用できます。
 なお、SELECT文を発行する際はdb_queryの方が高速ですが、db_selectの方がより簡潔にクエリを書くことができます。

// db_queryは任意のSQLを実行する
db_query("INSERT INTO {sample_table} (message, name) VALUES('{message}','{name}')");

// ただしセキュリティ上の問題から、置き換え処理が推奨されている
db_query("INSERT INTO {sample_table} (message, name) VALUES(:message,:name)", [':message' => $message, ':name' => $name]);

// 条件を指定して削除する例
db_query("DELETE FROM {sample_table} WHERE id=:id", [:id => 3]);

// db_selectはSELECT文しか実行できないが、メソッドチェーンを利用して書ける
// ここで「'n'」はテーブル名の別名で、SQLにおける「AS」のようなもの
$result = db_select('node', 'n')
  ->fields('n', array('nid'))
  ->condition('type', $type)
  ->orderBy('nid')
  ->execute();

// fieldsはでSELECTする列をarray型で指定し、conditionで条件を指定します
// (orderBy、limitはSQLと同じ意味なので割愛)
$select = db_select('node', 'n')
  ->fields('n', ['nid', 'sticky', 'created'])
  ->condition('n.promote', 1)
  ->condition('n.status', 1, '=')
  ->condition('n.age', 20, '>=')
  ->condition('n.tail', 180, '<=')
  ->condition('n.type', ['dog', 'cat', 'monkey'], 'IN')
  ->condition('n.weight', [50, 80], 'BETWEEN')
  ->orderBy('n.sticky')
  ->orderBy('n.created', 'DESC')
  ->limit(5)
  ->execute();

※余談ですが、MySQLで日付情報(timestamp型)を書き込む際は「文字列として」書き込むらしいですね……しかもタイムスタンプの情報がないので、UTCで書き込み・任意のタイムゾーンで読み出す処理を書くのに苦労しました。Drupalにおいて、ユーザーが使用しているタイムゾーンは「drupal_get_user_timezone()」で取得でき、DateTimeZone型にするには「new DateTimeZone(drupal_get_user_timezone());」とします

ちなみに

 db_selectdb_queryDrupal 9.0で削除予定……だと……!?

Deprecated
as of Drupal 8.0.x, will be removed in Drupal 9.0.0. Instead, get a database connection injected into your service from the container and call 
select() on it. For example, $injected_database->select($table, $alias, $options);

Deprecated
as of Drupal 8.0.x, will be removed in Drupal 9.0.0. Instead, get a database connection injected into your service from the container and call 
query() on it. For example, $injected_database->query($query, $args, $options);

参考

コメントを追加

プレーンテキスト

  • HTMLタグは利用できません。
  • 行と段落は自動的に折り返されます。
  • ウェブページのアドレスとメールアドレスは自動的にリンクに変換されます。
CAPTCHA
この質問はあなたが人間の訪問者であるかどうかをテストし、自動化されたスパム送信を防ぐためのものです。