Phalconモデルまとめ(2)リレーション

「最速」PHPフレームワークPhalconのモデルについて、基本事項をまとめます(公式ドキュメントの翻訳+αです)。記事執筆時のPhalconのバージョンは1.3.1です。

リレーションの定義

Phalconでは、リレーションはモデルのinitialize()メソッドの中で定義する必要があります。リレーションを定義するメソッドには4種類あり、いずれも「自分自身のフィールド名(≒カラム名)」「参照するモデル名」「参照するフィールド名」の3つのパラメータをとります。

メソッド 状態
hasMany 1対多
hasOne 1対1
belongsTo 多対1
hasManyToNany 多対多

以下のようなテーブルの関係を考えてみます。

  • 1つのRobotsは、1つ以上のRobotsPartsをもつ
  • 1つのPartsは、1つ以上のRobotsPartsをもつ
  • 1つ以上のRobotsPartsが、Robotsに属する
  • 1つ以上のRobotsPartsが、Partsに属する
  • RobotsとPartsは、RobotsPartsを介して、多対多の関係になっている(RobotsPartsは中間テーブル)

ER:robots-robots_parts-parts

それぞれのモデルは以下のように実装できます(Phalcon DevToolsはv1.3.1現在、リレーションの自動生成には対応していません。リレーションの記述は手動で行う必要があります)。

リレーション定義メソッドの第1引数には、自分自身のフィールド名、第2引数には参照するモデル名、第3引数には参照するモデルのフィールド名を渡します。複数のフィールドのリレーションを指定したい場合、配列を使うこともできます。

3つのモデルからなる多対多の関係を単一のメソッドで記述すると、以下のようになります。

リレーションを活用する

モデルの関係が明示的に定義されると、関連するレコードを簡単に一括取得できます。

Phalconは、関連するモデルへのデータの保存・取得にマジックメソッド(__set/__get/__call)を用います。

リレーションと同じ名前のプロパティにアクセスすると、関連するレコードが自動で取得されます。

getterもマジックメソッドで実装されています(明示的な定義が不要なgetter:マジックゲッター)。

PhalconMvcModelは、「get」が頭についているメソッドの呼び出しがされると、findFirst()又はfind()の結果を返します。以下の例では、マジックゲッターを使った場合と使わない場合とを比較しています。

関連するレコードを手動で取得する場合:

「get」という接頭辞は、find()/findFirst()する際に使用されます。どのメソッドが呼ばれるかは、リレーションの種類によります。

種類 説明 メソッド
belongsTo 関連するレコードのモデルを返す findFirst
hasOne 関連するレコードのモデルを返す findFirst
hasMany 関連するモデルの検索結果を返す find
hasManyToMany 関連するモデルの検索結果を返す(暗黙的にINNER JOINを行う) (複雑なクエリ)

「count」という接頭辞を使うことで、関連レコードの数を数えることもできます。

リレーションのエイリアス

エイリアスの働きを説明するため、以下の例を使用します。

「robots_similiar」は、あるロボットと別のロボットの類似性を定義しています。

ER:robots-robots_similar

このリレーションは以下のように実装できます。

いずれのリレーションも同じモデルを指しているため、どのレコードを取得するのか判然としません。

エイリアスを使うことで、リレーションの名前を付け直すことができます。

エイリアスを使うことで、レコードの取得は簡単になります。

仮想外部キー制約

デフォルトでは、リレーションはRDBの外部キー制約のようには動作しません。外部キー制約によってエラーとされるような値をDBに入れようとした場合、Phalconは何のバリデーションエラーも発しません。リレーション定義時の第4引数にパラメータを設定することで、この挙動を変更できます。

belongsTo()リレーションが外部キー制約として振る舞うように変更すると、DBへの値の登録時にも、外部キー制約によるバリデーションが行われるようになります。同じように、hasMany()/hasOne()の振る舞いが変更されると、その値が別テーブルから参照されている限り、削除することができなくなります。

CASCADEとRESTRICT

仮想外部キー制約として働くリレーションは、デフォルトでは作成・更新・削除に制限を加え、データの完全性を保ちます。

上記コード例では、マスタとなるロボットのレコードが削除されると、それを参照しているパーツのレコードも全て削除されるように設定しています。

[補足]名前空間とエイリアス

Phalcon公式ドキュメントには無いけれど、知っておいたほうが良いワザとして、「名前空間のエイリアス設定」があります。名前空間を使用したモデルへのリレーション設定は1つ上のサンプルで、エイリアスも別のサンプルにはありますが、両方を一度に扱ったサンプルはありません。モデルに名前空間を使用している場合、エイリアスの使用は必須に近いと思うので、ここで紹介しておきます。

上記のような設定を行ったモデルでは、以下のようにしてStoreModelsPartsにアクセスすることができます。

しかし、いちいち名前空間をフルパスで書くのはいかにも面倒臭い。この場合、エイリアスを利用すると幾分楽ができます。

今回はここまで

ここまでで、リレーションの基本は押さえました。次回は、Generating Calculationsから先をみていきます。

コメントを残す