トップ  > symfony  > モデル ( doctrine )  > 記事

No.1304 Doctrineの継承機能について

Doctrineの継承機能についてAdd Star


よくあるオブジェクトリレーショナルマッパーは基本的に1つのテーブルに対して1つのモデルオブジェクトを定義します。このときにモデルオブジェクト間に 親子関係を持たせたり、いくつかのモデルに対して抽象クラスを作りたいと思ったことはありませんか?Doctrineには継承に関する3つのパターンが用 意されており、今回はそれをご紹介したいと思います。

まずは3つのパターンの概要を説明します。

・Simple inheritance
単純に1つのテーブルに対して複数のモデルを作成する方法です。
どのレコードがどのモデルに対応するかは特に判断は行いません。

・Concrete inheritance
モデル1つひとつに対してテーブルを作成する方法です。
テーブルごと分けるため、カラムもテーブルごとに定義されます。

・Column Aggregation inheritance
単純に1つのテーブルに対して複数のモデルを作成する方法です。
Simple inheritanceと違い、各レコードに対してモデルに対応するキーを付与してレコードの判断を行います。


では実際のコードを見つつ、詳細について説明していきたいと思います。

◆Simple inheritance

  1. # schema.yml
  2. Log:
  3.   columns:
  4.     code: string(255)
  5.     message: string(255)
  6.  
  7. ErrorLog:
  8.   inheritance:
  9.     extends: Log
  10.     type: simple
  11.   columns:
  12.     exception_class: string(255)
  13.  
  14. ApplicationLog:
  15.   inheritance:
  16.     extends: Log
  17.     type: simple

  1. <?php
  2. // Log.php
  3. class Log extends sfDoctrineRecord
  4. {
  5.     public function setTableDefinition()
  6.     {
  7.         $this->setTableName('log');
  8.         $this->hasColumn('code', 'string', 255, array(
  9.              'type' => 'string',
  10.              'length' => '255',
  11.              ));
  12.         $this->hasColumn('message', 'string', 255, array(
  13.              'type' => 'string',
  14.              'length' => '255',
  15.              ));
  16.         $this->hasColumn('exception_class', 'string', 255, array(
  17.              'type' => 'string',
  18.              'length' => '255',
  19.              ));
  20.     }
  21.  
  22. }
  23.  
  24. // ErrorLog.php
  25. class ErrorLog extends Log
  26. {
  27. }
  28.  
  29. // ApplicationLog.php
  30. class ApplicationLog extends Log
  31. {
  32. }

一番単純なSimple inheritanceです。上記はログを残すためのLogテーブルと、ログの種類に分けていくつかの子クラスを作成する例になります。
この方法では取得した際にレコードがどのモデルに対応するのかは判断しないため、あまり使わないのではないかと思います。
上記のようなログの場合に、取得は全部まとめてやるけど作成するときに色々操作を変えたいというときなどに使用するとよいかと思います。


◆Concrete inheritance

  1. AbstractUser:
  2.   abstract: true
  3.   columns:
  4.     email: string(255)
  5.     name: string(255)
  6.     password: string(255)
  7.  
  8. User:
  9.   inheritance:
  10.     extends: AbstractUser
  11.     type: concrete
  12.   columns:
  13.     zip: string(8)
  14.     address1: string(255)
  15.     address2: string(255)
  16.  
  17. Admin:
  18.   inheritance:
  19.     extends: AbstractUser
  20.     type: concrete

  1. <?php
  2. // AbstractUser.php
  3. abstract class AbstractUser extends sfDoctrineRecord
  4. {
  5.     public function setTableDefinition()
  6.     {
  7.         $this->setTableName('abstract_user');
  8.         $this->hasColumn('email', 'string', 255, array(
  9.              'type' => 'string',
  10.              'length' => '255',
  11.              ));
  12.         $this->hasColumn('name', 'string', 255, array(
  13.              'type' => 'string',
  14.              'length' => '255',
  15.              ));
  16.         $this->hasColumn('password', 'string', 255, array(
  17.              'type' => 'string',
  18.              'length' => '255',
  19.              ));
  20.     }
  21.  
  22. }
  23.  
  24. // User.php
  25. class User extends AbstractUser
  26. {
  27.     public function setTableDefinition()
  28.     {
  29.         parent::setTableDefinition();
  30.         $this->setTableName('user');
  31.         $this->hasColumn('zip', 'string', 8, array(
  32.              'type' => 'string',
  33.              'length' => '8',
  34.              ));
  35.         $this->hasColumn('address1', 'string', 255, array(
  36.              'type' => 'string',
  37.              'length' => '255',
  38.              ));
  39.         $this->hasColumn('address2', 'string', 255, array(
  40.              'type' => 'string',
  41.              'length' => '255',
  42.              ));
  43.     }
  44.  
  45. }
  46.  
  47. // Admin.php
  48. class Admin extends AbstractUser
  49. {
  50.     public function setTableDefinition()
  51.     {
  52.         parent::setTableDefinition();
  53.         $this->setTableName('admin');
  54.     }
  55.  
  56. }

上記はUserの抽象クラスを作成して、それをベースにしたuserとadminテーブルを作成し、それぞれに対応するUserモデルとAdminモデルを作成する例です。
AbstractUserというモデルが抽象クラスとなります。schemaでabstractという属性を定義していますが、これをつけたモデルは抽象クラスとして定義されます。
先ほどとは違いテーブルが複数できるため、上記の用にテーブルは分けたい場合に使用します。なお親クラスに定義してあるカラムはそれぞれのテーブルに作成されます。

上記の例では抽象クラスを使用していますが、もちろん抽象クラスである必要はありません。とにかくテーブルを分けたい場合はConcrete inheritanceを使用すると思ってください。


◆Column Aggregation inheritance

  1. Product:
  2.   columns:
  3.     name: string(255)
  4.     description: string(255)
  5.     price: integer(4)
  6.     stock: integer(4)
  7.  
  8. Book:
  9.   inheritance:
  10.     extends: Product
  11.     type: column_aggregation
  12.   columns:
  13.     author: string(255)
  14.  
  15. Wear:
  16.   inheritance:
  17.     extends: Product
  18.     type: column_aggregation
  19.   columns:
  20.     size: string(255)
  21.     brand: string(255)

  1. <?php
  2. // Product.php
  3. class Product extends sfDoctrineRecord
  4. {
  5.     public function setTableDefinition()
  6.     {
  7.         $this->setTableName('product');
  8.         $this->hasColumn('name', 'string', 255, array(
  9.              'type' => 'string',
  10.              'length' => '255',
  11.              ));
  12.         $this->hasColumn('description', 'string', 255, array(
  13.              'type' => 'string',
  14.              'length' => '255',
  15.              ));
  16.         $this->hasColumn('price', 'integer', 4, array(
  17.              'type' => 'integer',
  18.              'length' => '4',
  19.              ));
  20.         $this->hasColumn('stock', 'integer', 4, array(
  21.              'type' => 'integer',
  22.              'length' => '4',
  23.              ));
  24.         $this->hasColumn('type', 'string', 255, array(
  25.              'type' => 'string',
  26.              'length' => 255,
  27.              ));
  28.         $this->hasColumn('author', 'string', 255, array(
  29.              'type' => 'string',
  30.              'length' => '255',
  31.              ));
  32.         $this->hasColumn('size', 'string', 255, array(
  33.              'type' => 'string',
  34.              'length' => '255',
  35.              ));
  36.         $this->hasColumn('brand', 'string', 255, array(
  37.              'type' => 'string',
  38.              'length' => '255',
  39.              ));
  40.  
  41.         $this->setSubClasses(array(
  42.              'Book' =>
  43.              array(
  44.               'type' => 'Book',
  45.              ),
  46.              'Wear' =>
  47.              array(
  48.               'type' => 'Wear',
  49.              ),
  50.              ));
  51.     }
  52.  
  53. }
  54.  
  55. // Book.php
  56. class Book extends Product
  57. {
  58. }
  59.  
  60. // Wear.php
  61. class Wear extends Product
  62. {
  63. }

Simple inheritanceと同様に単一のテーブルを複数のモデルで共有するColumn Aggregation inheritanceですが、Simple inheritanceとは大きな違いがあります。
Productクラスの定義の中に、typeというカラムが定義されています。これはColumn Aggregation inheritanceがレコードがどのモデルに対応するのかを特定するためのカラムです。setSubClassesというメソッドで実際にどのモデル に対してどの値が入るのかを定義しています。デフォルトでは子クラスのクラス名がtypeカラムに入るようになっているのでBookモデルの場合は Book、Wearモデルの場合はWearという文字が入るようになっています。

またこのtypeに入る値や、typeというカラム名は変更可能です。schema.ymlでは以下のようになります。

  1. Product:
  2.   columns:
  3.     name: string(255)
  4.     description: string(255)
  5.     price: integer(4)
  6.     stock:

引用元

更新:2009/08/11 08:55 カテゴリ: symfony  > モデル ( doctrine ) ▲トップ

FuelPHP

Mac

フロントエンド開発

web開発

プロマネ

マネタイズ

プレゼン

webサービス運用

webサービス

Linux

サーバ管理

MySQL

ソース・開発

svn・git

PHP

HTML・CSS

JavaScript

ツール, ライブラリ

ビジネス

テンプレート

負荷・チューニング

Windows

メール

メール・手紙文例

CodeIgniter

オブジェクト指向

UI・フロントエンド

cloud

マークアップ・テキスト

Flash

デザイン

DBその他

Ruby

PostgreSQL

ユーティリティ・ソフト

Firefox

ハードウェア

Google

symfony

OpenPNE全般

OpenPNE2

Hack(賢コツ)

OpenPNE3

リンク

個人開発

その他

未確認

KVS

ubuntu

Android

負荷試験

オープンソース

社会

便利ツール

マネー

Twig

食品宅配

WEB設計

オーディオ

一般常識

アプリ開発

Python

サイトマップ

うずら技術ブログ

たませんSNS

rss2.0