Bagaimana cara menetapkan nilai default di Ajaran 2?
Bagaimana cara menetapkan nilai default di Ajaran 2?
Jawaban:
Nilai default basis data tidak didukung "portable". Satu-satunya cara untuk menggunakan nilai default basis data adalah melalui columnDefinition
atribut pemetaan tempat Anda menentukan SQL
snippet ( DEFAULT
penyebab inklusif) untuk kolom yang bidangnya dipetakan.
Kamu bisa memakai:
<?php
/**
* @Entity
*/
class myEntity {
/**
* @var string
*
* @Column(name="myColumn", type="string", length="50")
*/
private $myColumn = 'myDefaultValue';
...
}
Nilai default tingkat PHP lebih disukai karena ini juga tersedia dengan benar pada objek yang baru dibuat dan bertahan (Doctrine tidak akan kembali ke database setelah mempertahankan objek baru untuk mendapatkan nilai default).
<?php
/**
* @Entity
*/
class myEntity {
/**
* @var string
*
* @ORM\Column(name="myColumn", type="integer", options={"default" : 0})
*/
private $myColumn;
...
}
Perhatikan bahwa ini menggunakan SQL DEFAULT
, yang tidak didukung untuk beberapa bidang seperti BLOB
dan TEXT
.
options={"default": 0}
Berhati-hatilah untuk menggunakan "dan tidak ', karena hal itu menyebabkan kesalahan dalam versi doktrin saya.
Siapkan konstruktor di entitas Anda dan atur nilai default di sana.
Menggunakan:
options={"default":"foo bar"}
dan tidak:
options={"default"="foo bar"}
Misalnya:
/**
* @ORM\Column(name="foo", type="smallint", options={"default":0})
*/
private $foo
Satu lagi alasan mengapa membaca dokumentasi untuk Symfony tidak akan pernah ketinggalan zaman . Ada solusi sederhana untuk kasus spesifik saya dan mengatur field type
opsi empty_data
ke nilai default.
Sekali lagi, solusi ini hanya untuk skenario di mana input kosong dalam formulir menetapkan bidang DB ke nol.
Tidak ada jawaban sebelumnya yang membantu saya dengan skenario spesifik saya tetapi saya menemukan solusinya.
Saya memiliki bidang formulir yang harus berperilaku sebagai berikut:
Saya kemudian mencoba semua rekomendasi yang diberikan di sini. Biarkan saya daftar mereka:
<?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';
}
...
}
Tidak ada yang berfungsi dan semua karena cara Symfony menggunakan kelas Entity Anda.
Bidang formulir Symfony mengesampingkan nilai default yang ditetapkan pada kelas Entity.
Artinya, skema Anda untuk DB Anda dapat memiliki nilai default yang ditentukan tetapi jika Anda membiarkan bidang yang tidak diperlukan kosong saat mengirimkan formulir Anda, bagian form->handleRequest()
dalam form->isValid()
metode Anda akan menimpa nilai-nilai default di Entity
kelas Anda dan mengaturnya ke nilai-nilai bidang input. Jika nilai kolom input kosong, maka Entity
properti akan disetel ke null
.
http://symfony.com/doc/current/book/forms.html#handling-form-submissions
Tetapkan nilai default pada controller Anda setelah form->handleRequest()
di dalam form->isValid()
metode Anda :
...
if ($myEntity->getMyColumn() === null) {
$myEntity->setMyColumn('myDefaultValue');
}
...
Bukan solusi yang indah tetapi berhasil. Saya mungkin bisa membuat validation group
tetapi mungkin ada orang yang melihat masalah ini sebagai transformasi data daripada validasi data , saya serahkan kepada Anda untuk memutuskan.
Saya juga mencoba menimpa Entity
setter dengan cara ini:
...
/**
* Set myColumn
*
* @param string $myColumn
*
* @return myEntity
*/
public function setMyColumn($myColumn)
{
$this->myColumn = ($myColumn === null || $myColumn === '') ? 'myDefaultValue' : $myColumn;
return $this;
}
...
Ini, meskipun terlihat lebih bersih, itu tidak berhasil . Alasannya adalah bahwa form->handleRequest()
metode jahat tidak menggunakan metode setter Model untuk memperbarui data (gali form->setData()
lebih detail).
Solusi yang saya gunakan adalah a LifeCycleCallback
. Masih menunggu untuk melihat apakah ada metode "asli" lagi, misalnya @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()); }
Anda dapat melakukannya menggunakan xml juga:
<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>
Inilah cara saya menyelesaikannya untuk diri saya sendiri. Di bawah ini adalah contoh Entitas dengan nilai default untuk MySQL. Namun, ini juga memerlukan pengaturan konstruktor di entitas Anda, dan bagi Anda untuk menetapkan nilai default di sana.
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
berjalan langsung ke tujuan memiliki ORM, yang merupakan abstraksi dari database. Solusi ini akan merusak portabilitas, akan membuat perangkat lunak Anda bergantung pada vendor DB Anda dan juga akan merusak alat-alat Migrasi Doctrine.
Bekerja untuk saya di database mysql juga:
Entity\Entity_name:
type: entity
table: table_name
fields:
field_name:
type: integer
nullable: true
options:
default: 1
Tak satu pun dari ini bekerja untuk saya. Saya menemukan beberapa dokumentasi di situs doktrin yang mengatakan untuk mengatur nilai secara langsung untuk menetapkan nilai default.
private $default = 0;
Ini memasukkan nilai yang saya inginkan.
Menambahkan ke @romanb jawaban yang brilian.
Ini menambahkan sedikit overhead dalam migrasi, karena Anda jelas tidak dapat membuat bidang tanpa batasan nol dan tanpa nilai default.
// 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");
Dengan jawaban ini, saya mendorong Anda untuk berpikir mengapa Anda memerlukan nilai default di database? Dan biasanya itu memungkinkan pembuatan objek tanpa kendala nol.
Jika Anda menggunakan definisi yaml untuk entitas Anda, berikut ini berfungsi untuk saya pada database postgresql:
Entity\Entity_name:
type: entity
table: table_name
fields:
field_name:
type: boolean
nullable: false
options:
default: false
$entity->setFieldName()
sebelum memerah? Doktrin tampaknya mendefinisikan nilai default pada nol. Satu-satunya solusi di yaml adalah mendefinisikan nilai default DI kelas entitas yang tampaknya bodoh bagi saya karena sudah didefinisikan dalam yaml ... -_-
Saya berjuang dengan masalah yang sama. Saya ingin memiliki nilai default dari database ke entitas (secara otomatis). Coba tebak, saya berhasil :)
<?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";
Sementara menetapkan nilai dalam konstruktor akan berhasil, menggunakan peristiwa Siklus Hidup Ajaran mungkin merupakan solusi yang lebih baik.
Dengan memanfaatkan prePersist
Peristiwa Siklus Hidup, Anda dapat menetapkan nilai default pada entitas Anda hanya pada bertahan awal.
hack
. Jangan pernah mengandalkan peretasan.
Hati-hati saat menetapkan nilai default pada definisi properti! Sebaliknya, lakukan di konstruktor, agar bebas masalah. Jika Anda mendefinisikannya pada definisi properti, maka tetap objek ke database, kemudian buat sebagian beban, maka properti tidak dimuat lagi akan memiliki nilai default. Itu berbahaya jika Anda ingin tetap objek lagi.