Doctrineでschemaの継承をする(Doctrine2 Inheritance Mapping + symfony2)

こんにちは、光永です。
Doctrine2+Symfony2 で、Inheritance Mappingを利用する、というのを去年やってみたところ、
思ったより情報を探すのに苦悩したので後学のためまとめておきます。

やりたいこと

  • ほぼ同じ構造を持ったテーブルを、複数作成する。
  • 一部カラムについては別々に命名し、Entity上のみ同一カラムとして扱う。
    • 例: hogehoge1_id / hogehoge2_id => $hogehogeId

データ構造

  • MappedSuperclass(継承元)に同一構造部分はまとめる。
  • sub class(敬称先)には、差分のみ定義。

イメージ

User テーブル

No 論理名 物理名 備考
1 ID id int
2 名称 name string
3 所属 group_id int ※ $groupIdとして扱う

Admin テーブル

No 論理名 物理名 備考
1 ID id int
2 名称 name string
3 E mail mail string
4 所属 admin_group_id int ※ $groupIdとして扱う

手順

  1. mappedSuperclassのymlをResources\config\doctrine直下に作成。
    また、entityファイルをEntity直下に作成。
# ...\Resources\config\doctrine\User.orm.yml
...\Resources\config\doctrine\User:
  type: mappedSuperclass
  id:
    id: ...
  fields:
    name: ...
    ...
// ...\Entity\User.php
namespace ...\Entity;
/**
 * User
 */
abstract class User
{
}
  1. subClassをResources\config\doctrine直下に作成。
    また、entityファイルをEntity直下に作成。
# ...\Resources\config\doctrine\Admin.orm.yml
...\Resources\config\doctrine\Admin:
  type: entity
  extends: itemRecord
  table: admin
  # 追加フィールド
  fields:
    mail: ...
  # $groupIdを override
  attributeOverride:
    groupId:
      column: admin_group_id
      type: integer
// ...\Entity\Admin.php
namespace ...\Entity;
/**
 * Admin
 */
class Admin extends User
{
}
  1. doctrine:generate:entitiesコマンドで、mappedSuperclass・subClassとも作成。
php app/console doctrine:generate:entities BundleName:EntityName
  1. doctrine:schema:updateでDBに反映。以下のようなSQLが発行されていれば成功。
    ※Userテーブルは生成されない。
INSERT INTO `admin` (...);

課題

  • mappedSuperclass

    • doctrine:generate:entities
      • orm.ymlファイルはResources\config\doctrine直下にしか置くことができない。(Symfonyのルール上)
        そのため、MappedSuperclassだけを別階層に置いておくことができず、継承元としてのみの役割のファイル・通常の定義ファイルが同階層に混ざる。
      • コマンドを実行しても、MappedSuperclassのクラスは自動でabstractにならない。手動でabstract付けること。
      • MappedSuperclassのフィールドがprivateで作成されてしまう。protectedでの生成はコマンド自体を改造しないと無理らしいので、とりあえず手動で文字列置換。
  • sub class

    • doctrine:generate:entities
      • extendsは自動で記述されない。手動で書くこと。
    • attribute override (attributeOverride)
      • 記載左記Entityのdoctrine:generate:entitiesでこける。(v2.5.6で確認)
        バグがある模様(v2.5.6で確認)
        https://github.com/doctrine/doctrine2/issues/3433
        によるとcomposer.jsonの指定を"2.4@dev"にしなさいのこと。
        ダウングレードなんですけど。。。と思いつつやってみるも、直らない
        しかたなし、上記コマンド発行の間だけコメントアウトして動かしている。
        どなたか改善方法教えてください。

参考

総評

わりと課題あるやんけ

以上、お役に立てれば幸い。
光永でした。