Doctrine2:给予子类

时间:2017-04-01 13:20:07

标签: php symfony doctrine-orm

我已定义用户实体(以yml映射)

namespace My\CoreBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

class User
{

...

我创建了一个继承自该实体的子类,以便我可以添加一些自定义验证方法和一些我需要但不需要保留的字段(例如ConfirmPassword,ConfirmEmail字段)

namespace My\SecondBundle\EditModels;

use My\CoreBundle\Entity\User;

class UserModel extends User
{

当用户提交注册表单时,我将请求映射到UserModel实体,如果它是有效的,我会尝试保留用户。

以下代码抛出异常

$entityManager->persist($userModel);

//=>The class 'My\SecondBundle\EditModels\UserModel' was not found in the chain configured namespaces My\CoreBundle\Entity

问题:如何将$ userModel(UserModel的实例)作为User实体类持久化?可能的选择:

  • 不要使用继承的类,并将自定义字段和验证方法添加到用户实体本身
  • 将字段从UserModel复制到User实体并保留用户实体

我不认为我应该使用Doctrine继承机制,因为我不想保存额外的字段。

谢谢

1 个答案:

答案 0 :(得分:0)

我认为您的问题在于,您刚刚在Doctrine2中配置了My\CoreBundle\Entity命名空间,但您实际想要保留的实体位于My\SecondBundle\EditModels

通常在继承标记为@ORM\Entity()的类时,您要扩展的类必须具有类注释@ORM\MappedSuperclass()。但通常你会将它用于单表不一致,例如,不是用于你的用例。

在我看来,将数据库相关属性与其他属性分开的方法是不可承受的。我会在模型中保留与验证相关的内容 - 您需要在创建/更新操作中使用它。

我不熟悉XML配置,但在使用注释时,您需要将每个属性标记为与数据库映射(使用@ORM\Column())。因此,Doctrine将完全忽略所有其他属性和方法。

所以我在这里分享了我最近开发的AbstractModel,看看我是如何实现验证的(使用respect/validation):

<?php
namespace Vendor\Package\Model;

use Doctrine\ORM\Mapping as ORM;

/**
 * Abstract Model
 *
 * @ORM\MappedSuperclass()
 */
abstract class AbstractModel
{
    /**
     * @var \Respect\Validation\Validator
     */
    protected $validator;

    /**
     * AbstractModel constructor
     */
    public function __construct()
    {
        $this->validator = static::validation();
    }

    /**
     * Defines validation for this model
     *
     * @return \Respect\Validation\Validator
     */
    public static function validation() : \Respect\Validation\Validator
    {
        return \Respect\Validation\Validator::create();
    }

    /**
     * Executes validations, defined in validation method.
     *
     * @return bool
     */
    public function isValid() : bool
    {
        if (is_null($this->validator)) {
            $this->validator = new \Respect\Validation\Validator();
            $this->validation();
        }
        return $this->validator->validate($this);
    }
}

从AbstractModel扩展的模型需要实现静态验证方法,以定义类验证:

<?php
namespace Vendor\Package\Model;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity()
 * @ORM\Table(name="my_model")
 */
class MyModel extends AbstractModel
{
    /**
     * @var string
     * @ORM\Column(type="string")
     */
    private $name;

    /**
     * Defines validation for this model
     *
     * @return \Respect\Validation\Validator
     */
    public static function validation() : \Respect\Validation\Validator
    {
        return \Respect\Validation\Validator::create()
            ->attribute('name', \Respect\Validation\Validator::notEmpty()->stringType()->length(null, 32))
            ;
    }
    // getter, setter, ...
}

每个实体,持久化到数据库,将具有$validator属性和所有这些方法,但因为我在这里留下了注释(并且非常确定这也适用于xml / yaml),Doctrine忽略它。

通过这种方式,您还可以将验证相关的东西保留在模型类本身之外,这有利于提高可读性。验证本身应该在模型本身中定义,imho。但是这个尊重/验证框架是实现这一目标的巧妙方法。希望这会有所帮助:)