मैं Doctrine 2 में एक डिफ़ॉल्ट मान कैसे सेट करूं?
मैं Doctrine 2 में एक डिफ़ॉल्ट मान कैसे सेट करूं?
जवाबों:
डेटाबेस डिफॉल्ट मान "पोर्टेबली" समर्थित नहीं हैं। डेटाबेस डिफ़ॉल्ट मानों का उपयोग करने का एकमात्र तरीका columnDefinition
मैपिंग विशेषता के माध्यम से होता है जहां आप उस फ़ील्ड के लिए मैप किए गए कॉलम के लिए SQL
स्निपेट ( DEFAULT
समावेशी कारण) निर्दिष्ट करते हैं ।
आप उपयोग कर सकते हैं:
<?php
/**
* @Entity
*/
class myEntity {
/**
* @var string
*
* @Column(name="myColumn", type="string", length="50")
*/
private $myColumn = 'myDefaultValue';
...
}
PHP- स्तर के डिफ़ॉल्ट मानों को प्राथमिकता दी जाती है क्योंकि ये नए बनाए गए और निरंतर ऑब्जेक्ट्स पर भी ठीक से उपलब्ध हैं (डिफ़ॉल्ट मान प्राप्त करने के लिए एक नई वस्तु को जारी रखने के बाद सिद्धांत डेटाबेस में वापस नहीं जाएंगे)।
<?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
एक और कारण है कि सिम्फनी के लिए दस्तावेज़ीकरण पढ़ने का चलन कभी खत्म नहीं होगा। मेरे विशिष्ट मामले का एक सरल समाधान है और 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';
}
...
}
इसमें से किसी ने भी काम नहीं किया और सभी इस बात के कारण कि सिम्फनी आपके एंटिटी क्लास का उपयोग कैसे करता है।
सिम्फनी फॉर्म फ़ील्ड्स डिफ़ॉल्ट मानों को ओवरराइड क्लास पर सेट करते हैं।
मतलब, आपके 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 होने के उद्देश्य से सीधे जाता है, जो डेटाबेस से अमूर्त है। यह समाधान पोर्टेबिलिटी को तोड़ देगा, आपके सॉफ्टवेयर को आपके डीबी विक्रेता पर निर्भर रखेगा और डॉक्ट्रिन माइग्रेशन टूल्स को भी तोड़ देगा।
मेरे लिए 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 परिभाषा का उपयोग करते हैं, तो मेरे लिए एक पोस्टग्रैस्क्ल डेटाबेस पर निम्नलिखित कार्य करता है:
Entity\Entity_name:
type: entity
table: table_name
fields:
field_name:
type: boolean
nullable: false
options:
default: false
$entity->setFieldName()
फ्लशिंग करने से पहले उपयोग नहीं किया है ? सिद्धांत शून्य पर डिफ़ॉल्ट मान को परिभाषित करने के लिए लगता है। 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
। कभी भी हैक पर भरोसा न करें।
संपत्ति की परिभाषा पर डिफ़ॉल्ट मान सेट करते समय सावधान रहें! इसके बजाय इसे कंस्ट्रक्टर में करें, इसे समस्या-मुक्त रखने के लिए। यदि आप इसे संपत्ति की परिभाषा पर परिभाषित करते हैं, तो डेटाबेस के लिए ऑब्जेक्ट को बनाए रखें, फिर एक आंशिक लोड करें, फिर लोड नहीं किए गए गुणों का फिर से डिफ़ॉल्ट मान होगा। यदि आप ऑब्जेक्ट को फिर से जारी रखना चाहते हैं तो यह खतरनाक है।