如何在 Doctrine 2 中设置默认值?
15 回答
<?php
/**
 * @Entity
 */
class myEntity {
    /**
     * @var string
     *
     * @ORM\Column(name="myColumn", type="integer", options={"default" : 0})
     */
    private $myColumn;
    ...
}
请注意,这使用 SQL ,某些字段(如和DEFAULT)不支持该 SQL 。BLOBTEXT
数据库默认值不受“可移植”支持。使用数据库默认值的唯一方法是通过columnDefinition映射属性,您可以在其中为字段映射到的列指定SQL片段(包括原因)。DEFAULT
您可以使用:
<?php
/**
 * @Entity
 */
class myEntity {
    /**
     * @var string
     *
     * @Column(name="myColumn", type="string", length="50")
     */
    private $myColumn = 'myDefaultValue';
    ...
}
PHP 级别的默认值是首选,因为这些默认值也适用于新创建和持久化的对象(在持久化新对象以获取默认值后,Doctrine 不会返回数据库)。
在您的实体中设置一个构造函数并在那里设置默认值。
采用:
options={"default":"foo bar"}
并不是:
options={"default"="foo bar"}
例如:
/**
* @ORM\Column(name="foo", type="smallint", options={"default":0})
*/
private $foo
    更新
阅读 Symfony 文档的另一个原因永远不会过时。对于我的具体情况,有一个简单的解决方案,就是将field type选项设置empty_data为默认值。
同样,此解决方案仅适用于表单中的空输入将 DB 字段设置为 null 的情况。
背景
以前的答案都没有帮助我解决我的具体情况,但我找到了解决方案。
我有一个表单字段,其行为如下:
- 不需要,可以留空。(使用“必需”=> false)
 - 如果留空,则应默认为给定值。为了更好的用户体验,我没有在输入字段上设置默认值,而是使用了 html 属性“占位符”,因为它不那么突兀。
 
然后我尝试了这里给出的所有建议。让我列出它们:
- 为实体属性设置默认值时:
 
<?php
/**
 * @Entity
 */
class myEntity {
    /**
     * @var string
     *
     * @Column(name="myColumn", type="string", length="50")
     */
    private $myColumn = 'myDefaultValue';
    ...
}
- 使用选项注释:
 
@ORM\Column(name="foo", options={"default":"foo bar"})
- 在构造函数上设置默认值:
 
/**
 * @Entity
 */
class myEntity {
    ...
    public function __construct()
    {
        $this->myColumn = 'myDefaultValue';
    }
    ...
}
这些都不起作用,这完全是因为 Symfony 如何使用您的 Entity 类。
重要的
Symfony 表单字段覆盖在 Entity 类上设置的默认值。 
这意味着,您的数据库架构可以定义一个默认值,但如果您在提交表单时将非必填字段留空,则form->handleRequest()您的方法内部form->isValid()将覆盖您的Entity类上的这些默认值并将它们设置为输入字段值。如果输入字段值为空白,则它将Entity属性设置为null。
http://symfony.com/doc/current/book/forms.html#handling-form-submissions
我的解决方法
form->handleRequest()在你的方法之后在你的控制器上设置默认值form->isValid():
...
if ($myEntity->getMyColumn() === null) {
    $myEntity->setMyColumn('myDefaultValue');
}
...
不是一个漂亮的解决方案,但它有效。我可能会做一个validation group,但可能有人认为这个问题是数据转换而不是数据验证,我让你来决定。
覆盖设置器(不起作用)
我也尝试以Entity这种方式覆盖设置器:
...
/**
 * Set myColumn
 *
 * @param string $myColumn
 *
 * @return myEntity
 */
public function setMyColumn($myColumn)
{
    $this->myColumn = ($myColumn === null || $myColumn === '') ? 'myDefaultValue' : $myColumn;
    return $this;
}
...
这,即使它看起来更干净,它也不起作用。原因是 evilform->handleRequest()方法不使用模型的 setter 方法来更新数据(深入form->setData()了解更多细节)。
我使用的解决方法是LifeCycleCallback. 还在等着看是否有更多的“原生”方法,例如@Column(type="string", default="hello default value").
/**
 * @Entity @Table(name="posts") @HasLifeCycleCallbacks
 */
class Post implements Node, \Zend_Acl_Resource_Interface {
...
/**
 * @PrePersist
 */
function onPrePersist() {
    // set default date
    $this->dtPosted = date('Y-m-d H:m:s');
}
    您也可以使用 xml 来执行此操作:
<field name="acmeOne" type="string" column="acmeOne" length="36">
    <options>
        <option name="comment">Your SQL field comment goes here.</option>
        <option name="default">Default Value</option>
    </options>
</field>
    这是我自己解决的方法。下面是一个带有 MySQL 默认值的实体示例。但是,这也需要在您的实体中设置构造函数,并在此处设置默认值。
Entity\Example:
  type: entity
  table: example
  fields:
    id:
      type: integer
      id: true
      generator:
        strategy: AUTO
    label:
      type: string
      columnDefinition: varchar(255) NOT NULL DEFAULT 'default_value' COMMENT 'This is column comment'
    这些都不适合我。我在教义网站上找到了一些文档,说直接设置值以设置默认值。
private $default = 0;
这插入了我想要的值。
在 mysql 数据库上也适用于我:
Entity\Entity_name:
    type: entity
    table: table_name
    fields: 
        field_name:
            type: integer
            nullable: true
            options:
                default: 1
    添加到@romanb 精彩的答案。
这会在迁移中增加一点开销,因为您显然无法创建一个具有非空约束且没有默认值的字段。
// this up() migration is autogenerated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != "postgresql");
//lets add property without not null contraint        
$this->addSql("ALTER TABLE tablename ADD property BOOLEAN");
//get the default value for property       
$object = new Object();
$defaultValue = $menuItem->getProperty() ? "true":"false";
$this->addSql("UPDATE tablename SET property = {$defaultValue}");
//not you can add constraint
$this->addSql("ALTER TABLE tablename ALTER property SET NOT NULL");
有了这个答案,我鼓励您思考为什么首先需要数据库中的默认值?通常是允许创建具有非空约束的对象。
如果您为实体使用 yaml 定义,则以下内容适用于我的 postgresql 数据库:
Entity\Entity_name:
    type: entity
    table: table_name
    fields: 
        field_name:
            type: boolean
            nullable: false
            options:
                default: false
    虽然在构造函数中设置值会起作用,但使用 Doctrine Lifecycle 事件可能是更好的解决方案。
通过利用prePersist生命周期事件,您可以仅在初始持久化时为您的实体设置默认值。
我在同样的问题上苦苦挣扎。我想将数据库中的默认值(自动)放入实体中。你猜怎么着,我做到了:)
<?php
/**
 * Created by JetBrains PhpStorm.
 * User: Steffen
 * Date: 27-6-13
 * Time: 15:36
 * To change this template use File | Settings | File Templates.
 */
require_once 'bootstrap.php';
$em->getConfiguration()->setMetadataDriverImpl(
    new \Doctrine\ORM\Mapping\Driver\DatabaseDriver(
        $em->getConnection()->getSchemaManager()
    )
);
$driver = new \Doctrine\ORM\Mapping\Driver\DatabaseDriver($em->getConnection()->getSchemaManager());
$driver->setNamespace('Models\\');
$em->getConfiguration()->setMetadataDriverImpl($driver);
$cmf = new \Doctrine\ORM\Tools\DisconnectedClassMetadataFactory();
$cmf->setEntityManager($em);
$metadata = $cmf->getAllMetadata();
// Little hack to have default values for your entities...
foreach ($metadata as $k => $t)
{
    foreach ($t->getFieldNames() as $fieldName)
    {
        $correctFieldName = \Doctrine\Common\Util\Inflector::tableize($fieldName);
        $columns = $tan = $em->getConnection()->getSchemaManager()->listTableColumns($t->getTableName());
        foreach ($columns as $column)
        {
            if ($column->getName() == $correctFieldName)
            {
                // We skip DateTime, because this needs to be a DateTime object.
                if ($column->getType() != 'DateTime')
                {
                    $metadata[$k]->fieldMappings[$fieldName]['default'] = $column->getDefault();
                }
                break;
            }
        }
    }
}
// GENERATE PHP ENTITIES!
$entityGenerator = new \Doctrine\ORM\Tools\EntityGenerator();
$entityGenerator->setGenerateAnnotations(true);
$entityGenerator->setGenerateStubMethods(true);
$entityGenerator->setRegenerateEntityIfExists(true);
$entityGenerator->setUpdateEntityIfExists(false);
$entityGenerator->generate($metadata, __DIR__);
echo "Entities created";
    在属性定义上设置默认值时要小心!而是在构造函数中执行它,以保持它没有问题。如果你在属性定义上定义它,然后将对象持久化到数据库中,然后进行部分加载,那么未加载的属性将再次具有默认值。如果您想再次持久化该对象,那将是危险的。