ฉันจะตั้งค่าเริ่มต้นใน 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 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 จะไม่ตกเทรนด์ มีวิธีแก้ไขปัญหาง่าย ๆ สำหรับกรณีเฉพาะของฉันและตั้งค่าfield type
ตัวเลือกempty_data
เป็นค่าเริ่มต้น
อีกครั้งโซลูชันนี้ใช้สำหรับสถานการณ์ที่อินพุตว่างในฟอร์มตั้งค่าฟิลด์ DB เป็นโมฆะเท่านั้น
ไม่มีคำตอบก่อนหน้านี้ที่ช่วยฉันในสถานการณ์เฉพาะ แต่ฉันพบวิธีแก้ปัญหา
ฉันมีเขตข้อมูลฟอร์มที่จำเป็นต้องทำงานดังต่อไปนี้:
ฉันลองทำตามคำแนะนำทั้งหมดที่ให้ไว้ที่นี่ ให้ฉันเขียนรายการพวกเขา:
<?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 Migration
ทำงานให้ฉันในฐานข้อมูล mysql ด้วย:
Entity\Entity_name:
type: entity
table: table_name
fields:
field_name:
type: integer
nullable: true
options:
default: 1
สิ่งนี้ไม่ได้ผลสำหรับฉัน ฉันพบเอกสารบางอย่างในเว็บไซต์ของหลักคำสอนที่ระบุว่าจะตั้งค่าโดยตรงเพื่อตั้งค่าเริ่มต้น
private $default = 0;
สิ่งนี้แทรกค่าที่ฉันต้องการ
กำลังเพิ่มไปยัง @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
$entity->setFieldName()
ก่อนที่จะล้างข้อมูล หลักคำสอนดูเหมือนว่าจะกำหนดค่าเริ่มต้นที่ null วิธีการแก้ปัญหาเฉพาะใน yaml คือการกำหนดค่าเริ่มต้นในระดับนิติบุคคลซึ่งดูเหมือนว่าใบ้ให้ฉันตั้งแต่มันกำหนดไว้แล้วใน 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";
ในขณะที่การตั้งค่าในตัวสร้างจะใช้งานได้การใช้เหตุการณ์ Doctrine Lifecycle อาจเป็นทางออกที่ดีกว่า
ด้วยการใช้ประโยชน์จากprePersist
กิจกรรมในรอบระยะเวลาคุณสามารถตั้งค่าเริ่มต้นของคุณในเอนทิตีของคุณเฉพาะในการเริ่มต้นยังคงมีอยู่
hack
ใช้เหตุการณ์วงจรถือว่าเป็น อย่าพึ่งแฮ็ก
ระวังเมื่อตั้งค่าเริ่มต้นในการกำหนดคุณสมบัติ! ทำในตัวสร้างแทนเพื่อให้ปราศจากปัญหา หากคุณกำหนดไว้ในนิยามคุณสมบัติให้คงวัตถุไว้ในฐานข้อมูลจากนั้นทำการโหลดบางส่วนแล้วคุณสมบัติที่โหลดไม่ได้จะมีค่าเริ่มต้นอีกครั้ง นั่นเป็นอันตรายหากคุณต้องการคงวัตถุไว้อีกครั้ง