ค่าเริ่มต้นในหลักคำสอน


338

ฉันจะตั้งค่าเริ่มต้นใน Doctrine 2 ได้อย่างไร


26
@ORM \ Column (ชื่อ = "foo", พิมพ์ = "ทศนิยม", ความแม่นยำ = 7, สเกล = 2, ตัวเลือก = {"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

อาเหม็ดสิ่งนี้ดูเหมือนจะใช้งานไม่ได้กับ booleans ใน Symfony 2.3 อย่างไรก็ตาม options = {"default" = "0"}) ใช้งานได้ให้ใส่จำนวนเต็มในเครื่องหมายคำพูด
Acyra

4
หากเป็นบูลีนทำไมคุณไม่ใช้: options = {"default": false}
robocoder

คำตอบ:


385

ค่าเริ่มต้นของฐานข้อมูลไม่รองรับ "แบบพกพา" วิธีเดียวที่จะใช้ค่าเริ่มต้นฐานข้อมูลผ่านcolumnDefinitionแอตทริบิวต์การทำแผนที่ที่คุณระบุSQLข้อมูลโค้ด ( DEFAULTสาเหตุรวม) สำหรับคอลัมน์สนามถูกแมปไป

คุณสามารถใช้ได้:

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

ต้องการค่าเริ่มต้นในระดับ PHP เนื่องจากยังมีอยู่ในวัตถุที่สร้างขึ้นใหม่และยังคงอยู่อย่างเหมาะสม (Doctrine จะไม่กลับไปที่ฐานข้อมูลหลังจากเก็บวัตถุใหม่เพื่อรับค่าเริ่มต้น)


11
แต่มีปัญหาที่นี่: จะเกิดอะไรขึ้นถ้าฉันตั้งค่าประเภท "datetime"
artragis

46
@artragis ใส่การเริ่มต้นของคุณในตัวสร้างเอนทิตี
Alain Tiemblo

16
ต้องใช้ความระมัดระวังในการย้ายข้อมูลโดยใช้วิธีการนี้เนื่องจากแถวที่มีอยู่จะทำให้การโยกย้ายล้มเหลว
Tamlyn

7
อย่าใช้พื้นที่การสร้างอินสแตนซ์เพื่อตั้งค่าตัวแปร ... เชื่อฉันสิว่าสิ่งเลวร้ายจะเกิดขึ้น ใช้พื้นที่ตัวสร้างแทน
mimoralea

4
ฉันขอแนะนำให้ใช้ columnDefinition ในคำอธิบายประกอบหรือใครบางคนจะใช้ไคลเอนต์ mysql หรือ phpmyadmin และค่าจะผิด ...
NDM

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

โปรดทราบว่านี้ใช้ SQL DEFAULTซึ่งไม่ได้รับการสนับสนุนสำหรับเขตข้อมูลบางอย่างเช่นและBLOBTEXT


4
จับดี! ดูเหมือนว่าไม่มีตัวเลือก = {"default" = 0} ตัวเลือกในเอกสารประกอบอย่างเป็นทางการ
WayFarer

2
FYI optionsพารามิเตอร์นี้ยังมีประโยชน์สำหรับunsignedค่าต่างๆ ดูคำตอบ
yvoyer

5
ฉันใช้ทั้งนี้และคำตอบที่ได้รับการยอมรับเพื่อครอบคลุมทุกฐาน นอกจากนี้โปรดทราบว่าคุณสามารถทำได้: options={"default": 0}ระวังการใช้ "และไม่ใช่" เนื่องจากจะทำให้เกิดข้อผิดพลาดในรุ่นหลักคำสอนของฉัน
Scott Flack

28
นี่ควรเป็นคำตอบที่เลือก!
Acelasi Eu

2
@Matt เขาอาจบอกว่าเพราะมันเป็นคุณสมบัติที่ไม่มีเอกสารและคุณลักษณะที่ไม่ได้จัดทำมีแนวโน้มที่จะถูกลบออก ตามเอกสารตอนนี้คุณควรจะปลอดภัยในการใช้มัน
JCM

62

ตั้งค่าตัวสร้างในเอนทิตีของคุณและตั้งค่าเริ่มต้นที่นั่น


ดูเหมือนว่านี่จะเป็นแนวทางที่สมเหตุสมผล มีใครพบปัญหาในการตั้งค่าเริ่มต้นในตัวสร้างหรือไม่
cantera

26
หลักคำสอนของที่แนะนำวิธีการแก้ปัญหา: doctrine-project.org/docs/orm/2.1/en/reference/faq.html
Cantera

@ cantera25 ที่ควรเป็นคำตอบ +1
Phill Pafford

3
สิ่งนี้จะไม่อัปเดตเอนทิตีที่มีอยู่หากคุณเพิ่มฟิลด์ใหม่ซึ่งจำเป็นต้องมีค่าเริ่มต้น ดังนั้นไม่ใช่ว่าไม่ควรเป็นคำตอบ ขึ้นอยู่กับสิ่งที่คุณต้องทำ
TomášTibenský

มันจะไม่ทำงานในการปรับปรุงวัตถุประสงค์อย่างใดอย่างหนึ่ง หากคุณต้องการกลับไปที่ค่าเริ่มต้นเพียงล้างฟิลด์ (แม้จะเป็นจำนวนเต็ม) แต่น่าเสียดายที่มันไม่ทำงาน
ThEBiShOp

55

ใช้:

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

และไม่:

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

ตัวอย่างเช่น

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

2
ฉันขอโทษคุณพูดถูก ดังนั้นคุณสามารถหาคำอธิบายในหน้านี้: การอ้างอิงคำอธิบายประกอบหลักคำสอน - orm
Stanislav Terletskyi

51

ปรับปรุง

อีกเหตุผลหนึ่งที่ทำไมการอ่านเอกสารสำหรับ Symfony จะไม่ตกเทรนด์ มีวิธีแก้ไขปัญหาง่าย ๆ สำหรับกรณีเฉพาะของฉันและตั้งค่าfield typeตัวเลือกempty_dataเป็นค่าเริ่มต้น

อีกครั้งโซลูชันนี้ใช้สำหรับสถานการณ์ที่อินพุตว่างในฟอร์มตั้งค่าฟิลด์ DB เป็นโมฆะเท่านั้น

พื้นหลัง

ไม่มีคำตอบก่อนหน้านี้ที่ช่วยฉันในสถานการณ์เฉพาะ แต่ฉันพบวิธีแก้ปัญหา

ฉันมีเขตข้อมูลฟอร์มที่จำเป็นต้องทำงานดังต่อไปนี้:

  1. ไม่จำเป็นต้องเว้นว่างไว้ (ใช้ 'จำเป็น' => เท็จ)
  2. หากเว้นว่างไว้ค่าเริ่มต้นควรเป็นค่าที่กำหนด เพื่อประสบการณ์การใช้งานที่ดีขึ้นฉันไม่ได้ตั้งค่าเริ่มต้นในช่องป้อนข้อมูล แต่ควรใช้แอตทริบิวต์ html 'ตัวยึดตำแหน่ง' เนื่องจากมีลักษณะไม่ชัดเจนน้อยกว่า

ฉันลองทำตามคำแนะนำทั้งหมดที่ให้ไว้ที่นี่ ให้ฉันเขียนรายการพวกเขา:

  • ตั้งค่าเริ่มต้นเมื่อสำหรับคุณสมบัตินิติบุคคล:
<?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คลาสของคุณและตั้งเป็นค่าฟิลด์อินพุต หากค่าช่องใส่ว่างเปล่าแล้วมันจะตั้งค่าคุณสมบัติการEntitynull

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

1
คอลัมน์บูลีนไม่สนับสนุนค่าเริ่มต้นจาก php ดังนั้นคำอธิบายประกอบเท่านั้น
Crusader

นี่เป็นทางออกเดียวที่ทำงานเมื่อข้อมูลมาจากแบบฟอร์ม ฉันไม่เห็นด้วยกับความคิดเห็นข้างต้นที่เกี่ยวข้องกับบูลีน พวกเขาไม่ยอมรับคำอธิบายประกอบเริ่มต้น
BernardA

องค์ประกอบแบบฟอร์ม Symfony ใช้ตัวตั้งค่าโมเดล แต่เฉพาะเมื่อข้อมูลรูปแบบโมเดลของฟอร์มแตกต่างกับข้อมูลที่ส่งคืนโดย getter ที่สอดคล้องกันของอินสแตนซ์ของโมเดลวัตถุ หากคุณมีเมธอด setter / getter ที่กำหนดเอง - ใช้ตัวเลือกแบบฟอร์ม "property_path" (จะได้รับการจัดการโดย PropertyAccessor) หรือ DataMapper แบบกำหนดเอง (อนุญาตให้กำหนดขั้นตอนการถ่ายโอนข้อมูลระหว่างวัตถุและแบบจำลองด้วยตนเอง)
Arkemlar

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 แล้วรหัสของคุณจะเขียนทับคุณสมบัตินั้น ใช้ accessors ทุกครั้งถ้ามีอยู่! 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'

ด้วยบรรทัดนี้ในการกำหนดค่าหลักคำสอนของฉันพยายามวางค่าเริ่มต้นในคอลัมน์ทุกครั้งที่ฉันเรียกใช้ คำสั่ง php app / console: schema: update
shapeshifter

1
นี่คือคำตอบที่เลวร้ายที่สุดที่นี่ columnDefinitionไปยังจุดประสงค์ของการมี ORM โดยตรงซึ่งเป็นนามธรรมจากฐานข้อมูล โซลูชันนี้จะทำลายการพกพาจะทำให้ซอฟต์แวร์ของคุณขึ้นอยู่กับผู้ขาย DB ของคุณและจะทำลายเครื่องมือ Doctrine Migration
Pedro Cordeiro

@PedroCordeiro ฉันเห็นด้วยกับคุณอย่างสมบูรณ์ นี่เป็นเพียงวิธีการแก้ปัญหาที่รวดเร็วจนกระทั่งปัญหาอื่น ๆ เกิดขึ้น
Putna

7

ทำงานให้ฉันในฐานข้อมูล mysql ด้วย:

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

ในรูปแบบคำอธิบายประกอบสำหรับผู้ที่สนใจ: @ORM \ Column (ชื่อ = "Entity_name", พิมพ์ = "จำนวนเต็ม", ตัวเลือก = {"default" = "1"})
Hannes

7

สิ่งนี้ไม่ได้ผลสำหรับฉัน ฉันพบเอกสารบางอย่างในเว็บไซต์ของหลักคำสอนที่ระบุว่าจะตั้งค่าโดยตรงเพื่อตั้งค่าเริ่มต้น

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 ฉันจะเพิ่มค่าเริ่มต้นในคอลัมน์ได้อย่างไร
Tobi


3

กำลังเพิ่มไปยัง @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");

ด้วยคำตอบนี้ฉันขอแนะนำให้คุณคิดว่าทำไมคุณต้องการค่าเริ่มต้นในฐานข้อมูลตั้งแต่แรก? และโดยปกติจะอนุญาตให้สร้างวัตถุที่ไม่มีข้อ จำกัด เป็นโมฆะ


3

หากคุณใช้คำนิยาม yaml สำหรับเอนทิตีของคุณข้อมูลต่อไปนี้ใช้ได้กับฉันในฐานข้อมูล postgresql:

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

1
ถ้าคุณไม่ได้ใช้งาน$entity->setFieldName()ก่อนที่จะล้างข้อมูล หลักคำสอนดูเหมือนว่าจะกำหนดค่าเริ่มต้นที่ null วิธีการแก้ปัญหาเฉพาะใน yaml คือการกำหนดค่าเริ่มต้นในระดับนิติบุคคลซึ่งดูเหมือนว่าใบ้ให้ฉันตั้งแต่มันกำหนดไว้แล้วใน 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

เนื่องจากคุณไม่แนะนำคำตอบของคุณเองคุณก็อาจจะลบมันได้เช่นกัน)
Dragos

1

ในขณะที่การตั้งค่าในตัวสร้างจะใช้งานได้การใช้เหตุการณ์ Doctrine Lifecycle อาจเป็นทางออกที่ดีกว่า

ด้วยการใช้ประโยชน์จากprePersistกิจกรรมในรอบระยะเวลาคุณสามารถตั้งค่าเริ่มต้นของคุณในเอนทิตีของคุณเฉพาะในการเริ่มต้นยังคงมีอยู่


hackใช้เหตุการณ์วงจรถือว่าเป็น อย่าพึ่งแฮ็ก
emix

0

ระวังเมื่อตั้งค่าเริ่มต้นในการกำหนดคุณสมบัติ! ทำในตัวสร้างแทนเพื่อให้ปราศจากปัญหา หากคุณกำหนดไว้ในนิยามคุณสมบัติให้คงวัตถุไว้ในฐานข้อมูลจากนั้นทำการโหลดบางส่วนแล้วคุณสมบัติที่โหลดไม่ได้จะมีค่าเริ่มต้นอีกครั้ง นั่นเป็นอันตรายหากคุณต้องการคงวัตถุไว้อีกครั้ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.