Doctrine में डिफ़ॉल्ट मूल्य


338

मैं Doctrine 2 में एक डिफ़ॉल्ट मान कैसे सेट करूं?


26
@ORM \ Column (नाम = "foo", प्रकार = "दशमलव", परिशुद्धता = 7, स्केल = 2, विकल्प = {"डिफ़ॉल्ट" = 0}) काम करता है (नीचे गैर-लोकप्रिय उत्तर से)
WayFarer

2
@ORM \ Column (नाम = "is_activated", प्रकार = "बूलियन", विकल्प = {"डिफ़ॉल्ट": 0}) या @ORM \ Column (नाम = "is_activated", प्रकार = "बुलियन", विकल्प = {"डिफ़ॉल्ट" "= 0})
अहमदी

अहमद यह सिम्फनी 2.3 में बूलियंस के लिए काम नहीं करता है। हालाँकि विकल्प = {"डिफ़ॉल्ट" = "0"}) काम करता है, पूर्णांक को उद्धरणों में रखता है।
Acyra

4
यदि यह एक बूलियन है, तो आप उपयोग क्यों नहीं कर रहे हैं: विकल्प = {"डिफ़ॉल्ट": गलत}?
रोबोकोड

जवाबों:


385

डेटाबेस डिफॉल्ट मान "पोर्टेबली" समर्थित नहीं हैं। डेटाबेस डिफ़ॉल्ट मानों का उपयोग करने का एकमात्र तरीका columnDefinitionमैपिंग विशेषता के माध्यम से होता है जहां आप उस फ़ील्ड के लिए मैप किए गए कॉलम के लिए SQLस्निपेट ( DEFAULTसमावेशी कारण) निर्दिष्ट करते हैं ।

आप उपयोग कर सकते हैं:

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

PHP- स्तर के डिफ़ॉल्ट मानों को प्राथमिकता दी जाती है क्योंकि ये नए बनाए गए और निरंतर ऑब्जेक्ट्स पर भी ठीक से उपलब्ध हैं (डिफ़ॉल्ट मान प्राप्त करने के लिए एक नई वस्तु को जारी रखने के बाद सिद्धांत डेटाबेस में वापस नहीं जाएंगे)।


11
लेकिन यहाँ एक समस्या है: क्या होगा यदि मैं "डेटाइम" प्रकार सेट करूँ?
आर्ट्रैगिस

46
@artragis ने इकाई निर्माण में अपना संस्कार डाला
Alain Tiemblo

16
इस दृष्टिकोण का उपयोग करके माइग्रेशन के साथ देखभाल की जानी चाहिए क्योंकि किसी भी मौजूदा पंक्तियों के कारण माइग्रेशन विफल हो जाएगा।
तामलिन

7
चर सेट करने के लिए तात्कालिक क्षेत्र का उपयोग न करें ... मेरा विश्वास करो, बुरी बात होगी। इसके बजाय कंस्ट्रक्टर क्षेत्र का उपयोग करें।
मिमोरिया

4
मैं एनोटेशन में कॉलमडिफ़िनिशन का उपयोग करने के लिए कहता हूं, या कोई व्यक्ति mysql क्लाइंट या phpmyadmin का उपयोग करेगा और मान गलत होगा ...
NDM 14

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

ध्यान दें कि यह SQL का उपयोग करता है DEFAULT, जो कुछ क्षेत्रों जैसे BLOBऔर के लिए समर्थित नहीं है TEXT


4
अच्छी पकड़! ऐसा लगता है कि आधिकारिक दस्तावेज में कोई विकल्प = {"डिफ़ॉल्ट" = 0} विकल्प नहीं हैं
WayFarer

2
FYI करें, मानों के optionsलिए पैरामीटर भी उपयोगी unsignedहै। इस उत्तर को
yvoyer

5
मैं सभी आधारों को कवर करने के लिए इस और स्वीकृत उत्तर दोनों का उपयोग करता हूं। इसके अलावा सिर्फ एक नोट जो आप भी कर सकते हैं: options={"default": 0}"उपयोग करने के लिए सावधान रहें" और 'नहीं', क्योंकि यह मेरे सिद्धांत के संस्करण में त्रुटियों का कारण बनता है।
स्कॉट फ्लैक

28
यह चयनित उत्तर होना चाहिए!
अकालासी ईयू

2
@ मट ने शायद कहा कि क्योंकि यह एक अनकम्फर्टेबल फ़ीचर था, और अनडोक्युमेटेड फीचर्स को हटाए जाने का खतरा है। जैसा कि अभी यह प्रलेखित है, आपको इसका उपयोग करके सुरक्षित होना चाहिए।
JCM

62

अपनी इकाई में एक निर्माता सेट करें और वहां डिफ़ॉल्ट मान सेट करें।


यह निश्चित रूप से तार्किक दृष्टिकोण की तरह लगता है। क्या किसी ने निर्माणकर्ता में चूक स्थापित करने के मुद्दों को चलाया है?
कैंटर

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
मुझे क्षमा करें, आप सही हैं। तो आप इस पृष्ठ पर एक स्पष्टीकरण पा सकते हैं: सिद्धांत-ओआरएम एनोटेशन-संदर्भ
स्टैनिस्लाव टेरलेस्की

51

अपडेट करें

एक और कारण है कि सिम्फनी के लिए दस्तावेज़ीकरण पढ़ने का चलन कभी खत्म नहीं होगा। मेरे विशिष्ट मामले का एक सरल समाधान है और 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';
    }
    ...
}
इसमें से किसी ने भी काम नहीं किया और सभी इस बात के कारण कि सिम्फनी आपके एंटिटी क्लास का उपयोग कैसे करता है।

जरूरी

सिम्फनी फॉर्म फ़ील्ड्स डिफ़ॉल्ट मानों को ओवरराइड क्लास पर सेट करते हैं। मतलब, आपके 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

1
बूलियन कॉलम php से डिफॉल्ट का समर्थन नहीं करता है, इसलिए केवल एनोटेशन
क्रूसेडर

यह एकमात्र समाधान है, जब जानकारी रूपों से आ रही है। इसके अलावा मैं बूलियन से संबंधित उपरोक्त टिप्पणियों से असहमत हूं। वे डिफ़ॉल्ट एनोटेशन को स्वीकार नहीं करते हैं।
बर्नार्डा

सिम्फनी फॉर्म घटक मॉडल सेटर्स का उपयोग करता है, लेकिन केवल तब जब फॉर्म का मॉडल प्रारूप डेटा ऑब्जेक्ट ऑब्जेक्ट उदाहरण के संगत गेटर द्वारा लौटाए गए डेटा के साथ भिन्न होता है। यदि आपके पास अपने कस्टम सेटर / गेट्टर विधियाँ हैं - तो "property_path" फ़ॉर्म विकल्प (PropertyAccessor द्वारा नियंत्रित किया जाएगा) या कस्टम DataMapper का उपयोग करें (फ़ॉर्म और मॉडल ऑब्जेक्ट के बीच डेटा ट्रांसफर रूटीन को मैन्युअल रूप से परिभाषित करने की अनुमति देता है)।
अरकेमलर

1
यह प्रश्न सिद्धांत के बारे में है, सिम्फनी नहीं है, इसलिए यह उत्तर वास्तव में विषय पर नहीं है।
०34

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
भविष्य के पाठकों के लिए, जीवनचक्र कॉलबैक पर भरोसा न करें :) यहां तक ​​कि मार्को पिवेटा भी उनके खिलाफ हैं।
एमिक्स

चेतावनी! यदि इकाई ने पहले से ही dtPosted संपत्ति सेट की है, तो आपका कोड संपत्ति को अधिलेखित कर देगा। यदि वे मौजूद हैं तो हमेशा एक्सेसर्स का उपयोग करें! if (!$this->getDtPosted()) { $this->setDtPosted(new \DateTime()); }
बारह

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 ऐप / कंसोल सिद्धांत: स्कीमा: अपडेट
आकृति

1
यह यहां सबसे खराब जवाब है। columnDefinitionएक ORM होने के उद्देश्य से सीधे जाता है, जो डेटाबेस से अमूर्त है। यह समाधान पोर्टेबिलिटी को तोड़ देगा, आपके सॉफ्टवेयर को आपके डीबी विक्रेता पर निर्भर रखेगा और डॉक्ट्रिन माइग्रेशन टूल्स को भी तोड़ देगा।
पेड्रो कॉर्डिएरो

@PedroCordeiro मैं आपसे पूरी तरह सहमत हूँ। यह सिर्फ एक तेजी से समाधान है जब तक कि कोई अन्य मुद्दा नहीं उठता।
पूतना

7

मेरे लिए mysql डेटाबेस पर भी काम करता है:

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

एनोटेशन प्रारूप में जिसके लिए रुचि है: @ORM \ Column (नाम = "Entity_name", प्रकार = "पूर्णांक", विकल्प = {"डिफ़ॉल्ट" = "1"})
हेंस

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 लिंक देखें। मैं किसी कॉलम में डिफ़ॉल्ट मान कैसे जोड़ सकता हूं?
तोबी


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 परिभाषा का उपयोग करते हैं, तो मेरे लिए एक पोस्टग्रैस्क्ल डेटाबेस पर निम्नलिखित कार्य करता है:

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

1
क्या होगा अगर आपने $entity->setFieldName()फ्लशिंग करने से पहले उपयोग नहीं किया है ? सिद्धांत शून्य पर डिफ़ॉल्ट मान को परिभाषित करने के लिए लगता है। 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
कुछ वर्षों से इस पर वापस आकर मैं आपको इस दृष्टिकोण का उपयोग नहीं करने की सलाह देता हूं, यह वास्तव में एक हैक हैक है।
स्टीफन ब्रेम

चूंकि आप अपने स्वयं के उत्तर की अनुशंसा नहीं करते हैं, इसलिए आप इसे ठीक भी कर सकते हैं;)
ड्रैगोस

1

कंस्ट्रक्टर में मान सेट करने के दौरान काम करेगा, Doctrine Lifecycle घटनाओं का उपयोग करना बेहतर समाधान हो सकता है।

prePersistजीवनचक्र ईवेंट का लाभ उठाकर , आप केवल प्रारंभिक दृढ़ता पर अपनी इकाई पर अपना डिफ़ॉल्ट मान सेट कर सकते हैं।


जीवनचक्र की घटनाओं का उपयोग करना माना जाता है hack। कभी भी हैक पर भरोसा न करें।
एमिक्स

0

संपत्ति की परिभाषा पर डिफ़ॉल्ट मान सेट करते समय सावधान रहें! इसके बजाय इसे कंस्ट्रक्टर में करें, इसे समस्या-मुक्त रखने के लिए। यदि आप इसे संपत्ति की परिभाषा पर परिभाषित करते हैं, तो डेटाबेस के लिए ऑब्जेक्ट को बनाए रखें, फिर एक आंशिक लोड करें, फिर लोड नहीं किए गए गुणों का फिर से डिफ़ॉल्ट मान होगा। यदि आप ऑब्जेक्ट को फिर से जारी रखना चाहते हैं तो यह खतरनाक है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.