Doctrine2の小ネタ(データベースからエンティティを作る&エンティティの継承編)

こんにちは、今回は

  • データベースのテーブル定義から、エンティティを作成する方法。
  • エンティティクラスを継承関係を用いて活用する方法。

を解説したいと思います。

既存のアプリケーションをSymfony2に移行する場合に役に立つのではないでしょうか?

データベースのテーブル定義から、エンティティを作成する方法

実は、既にあるデータベースからエンティティを生成する方法という公式ページですでに解説されています。

が、Annotationでエンティティを管理する場合、

php app/console doctrine:mapping:import --force AcmeBlogBundle xml

だとXmlファイルが作成されてしまい、annotationが無効となってしまう(xmlによる設定とanntationによる設定は共存できない)問題が発生してしまいます。
なので、

php app/console doctrine:mapping:convert annotation ./src --from-database --namespace="Acme\BlogBundle\Entity\\"
php app/console doctrine:generate:entities AcmeBlogBundle

とした方が、初めからAnnotaion付きのエンティティが作成されるので、よいです。namespaceの最後のバックスラッシュの2重はダブルクォーテーションのエスケープを避け、バックスラッシュを文字列として認識させるためです。
結果、src/Acme/BlogBundle/Entity/にエンティティクラスが作成されます。

エンティティクラスを継承関係を用いて活用する方

エンティティは、Doctrine2では、PHPのクラスとして作成されています。したがって、継承など、PHPのクラスに用いられる方法が活用できます。
さて、これは活用方法の1例ではありますが、当社の社内システムにおけるDBのテーブルのカラムには基本的に

  • 主キー(id)
  • データの作成日時
  • データの最終更新日時

が、大体のテーブルに含まれています。そして、そのカラム名はすべて、id,created_at,updated_atとなっています。これを、エンティティの継承で実現させてみましょう。

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\MappedSuperclass
 * @ORM\HasLifecycleCallbacks()
 */
class UtilEntity{

    /**
     * @var bigint $id
     *
     * @ORM\Column(name="id", type="bigint", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $id;

    /**
     * @var datetime $createdAt
     *
     * @ORM\Column(name="created_at", type="datetime", nullable=false)
     */
    protected $createdAt;

    /**
     * @var datetime $updatedAt
     *
     * @ORM\Column(name="updated_at", type="datetime", nullable=true)
     */
    protected $updatedAt;

    public function __construct($id = null){
        $this->id = $id;
    }

    /**
     * Get id
     *
     * @return bigint
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set createdAt
     *
     * @param datetime $createdAt
     */
    public function setCreatedAt($createdAt)
    {
        $this->createdAt = $createdAt;
    }

    /**
    * @ORM\prePersist
    */
    public function setCreatedValue()
    {
        $this->createdAt = new \DateTime();
    }

    /**
     * Get createdAt
     *
     * @return datetime
     */
    public function getCreatedAt()
    {
        return $this->createdAt;
    }

    /**
     * Set updatedAt
     *
     * @param datetime $updatedAt
     */
    public function setUpdatedAt($updatedAt)
    {
        $this->updatedAt = $updatedAt;
    }

    /**
     * Get updatedAt
     *
     * @return datetime
     */
    public function getUpdatedAt()
    {
        return $this->updatedAt;
    }

    /**
    * @ORM\prePersist
    * @ORM\preUpdate
    */
    public function setUpdatedValue()
    {
        $this->updatedAt = new \DateTime();
    }
}

という、Utilなエンティティクラスを作成します。ポイントは

  • @Entityを付与しないと@ORM\HasLifecycleCallbacks()がなぜか認識してくれない
  • @Entityが存在するとき、必ず@Idを付与したプロパティが1つはないといけない
  • @prepersist(Insert時)に現在の日時をcreated_atに挿入する(setCreatedValue)
  • @prepersist(Insert時)、@preupdate(Update時)に現在の日時をupdated_atに挿入する(setUpdatedValue)

です。
Doctrineのイベントに関しては、http://docs.symfony.gr.jp/symfony2/book/doctrine.html#lifecycle-callbackを参考にしてください。

最後に、このUtilEntityクラスを継承した、エンティティクラスは、id,created_at,updated_atに関する記述をおこなう必要がなくなります。

もちろん、継承したエンティティを使い

php app/console doctrine:schema:update --force

とすれば、エンティティがid,created_at,updated_atを持っているので、正確なテーブルを作成することができるでしょう。

今回はこれで失礼いたします。

投稿者プロフィール

開発 アルバイト
中の人には主に、
PHP・Symfony2系の人と
Ruby・Rails系の人がいます。
ときどきJavascript・データベースにも手を出すかもしれません。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Time limit is exhausted. Please reload CAPTCHA.