Doctrine 2でデフォルト値を設定するにはどうしたらいいですか?
Doctrine 2でデフォルト値を設定するにはどうしたらいいですか?
回答:
データベースのデフォルト値は「移植可能」にサポートされていません。データベースのデフォルト値を使用する唯一の方法は、フィールドがマップされる列のスニペット(両端を含む)をcolumnDefinition
指定するマッピング属性を使用することです。SQL
DEFAULT
以下を使用できます。
<?php
/**
* @Entity
*/
class myEntity {
/**
* @var string
*
* @Column(name="myColumn", type="string", length="50")
*/
private $myColumn = 'myDefaultValue';
...
}
PHPレベルのデフォルト値は、新しく作成され永続化されたオブジェクトでも適切に利用できるため、推奨されます(Doctrineは、デフォルト値を取得するために新しいオブジェクトを永続化した後、データベースに戻りません)。
<?php
/**
* @Entity
*/
class myEntity {
/**
* @var string
*
* @ORM\Column(name="myColumn", type="integer", options={"default" : 0})
*/
private $myColumn;
...
}
これはSQLを使用することに注意してください。SQL DEFAULT
はBLOB
およびなどの一部のフィールドではサポートされていませんTEXT
。
options={"default": 0}
それは教義の私のバージョンでエラーが発生すると、「使用するように注意してください」とありません。
エンティティにコンストラクタを設定し、そこにデフォルト値を設定します。
使用する:
options={"default":"foo bar"}
ではなく:
options={"default"="foo bar"}
例えば:
/**
* @ORM\Column(name="foo", type="smallint", options={"default":0})
*/
private $foo
Symfony のドキュメントを読むもう1つの理由は、トレンドから外れないことです。私の特定のケースに対する簡単な解決策があり、field type
オプションempty_data
をデフォルト値に設定することです。
繰り返しになりますが、このソリューションは、フォーム内の空の入力がDBフィールドをnullに設定するシナリオにのみ対応しています。
以前の回答のどれも私の特定のシナリオで私を助けませんでしたが、解決策を見つけました。
私は次のように動作する必要があるフォームフィールドを持っていました:
次に、ここに記載されているすべての推奨事項を試しました。それらをリストしましょう:
<?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()
詳細については、詳しく調べてください)。
私が使用した回避策はでした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');
}
if (!$this->getDtPosted()) { $this->setDtPosted(new \DateTime()); }
あなたも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'
columnDefinition
データベースからの抽象化であるORMを使用する目的に直接向かいます。このソリューションは移植性を壊し、ソフトウェアをDBベンダーに依存させ続け、Doctrine Migrationsツールも壊します。
これはどれも私にとってはうまくいきませんでした。doctrineのサイトで、値を直接設定してデフォルト値を設定するように指示しているドキュメントを見つけました。
private $default = 0;
これは私が欲しかった値を挿入しました。
@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でない制約を持つオブジェクトを作成できるようにするためです。
エンティティにyaml定義を使用する場合、私はpostgresqlデータベースで次のように機能します。
Entity\Entity_name:
type: entity
table: table_name
fields:
field_name:
type: boolean
nullable: false
options:
default: false
$entity->setFieldName()
フラッシュする前に使用しなかった場合はどうなりますか?Doctrineはデフォルト値をnullに定義しているようです。YAMLでの唯一の解決策は、デフォルト値を定義することであるIN -_- ...それはすでにYAMLで定義されていますので、私にはダムと思われるエンティティクラス
私は同じ問題で苦労しました。データベースからエンティティに(自動的に)デフォルト値を設定したかったのです。何だと思う、私はそれをやった:)
<?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";