原则:连接列字段的默认值


Doctrine : Default value on joinColumn field

symfony2和Doctrine的新功能。

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

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: {  }

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

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

columnDefinition 教义列注释参考¶

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

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

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

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

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

例:

(new PublicText())
    ->getFoo(); //null - expected object(Foo)#1 (1) { ["id"] => int(1) }
<小时 />

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

构造函数

通常,最快的方法和大多数用户所做的是要求在构造函数中进行关联。

public function __construct(Foo $foo)
{
   $this->foo = $foo;
}

然后,您可以使用 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();
<小时 />

生命周期事件

我的首选方法 设置大多数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);
    }
}

然后在控制器中。

$text = new 'Path'To'Entity'PublicText;
$em->persist($text); //retrieve and set foo if not set in the Entity Event.
$em->flush();
<小时 />

存储库方法

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

在实体中定义存储库类

/**
 * @Entity(repositoryClass="PublicTextRepo")
 */
class PublicText
{
    // ...
}

存储 库

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;
   }
}

然后在您的控制器中,您可以执行

$text = $em->getRepository('app:PublicText')->create();
$em->persist($text);
$em->flush();
<小时 />

鉴别器映射

尽管根据用例并不总是可行的。定义实体默认值的方法之一是创建具有单个表继承的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';
    // ...
}

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

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

使用注释,您可以在@ORM''列上使用:options={"default" = YourValue},因此在yaml中我认为您可以添加

options:
    default: yourValue

不确定,我给你一个主意...