web-dev-qa-db-ja.com

Doctrineのデフォルト値

Doctrine 2にデフォルト値を設定するにはどうすればいいですか?

310
Jiew Meng

データベースのデフォルト値は「移植可能」にはサポートされていません。データベースのデフォルト値を使用する唯一の方法は、フィールドがマップされる列にcolumnDefinitionスニペット(SQL causeを含む)を指定するDEFAULTマッピング属性を使用することです。

あなたが使用することができます:

<?php
/**
 * @Entity
 */
class myEntity {
    /**
     * @var string
     *
     * @Column(name="myColumn", type="string", length="50")
     */
    private $myColumn = 'myDefaultValue';
    ...
}

PHPレベルのデフォルト値は新しく作成され永続化されたオブジェクトでも適切に利用可能であるため推奨されます(デフォルト値を取得するために新しいオブジェクトを永続化した後Doctrineはデータベースに戻りません)。

362
romanb
<?php
/**
 * @Entity
 */
class myEntity {
    /**
     * @var string
     *
     * @ORM\Column(name="myColumn", type="integer", options={"default" : 0})
     */
    private $myColumn;
    ...
}

これはSQL DEFAULTを使用することに注意してください。これはBLOBTEXTのようないくつかのフィールドではサポートされていません。

482
iv3ndy

エンティティにコンストラクタを設定し、そこでデフォルト値を設定します。

61
Jeremy Hicks

つかいます:

options={"default":"foo bar"}

ではない:

options={"default"="foo bar"}

例えば:

/**
* @ORM\Column(name="foo", type="smallint", options={"default":0})
*/
private $foo
54

更新

がSymfonyのドキュメントを読むもう1つの理由は決してトレンドから外れないでしょう。私の特定のケースには簡単な解決策があり、field typeオプションempty_dataをデフォルト値に設定することです。

繰り返しますが、この解決策は、フォーム内の空の入力がDBフィールドをnullに設定するシナリオ専用です。

バックグラウンド

前の答えのどれも私の特定のシナリオで私を助けませんでした、しかし私は解決策を見つけました。

私は以下のように振る舞うために必要なフォームフィールドを持っていました:

  1. 必須ではありません。空白のままにすることもできます。 ( 'required' => falseを使いました)
  2. 空白のままにした場合は、デフォルトで指定の値になります。ユーザーエクスペリエンスを向上させるために、入力フィールドにデフォルト値を設定しませんでしたが、邪魔にならないように、HTML属性の 'placeholder'を使用しました。

それから私はここで与えられた全ての勧告を試しました。それらをリストしてみましょう:

  • エンティティプロパティにデフォルト値を設定します。
<?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クラスに設定されたデフォルト値をオーバーライドします。つまり、あなたのDBのスキーマにはデフォルト値を定義することができます。 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;
}
...

これは、きれいに見えても、機能しません。その理由は、邪魔なform->handleRequest()メソッドはモデルのセッターメソッドを使ってデータを更新していないからです(詳細はform->setData()を読んでください)。

49
Callistino

私が使用した回避策は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');
}
16
Jiew Meng

あなたは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>
12
Andrew Zhilin

これが私が自分で解決した方法です。以下はMySQLのデフォルト値を持つEntityの例です。ただし、これにはエンティティ内のコンストラクタを設定する必要があります。また、デフォルト値を設定する必要があります。

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'
7
Putna

Mysqlデータベースでも私のために働きます:

Entity\Entity_name:
    type: entity
    table: table_name
    fields: 
        field_name:
            type: integer
            nullable: true
            options:
                default: 1
7
Alex Hoang

これのどれも私のために働きませんでした。私はdoctrineのサイトでデフォルト値を設定するために直接値を設定するように言ういくつかのドキュメントを見つけました。

http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/reference/faq.html

private $default = 0;

これは私が欲しかった価値を挿入しました。

6
metric152

あなたのエンティティにyaml定義を使っているのであれば、postgresqlデータベースでは次のように動作します。

Entity\Entity_name:
    type: entity
    table: table_name
    fields: 
        field_name:
            type: boolean
            nullable: false
            options:
                default: false
3
wonzbak

@romanbのすばらしい答えに追加します。

これにより、マイグレーションに多少のオーバーヘッドが追加されます。明らかに、nullでない制約やデフォルト値のないフィールドを作成することはできないからです。

// 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");

この答えで、なぜデータベースにデフォルト値が必要なのでしょうか。そして通常それはnullではない制約でオブジェクトを作成することを許可することです。

2
Dziamid

コンストラクタで値を設定しても機能しますが、Doctrine Lifecycleイベントを使用することをお勧めします。

prePersistライフサイクルイベントを利用することによって、あなたはあなたのエンティティにあなたのデフォルト値を設定することができるのは初期の永続化の時だけです。

1
tiruncula

私は同じ問題に苦労しました。データベースからエンティティへのデフォルト値を(自動的に)持っていたかったのです。何だと思います、私はそれをしました:)

<?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";
1
Steffen Brem

プロパティ定義にデフォルト値を設定するときは注意してください。問題のないようにするために、代わりにコンストラクターで行ってください。プロパティ定義で定義した場合は、オブジェクトをデータベースに永続化してから部分ロードを実行すると、ロードされていないプロパティもデフォルト値になります。オブジェクトをもう一度永続化したい場合、それは危険です。

0
tomazahlin