11
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Doctrine2でValueObject

Last updated at Posted at 2014-11-07

はじめに

実は結構前からDoctrine2のAnnocationでValueObjectを表現する事が出来ます。
しかし、まだ正式版のリリースはありません。。。
でも知りたい方への紹介、代替案の紹介、自身の暇つぶしも兼ねて記したいと思います。

準備

Symfony2のプロジェクト内(じゃなくてもいいですがDoctrine2を動かしている環境で)
composer.jsonへ何も考えずに以下の定義を追加してcomposer updateしましょう。


  "require": {
    "doctrine/orm": "2.5.*@dev",
    "doctrine/dbal": "v2.5.0-RC2",
  }

これで準備はできました。

実装方法

http://doctrine-orm.readthedocs.org/en/latest/tutorials/embeddables.html
をみればわかります。
が、暇なので実装例について。コメントも合わせて書いていきます。


/**
 * Class User
 * @package RSchedule\Bundle\RScheduleBundle\Entity\User
 *
 * @ORM\Table(name="user")
 * @ORM\Entity(repositoryClass="RSchedule\Bundle\RScheduleBundle\Entity\User\UserRepository")
 */
class User extends Entity
{
    /**
     * @param UserAuthority $userAuthority
     *
     * //これが重要、UserへUserAuthorityをEbeddedする
     * //DoctrineによってUserを実態化した際に、UserAuthorityが組み込まれる
     * @ORM\Embedded(class = "UserAuthority", columnPrefix = false))
     */
    private $userAuthority;

}

/**
 * Class UserAuthority
 * @package RSchedule\Bundle\RScheduleBundle\Entity\User
 *
 * //これが重要、何かのクラスへ組み込まれる事を宣言している
 * @ORM\Embeddable
 */
final class UserAuthority extends Enum
{
    /**
     * 管理者権限
     */
    const ADMIN = 0;
    /**
     * 管理者権限なし
     */
    const OTHER = 1;

    /**
   * //通常通りAnnotationでカラムの属性を定義可能
     * @ORM\Column(name="authority", columnDefinition="TINYINT(1) DEFAULT 1 NOT NULL", options={"comment" = "権限"})
     */
    private $authority;


    /**
     * @param $value
     */
    public function __construct($value)
    {
        $this->authority = parent::__construct($value);
    }

    /**
     * @return integer
     */
    public function valueOf()
    {
        return $this->authority;
    }

}

//これは色々やり方あるけどEnumっぽくしたかった(mysqlのじゃないよ)
abstract class Enum
{

    public function __construct($value)
    {
        $ref = new \ReflectionClass(get_class($this));
        $constants = $ref->getConstants();
        if (!in_array($value, $constants, true)) {
            throw new \InvalidArgumentException("does not definition:{$value}");
        }

        return $value;
    }

    abstract public function valueOf();

}

代替案

つかいたい、でもRC2は流石に、、、じゃあせめて正式サポート時にリファクタしやすいようにしよう、
そんな方法のご紹介です。



/**
 * Class User
 * @package RSchedule\Bundle\RScheduleBundle\Entity\User
 *
 * @ORM\Table(name="user")
 * @ORM\Entity(repositoryClass="RSchedule\Bundle\RScheduleBundle\Entity\User\UserRepository")
 */
class User extends Entity
{
    /**
     * @param UserAuthority $userAuthority
     *
     * @ORM\Column(name="authority", columnDefinition="TINYINT(1) DEFAULT 1 NOT NULL", options={"comment" = "権限"})
     */
    private $userAuthority;

    // こんな感じでクラスにインジェクションする
    public setUserAuthority(UserAuthority $userAuthority)
    {
          $this->userAuthority = $userAuthority->valueOf();
    }

    // 取り出すときもインスタンス化したクラスを返す
    public getUserAuthority()
    {
          return new UserAuthority($this->userAuthority);
    }

}

/**
 * Class UserAuthority
 * @package RSchedule\Bundle\RScheduleBundle\Entity\User
 *
 */
final class UserAuthority extends Enum
{
    /**
     * 管理者権限
     */
    const ADMIN = 0;
    /**
     * 管理者権限なし
     */
    const OTHER = 1;

    private $authority;

    /**
     * @param $value
     */
    public function __construct($value)
    {
        $this->authority = parent::__construct($value);
    }

    /**
     * @return integer
     */
    public function valueOf()
    {
        return $this->authority;
    }

}

abstract class Enum
{

    public function __construct($value)
    {
        $ref = new \ReflectionClass(get_class($this));
        $constants = $ref->getConstants();
        if (!in_array($value, $constants, true)) {
            throw new \InvalidArgumentException("does not definition:{$value}");
        }

        return $value;
    }

    abstract public function valueOf();

}

// 新規のインスタンス化はFactoryへ任せてこんな感じにすると実装がシンプルになるかも
class UserFactory
{

    public function newUser()
    {
         $user = new User();
         $user->setUserAuthority(new UserAuthority(UserAuthority::ADMIN));
         return $user;
    }

}


参考

http://doctrine-orm.readthedocs.org/en/latest/tutorials/embeddables.html

[http://welcometothebundle.com/persist-the-money-doctrine-value-object/]

[https://packagist.org/packages/doctrine/orm]


11
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?