前回までの作業で、すべてのフローの画面設計とバリデーション定義が一旦完了となりました。今回から2回に渡って、画面設計によって洗い出された項目に基づいてデータベースのテーブルを作成し、アプリケーションにPiece_ORMを使ったデータアクセスを組み込んでいきます。
データベース設計とテーブル定義
データベースのテーブルを作成するためには、当然ながら作成対象の項目(フィールド)がわかっていなければいけません。今回の開発プロセスでは、すでに各画面のフィールドが洗い出されていますので、それを利用することにしましょう。下記は画面と画面のフィールドの対応表になります。
画面 | フィールド1 | フィールド2 |
新規エントリー入力画面 | タイトル | 内容 |
新規エントリー入力確認画面 | タイトル | 内容 |
エントリー一覧画面 | タイトル | |
エントリー参照画面 | タイトル | 内容 |
エントリー編集画面 | タイトル | 内容 |
エントリー削除確認画面 | タイトル | 内容 |
ごらんの通り、今回は「タイトル」と「内容」の2つのフィールドしかありませんので、これらを「エントリー」テーブルとして表現することにします。また、これらの2つのフィールドでは1つのエントリーを特定できないため、連番型のフィールドも用意し、そのフィールドをプライマリキーに指定します。以上を表現するテーブル作成用のSQLは下記のようになります。
データベース及びユーザの作成
次に、データベースサービスを起動し、PostgreSQLのデータベースとユーザを作成します。なお、今回はデータベース及びユーザ、パスワードのいずれもpieceblogという文字列を使うことにします。下記はpgbashを使った作成例です。
作成が完了したら、接続のテストをしておきましょう。
テーブルの作成
続いて、先ほどのテーブル作成用のSQLを使ってテーブルを作成します。
以上でデータベース側の準備は完了です。
PieceORMコンポーネントとMDB2_Driver_pgsqlのインストール
PHPからデータベースにアクセスするには下記の方法が考えられます。
- PHPにバンドルされている各RDBMS用のエクステンションを直接使う(抽象度: 低)
- 古くはPEAR::DBに代表されるようなデータベース抽象化ライブラリを使う(抽象度: 中)
- オブジェクトリレーショナルマッピングフレームワークを使う(抽象度: 高)
抽象度が高くなるにつれて、コードの重複や制御フローの不具合の削減が期待でき、ユーザはより本質的なコードのみを記述できるようになります。今回は、上記の中で最も抽象度の高いオブジェクトリレーショナルマッピングフレームワークのひとつ、Piece_ORMを使ってデータアクセスを実装していきます。
Piece_Unityを使ったアプリケーションでPiece_ORMを使う場合、Piece_ORMの設定をPiece_Unityから行うためのPieceORMコンポーネントを使うとより便利です。Piece_Unityでは、コア機能以外のコードが個別のパッケージとして提供されており、それらはPiece_Unityコンポーネントと呼ばれています。
では、下記のようにPieceORMコンポーネントをインストールしましょう。この時、環境にPiece_ORM, MDB2がインストールされていなければ自動的にインストールされます。
MDB2はそれ単体では抽象化されたAPIを定義しているにすぎませんので、実際に各RDBMSにアクセスするためには各RDBMS用のドライバが必要になります。今回はPostgreSQLを使っていますので、PostgreSQL用のドライバであるMDB2_Driver_pgsqlをインストールします。
以上で必要なパッケージのインストールは完了です。
PieceORMコンポーネントの設定
PieceORMコンポーネントを利用するためには、ふたつのプラグイン、ConfiguratorChain及びConfigurator_PieceORMの設定が必要となります。ConfiguratorChainはPiece_Unity自体が提供するプラグインで、Piece_Unityコンポーネントやアプリケーションを設定するプラグイン(コンフィギュレータ)を実行するために使用されます。Configurator_PieceORMは、PieceORMコンポーネントが提供するプラグインで、Piece_ORMを設定するために使用されます。これらのプラグインの設定は下記のようになります。
ConfiguratorChainプラグインの拡張ポイントconfiguratorsは、実際に設定を行うためのプラグインを登録するために使用されます。Piece_Unityはこの拡張ポイントに登録されたプラグインを、自身の実行環境構築後に実行します。上記の場合は、Configurator_PieceORMプラグインが実行されることになります。
Configurator_PieceORMプラグインの設定ポイントについては下記の表をご参照ください。また、設定した各ディレクトリを忘れずに作成しておきましょう。
設定ポイント | 概要 |
configDirectory | Piece_ORM設定ファイル(piece-orm-config.yaml)の配置先ディレクトリ |
cacheDirectory | 各種キャッシュの配置先ディレクトリ |
mapperConfigDirectory | マッパー定義ファイルの配置先ディレクトリ |
データアクセスコード配置先の検討とフローの変更-新規エントリー入力フロー
Piece_ORMを使ったデータアクセスの準備が整いましたので、いよいよアプリケーションにデータアクセスコードを組み込んでいきます。新規エントリー入力フロー以外の2つのフローでは、レコードの存在が前提になってきますので、最初に新規エントリー入力フローに対してデータアクセスコードを実装することにします。
さて、いきなりコードを書き始めたいところですが、まずはコードの配置先について検討してみましょう。新規エントリー入力フローにおいてレコード作成が期待されるタイミングは、新規エントリー入力確認画面のCreateボタンがクリックされたときになります。
現在のフロー定義では、CreateボタンがクリックされるとDisplayNewFinishFromDisplayNewConfirmイベントが発生し、DisplayNewFinishステートに遷移します。コードの配置先として考えられるのは、遷移イベント発生時、ステートからの退場時、ステートへの入場時、そしてステート更新時のいずれかのイベントハンドラです。現在のところ、最もシンプルかつ意図が明確なことから、筆者はビュー関連以外のコードをアクションステートのアクティビティ(ステート更新時のイベントハンドラに対応)に配置することを推奨しています。しかしながら、現在のフロー定義にはまだ対応するアクションステートが存在しないため、新たに作成する必要があります。以上を踏まえて、フロー定義にステートProcessCreateNewを追加し、そのアクティビティを準備します。変更前後のフロー定義ファイル及びステートチャート図を下記に示します。
その他にも、HTMLテンプレートに埋め込まれたイベント名の変更、アクションクラスへのイベントハンドラの追加を行う必要があります。
変更が完了したら、ブラウザから動作を確認しておきましょう。
データアクセスコードの実装─新規エントリー入力フロー
では、データアクセスコードの実装を行います。具体的な作業は、アクションクラスへのデータアクセスコードの実装、マッパー定義ファイルの作成、Piece_ORM設定ファイルの作成の3つになります。下記はデータアクセスコードの実装です。
最初にコンストラクタのstdClassのインスタンスを生成していた部分がPiece_ORM::createObject('Entry')で置換されていますが、返されるオブジェクトは依然としてstdClassのインスタンスであることに注意してください。元のコードとの違いは、Piece_ORM::createObject()によってあらかじめテーブルのフィールドに対応したプロパティが用意されていることだけです。
イベントハンドラには実際のデータアクセスコードが記述されています。Piece_ORM::getMapper()は引数に与えられたマッパー名に対応するマッパーオブジェクトを返します。$mapper->insert()は、引数に与えられたオブジェクトを新規レコードとしてマッパーに対応するテーブルに追加します。
マッパー名はテーブル名に対応しており、マッパーのコンテキストではテーブル名はキャメルケースで取り扱われます。名称の先頭は大文字に変換されます。また、“_”(アンダースコア)は削除され、“_”(アンダースコア)の直後の文字が大文字に変換されます。今回の場合、対象テーブル名はentryなのでマッパー名はEntryになります。
現在のところ、Piece_ORMはメタデータに基づいたマッパーオブジェクト生成を行いません。言い換えると、対象テーブルが存在することによってマッパーが有効になるわけではありません。そのため、Entryマッパーを有効にするには、マッパー定義ファイルEntry.yamlを準備する必要があります。マッパー定義ファイルの最も重要な用途は対象テーブルのマッパーを有効にすることです。その他の用途としては、任意のメソッド名とSQLのマッピング、SQLのオーバーライト、メソッドに対するリレーションシップの設定などがあります。対象テーブルのマッパーを有効にする用途のみに使用する場合は、単に空のファイルを用意します。よって今回の場合、空のファイル/path/to/pieceblog/web/webapp/config/orm/mappers/Entry.yamlを作成することになります。
最後の作業は、データベースへの接続情報をPiece_ORM設定ファイルに定義することです。
作業が完了したら、ブラウザから動作を確認してください。エラーが発生せずにエントリー一覧画面が表示されたら成功です。現段階ではエントリー一覧画面には本物のレコードは反映されないため、直接データベースにアクセスし、レコードが追加されているかどうかを確認しましょう。
おわりに
今回はデータベース設計とテーブル定義、各種環境設定を行ったあと新規エントリー入力フローにデータアクセスコードを組み込みました。
上記のようにPiece_ORMによるデータアクセスコードは非常に簡潔なものになります。一般的にアクションクラスへのデータアクセスコードの配置は推奨されていませんが、上記のような簡潔なコードを別のクラスに配置することに意味があるとは思えません。筆者はPiece_ORMを使ったデータアクセスコードはむしろイベントハンドラに記述することを推奨しています。とはいえ、イベントハンドラやアクションクラスが複雑になったときは、他のクラス同様メソッド抽出やクラス抽出によるリファクタリングを行ってください。
次回は残りの2つのフローにデータアクセスコードを組み込み、アプリケーション全体がデータベースを使った形で動作するようにします。