Doctrine : joinColumn 字段的默认值

sde*_*ont 4 php entity symfony doctrine-orm

symfony2 和 Doctrine 的新手。

如何为字段foo_id(它是Foo表上的引用)设置默认值以指向ID 1Foo 表(在所有情况下都存在)的 ?

Me\NavigationBundle\Entity\PublicText:
    type: entity
    table: public_text
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO
    fields:
        title:
            type: string
            length: '255'
            nullable: false
        content:
            type: string
            length: '2000'
            nullable: false            
    manyToOne:
        foo:
            #How to set a default value???
            targetEntity: \Me\NavigationBundle\Entity\Foo
            joinColumn:
                name: foo_id
                referencedColumnName: id   
                nullable: false 
    lifecycleCallbacks: {  }
Run Code Online (Sandbox Code Playgroud)

我尝试了很多事情都没有成功:

  • 在 Foo 的构造函数中将默认值设置为 ID 1
  • 执行请求以检索 Me 实体中 ID 为 1 的 Foo 对象(可以工作,但不好的做法)

Den*_*nis 6

查找columnDefinition学说列注释Reference¶

优点: 您可以设置自己的列定义

缺点: doctrine orm:schema-tool被 Doctrine 使用(如果你使用它),会感到困惑,并且总是报告具有自定义columnDefinition更改的列。因为它总是会告诉您为您的列定义运行更改命令,如此处所述

如果您使用“columnDefinition”,SchemaTool 将不再正确检测列上的更改。

例子

/**
 * @ManyToOne(targetEntity="YourType")
 * @JoinColumn(
 *     name="your_type_id",
 *     referencedColumnName="id",
 *     nullable=false,
 *     columnDefinition="INT NOT NULL DEFAULT 1"
 * )
 */
private $yourType;
Run Code Online (Sandbox Code Playgroud)


fyr*_*rye 2

请注意,columnDefinition单独使用可以生成迁移,但会破坏 ORM 上下文并可能导致 FK 完整性问题。您仍然需要将对象关联添加到 ORM 以持久保存实体。查看来自奥克拉米乌斯的警告

例子:

(new PublicText())
    ->getFoo(); //null - expected object(Foo)#1 (1) { ["id"] => int(1) }
Run Code Online (Sandbox Code Playgroud)

我在教义 2 中看到了许多实现这一目标的方法。

构造函数

一般来说,最快的方法和大多数用户所做的就是需要在构造函数中进行关联。

public function __construct(Foo $foo)
{
   $this->foo = $foo;
}
Run Code Online (Sandbox Code Playgroud)

然后您可以getReference在控制器中检索它,而无需查询数据库。请参阅http://doctrine-orm.readthedocs.org/en/latest/reference/advanced-configuration.html#reference-proxies

$foo = $em->getReference('app:Foo', 1);
$text = new \Path\To\Entity\PublicText($foo);
$em->persist($text);
$em->flush();
Run Code Online (Sandbox Code Playgroud)

生命周期事件

我的首选方法设置大多数ManyToOne关系的默认值的另一种方法是利用LifeCycleEvents http://doctrine-orm.readthedocs.org/en/latest/reference/events.html

尽管它确实有一些需要注意的警告。因此,在实施到生产环境之前,请务必进行 RTM。在这种情况下,它应该可以正常工作,但我不知道你的整个映射结构。

 use Doctrine\ORM\Event\LifecycleEventArgs;

/**
 * @Entity
 * @HasLifeCycleEvents
 */
class PublicText
{
    // ...

    /**
     * @PrePersist
     * @param \Doctrine\ORM\Event\LifecycleEventArgs $event
     */
    public function onPrePersist(LifecycleEventArgs $event)
    {
        if (false === empty($this->foo)) {
           return;
        }
        $this->foo = $event->getEntityManager()->getReference('app:Foo', 1);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的控制器中。

$text = new \Path\To\Entity\PublicText;
$em->persist($text); //retrieve and set foo if not set in the Entity Event.
$em->flush();
Run Code Online (Sandbox Code Playgroud)

存储库方法

实体中的另一个选项是使用存储库设置属性的值。

在实体中定义存储库类

/**
 * @Entity(repositoryClass="PublicTextRepo")
 */
class PublicText
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

存储库

use Doctrine\ORM\EntityRepository;

class PublicTextRepo extends EntityRepository
{
   public function create()
   {
       $text = new \Path\To\Entity\PublicText;
       $foo = $this->_em->getReference('app:Foo', 1);
       $text->setFoo($foo );
       return $text;
   }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的控制器中你可以这样做

$text = $em->getRepository('app:PublicText')->create();
$em->persist($text);
$em->flush();
Run Code Online (Sandbox Code Playgroud)

鉴别器图

尽管根据用例并不总是可行。我定义实体默认值的方法之一是创建DiscriminatorMap具有单表继承的实体。http://doctrine-orm.readthedocs.org/en/latest/reference/inheritance-mapping.html#single-table-inheritance

这样,当创建对象时,会在数据库中自动设置默认值,并将对象锁定为该类型。问题在于,结果值不是像上面其他方法中那样的对象。

要获取对象的鉴别器static值,您可以在定义的对象中使用常量。

/**
 * @Entity
 * @InheritanceType("SINGLE_TABLE")
 * @Table(name="user")
 * @DiscriminatorColumn(name="type", type="string")
 * @DiscriminatorMap({Person::TYPE="Person", Employee::TYPE="Employee"})
 */
class Person
{
    const TYPE = 'person';     

    /**
     * @return string [person|employee]
     */   
    public function getType()
    {
        return $this::TYPE;
    }
    // ...
}

/**
 * @Entity
 */
class Employee extends Person
{
    const TYPE = 'employee';
    // ...
}
Run Code Online (Sandbox Code Playgroud)

然后你需要在控制器中做的就是。

$employee = new \Path\To\Entity\Employee;
$em->persist($employee); //inserts with `user.type` as `employee`
$em->flush();

echo $employee->getType(); //employee
Run Code Online (Sandbox Code Playgroud)