Doctrineのデフォルト値


338

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


26
@ORM \ Column(name = "foo"、type = "decimal"、precision = 7、scale = 2、options = {"default" = 0})は機能します(以下の人気のない回答から)
WayFarer

2
@ORM \ Column(name = "is_activated"、type = "boolean"、options = {"default":0})または@ORM \ Column(name = "is_activated"、type = "boolean"、options = {"default "= 0})
ahmed hamdy 2013年

AhmedこれはSymfony 2.3のブール値では機能しないようです。ただし、options = {"default" = "0"})は機能し、整数を引用符で囲みます。
アサイラ2014年

4
ブール値の場合は、なぜoptions = {"default":false}を使用しないのですか?
ロボコーダー、

回答:


385

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

以下を使用できます。

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

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


11
しかし、ここに問題があります。「日時」タイプを設定するとどうなりますか?
artragis 2012

46
@artragisは、インスタンス化をエンティティコンストラクターに入れます
Alain Tiemblo 2012

16
既存の行があると移行が失敗するため、このアプローチを使用した移行には注意が必要です。
タムリン2013年

7
変数を設定するためにインスタンス化領域を使用しないでください...私を信じてください、悪いことが起こります。代わりにコンストラクター領域を使用してください。
ミモレラ2014

4
アノテーションでcolumnDefinitionを使用することをお勧めします。そうしないと、誰かがmysqlクライアントまたはphpmyadminを使用し、値が間違ってしまいます...
NDM

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

これはSQLを使用することに注意してください。SQL DEFAULTBLOBおよびなどの一部のフィールドではサポートされていませんTEXT


4
良いキャッチ!options = {"default" = 0}オプションが公式ドキュメントにないようです
WayFarer

2
options参考までに、パラメータはunsigned値にも役立ちます。この回答を
yvoyer

5
私はこれと受け入れられた答えの両方を使用して、すべてのベースをカバーします。また、あなたも行うことができますちょうどノート:options={"default": 0}それは教義の私のバージョンでエラーが発生すると、「使用するように注意してください」とありません。
スコット・フラック

28
これが選択された答えになるはずです!
Acelasi Eu、2014

2
@マット彼はおそらくそれが文書化されていない機能だったので、アンカムメントされた機能は削除される傾向があると言った。現在ドキュメント化されているので、安全に使用できます。
JCM 2015年

62

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


これは確かに論理的なアプローチのようです。コンストラクタでデフォルトを設定するときに問題が発生しましたか?
cantera

26
Doctrineの推奨ソリューション:doctrine-project.org/docs/orm/2.1/en/reference/faq.html
cantera

答えになるはずの@ cantera25 +1
Phill Pafford

3
デフォルト値が必要な新しいフィールドを追加しても、既存のエンティティは更新されません。ですから、それが答えであってはなりません。正確にあなたが何をする必要があるかに依存します
トマーシュTibenský

更新目的でも機能しません。(整数の場合でも)フィールドを空にするだけでデフォルト値に戻したい場合は、残念ながら機能しません。
ThEBiShOp 2016


51

更新

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

繰り返しになりますが、このソリューションは、フォーム内の空の入力がDBフィールドをnullに設定するシナリオにのみ対応しています。

バックグラウンド

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

私は次のように動作する必要があるフォームフィールドを持っていました:

  1. 必須ではなく、空白のままにすることができます。(「必須」を使用=> 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クラスをどのように使用するかにより、どれも機能しませんでした。

重要

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()詳細については、詳しく調べてください)。


この答えは確かに一番上に行くはずです。フォームコンポーネントは、PropertyAccessorを使用して、プロパティの値を取得および設定します。たぶん、プロパティアクセサーは、メソッドが使用可能なときにそれらを使用する必要がありますか?
Xobb 2014

1
ブール列はphpのデフォルトをサポートしていないため、注釈のみ
Crusader

これは、フォームから情報を取得するときに機能した唯一のソリューションです。また、ブールに関する上記のコメントには同意しません。それらはデフォルトの注釈を受け入れません。
BernardA 2017年

symfonyのフォームコンポーネントモデルセッターを使用しますが、フォームのモデルフォーマットデータがモデルオブジェクトインスタンスの対応するゲッターによって返されたデータと異なる場合のみです。カスタムセッター/ゲッターメソッドがある場合-「property_path」フォームオプション(PropertyAccessorによって処理されます)またはカスタムDataMapper(フォームとモデルオブジェクト間のデータ転送ルーチンを手動で定義できます)を使用します。
アーケムラー

1
この質問はsymfonyではなく教義に関するものなので、この回答はあまり話題になりません。
OMN

18

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

1
今後の読者は、ライフサイクルコールバックに頼らないでください:) Marco Pivettaも反対します。
emix

警告!エンティティがすでにdtPostedプロパティを設定している場合、コードは単にプロパティを上書きします。アクセサーが存在する場合は常に使用してください!if (!$this->getDtPosted()) { $this->setDtPosted(new \DateTime()); }
Barh

13

あなたも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>

8

これが私が自分で解決した方法です。以下は、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'

私の設定のこの行で、Doctrineは実行するたびにデフォルトを列にドロップしようとします。php app / console doctrine:schema:update
shapeshifter

1
これがここで最悪の答えです。columnDefinitionデータベースからの抽象化であるORMを使用する目的に直接向かいます。このソリューションは移植性を壊し、ソフトウェアをDBベンダーに依存させ続け、Doctrine Migrationsツールも壊します。
Pedro Cordeiro、2014

@PedroCordeiro私はあなたに完全に同意します。これは、別の問題が発生するまでの迅速な解決策です。
Putna 2014

7

mysqlデータベースでも動作します:

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

関心のある人のための注釈形式:@ORM \ Column(name = "Entity_name"、type = "integer"、options = {"default" = "1"})
Hannes

7

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

https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/faq.html#how-can-i-add-default-values-to-a-column

private $default = 0;

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


リンクをdoctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/に変更してください…ポイント3.2.2を参照してください。列にデフォルト値を追加するにはどうすればよいですか?
トビは2016年


3

@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でない制約を持つオブジェクトを作成できるようにするためです。


3

エンティティにyaml定義を使用する場合、私はpostgresqlデータベースで次のように機能します。

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

1
$entity->setFieldName()フラッシュする前に使用しなかった場合はどうなりますか?Doctrineはデフォルト値をnullに定義しているようです。YAMLでの唯一の解決策は、デフォルト値を定義することであるIN -_- ...それはすでにYAMLで定義されていますので、私にはダムと思われるエンティティクラス
j0k

1

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

<?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";

3
数年前からこれに戻ると、私はこのアプローチを使用しないことをお勧めします。これは本当にハックハックです。
Steffen Brem 2016

自分の答えはお勧めしないので、削除することもできます;)
Dragos

1

コンストラクタで値を設定することは機能しますが、Doctrine Lifecycleイベントを使用する方が良い解決策になるかもしれません。

prePersistライフサイクルイベントを活用することで、初期永続化時にのみエンティティにデフォルト値を設定できます。


ライフサイクルイベントの使用はと見なされますhack。ハッキングに依存しないでください。
2016

0

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.