Doktrin'de varsayılan değer


338

Doktrin 2'de nasıl varsayılan bir değer ayarlayabilirim?


26
@ORM \ Column (name = "foo", type = "ondalık", duyarlık = 7, ölçek = 2, seçenekler = {"varsayılan" = 0}) çalışır (aşağıdaki popüler olmayan yanıttan)
WayFarer

2
@ORM \ Sütun (name = "is_activated", type = "boolean", options = {"default": 0}) VEYA @ORM \ Column (name = "is_activated", type = "boolean", options = {"varsayılan "= 0})
ahmed hamdy

Ahmed bu Symfony 2.3 booleans için işe yaramaz gibi görünüyor. Ancak options = {"default" = "0"}) çalışır ve tamsayıyı tırnak içine alır.
Acyra

4
Eğer bir boolean ise, neden kullanmıyorsunuz: options = {"default": false}?
robocoder

Yanıtlar:


385

Veritabanı varsayılan değerleri "taşınabilir" olarak desteklenmez. Veritabanı varsayılan değerlerini kullanmanın tek yolu , alanın eşlendiği sütun için snippet'i ( neden dahil) columnDefinitionbelirttiğiniz eşleme özniteliğidir .SQLDEFAULT

Kullanabilirsiniz:

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

PHP düzeyinde varsayılan değerler tercih edilir, çünkü bunlar yeni oluşturulan ve kalıcı nesnelerde de uygun şekilde bulunur (Doktrin, varsayılan değerleri almak için yeni bir nesneye devam ettikten sonra veritabanına geri dönmez).


11
ancak burada bir sorun var: Bir "datetime" türü ayarlarsam ne olur?
artragis

46
@artragis örneklemenizi varlık yapıcısına yerleştirdi
Alain Tiemblo

16
Mevcut satırlar taşıma işleminin başarısız olmasına neden olacağından, bu yaklaşımı kullanan taşıma işlemlerine dikkat edilmelidir.
Tamlyn

7
Değişkenleri ayarlamak için örnekleme alanını kullanmayın ... Güven bana, kötü bir şey olacak. Bunun yerine yapıcı alanını kullanın.
mimoralea

4
Ek açıklamadaki columnDefinition'ı kullanmanızı öneririm, yoksa biri mysql istemcisini veya phpmyadmin'i kullanır ve değerler yanlış olur ...
NDM

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

Bunun, ve DEFAULTgibi bazı alanlar için desteklenmeyen SQL kullandığını unutmayın .BLOBTEXT


4
İyi yakalama! Resmi belgelerde seçenek yok {{default "= 0} seçeneği yok
WayFarer

2
FYI, optionsparametre de unsigneddeğerler için kullanışlıdır . bu cevaba
yvoyer

5
Tüm üsleri kapsamak için bu ve kabul edilen cevabı kullanıyorum. Ayrıca yapabileceğiniz bir not: options={"default": 0}Doktrin versiyonumda hatalara neden olduğu için "değil" i kullanmaya dikkat edin.
Scott Flack

28
Bu seçilen cevap olmalı!
Acelasi Eu

2
@Matt muhtemelen belgelenmemiş bir özellik olduğu ve belgesiz özelliklerin kaldırılmaya eğilimli olduğunu söyledi. Şimdi belgelendiği gibi, onu kullanmanız güvenli olmalıdır.
JCM

62

Varlığınızda bir kurucu ayarlayın ve orada varsayılan değeri ayarlayın.


Bu kesinlikle mantıklı bir yaklaşım gibi görünüyor. Herkes kurucuda varsayılanları ayarlamak ile ilgili sorunlar var mı?
cantera


@ cantera25 bu cevap +1 olmalı
Phill Pafford

3
varsayılan değere sahip olması gereken yeni bir alan eklerseniz mevcut varlıklar güncellenmez. yani hayır, cevap bu olmamalı. tam olarak ne yapmanız gerektiğine bağlı
Tomáš Tibenski

Güncelleme amacıyla da çalışmaz. Sadece alanı boşaltarak (tamsayı için bile) varsayılan değere geri dönmek istiyorsanız, maalesef çalışmaz.
ThEBiShOp


51

Güncelleme

Symfony belgelerini okumanın bir nedeni daha trend dışı kalmayacak. Özel durumum için basit bir çözüm var ve field typeseçeneği empty_datavarsayılan bir değere ayarlamaktır.

Yine, bu çözüm yalnızca bir formdaki boş bir girdinin DB alanını null olarak ayarladığı senaryo içindir.

Arka fon

Önceki cevapların hiçbiri özel senaryomda bana yardımcı olmadı ama bir çözüm buldum.

Aşağıdaki gibi davranması gereken bir form alanı vardı:

  1. Gerekli değil, boş bırakılabilir. (Kullanılan 'zorunlu' => yanlış)
  2. Boş bırakılırsa, varsayılan olarak belirli bir değere ayarlanmalıdır. Daha iyi kullanıcı deneyimi için, giriş alanında varsayılan değeri ayarlamadım, ancak daha az rahatsız edici olduğu için html özniteliği 'yer tutucu' kullandım.

Daha sonra burada verilen tüm önerileri denedim. Onları listeleyeyim:

  • Obje özelliği için bir varsayılan değer belirleyin:
<?php
/**
 * @Entity
 */
class myEntity {
    /**
     * @var string
     *
     * @Column(name="myColumn", type="string", length="50")
     */
    private $myColumn = 'myDefaultValue';
    ...
}
  • Seçenekler ek açıklamasını kullanın:
@ORM\Column(name="foo", options={"default":"foo bar"})
  • Yapıcıda varsayılan değeri ayarlayın:
/**
 * @Entity
 */
class myEntity {
    ...
    public function __construct()
    {
        $this->myColumn = 'myDefaultValue';
    }
    ...
}
Hiçbiri işe yaramadı ve hepsi Symfony'un Entity sınıfınızı nasıl kullandığından dolayı.

ÖNEMLİ

Symfony form alanları, Entity sınıfında ayarlanan varsayılan değerleri geçersiz kılar. Yani, DB'niz için şemanızın varsayılan bir değeri tanımlanmış olabilir, ancak formunuzu gönderirken zorunlu olmayan bir alanı boş bırakırsanız form->handleRequest(), form->isValid()yönteminizin içi Entitysınıfınızdaki bu varsayılan değerleri geçersiz kılar ve bunları giriş alanı değerlerine ayarlar. Giriş alanı değerleri boşsa, Entityözelliği olarak ayarlar null.

http://symfony.com/doc/current/book/forms.html#handling-form-submissions

Geçici Çözümüm

Yöntemin form->handleRequest()içinde sonra denetleyicinizdeki varsayılan değeri ayarlayın form->isValid():

...
if ($myEntity->getMyColumn() === null) {
    $myEntity->setMyColumn('myDefaultValue');
}
...

Güzel bir çözüm değil ama işe yarıyor. Muhtemelen bir yapabilirim, validation groupancak bu sorunu veri doğrulaması yerine bir veri dönüşümü olarak gören insanlar olabilir , karar vermek için size bırakıyorum.


Ayarlayıcıyı Geçersiz Kıl (Çalışmıyor)

Ayrıca Entityayarlayıcıyı bu şekilde geçersiz kılmaya çalıştım :

...
/**
 * Set myColumn
 *
 * @param string $myColumn
 *
 * @return myEntity
 */
public function setMyColumn($myColumn)
{
    $this->myColumn = ($myColumn === null || $myColumn === '') ? 'myDefaultValue' : $myColumn;

    return $this;
}
...

Bu, daha temiz görünse de, işe yaramıyor . Bunun nedeni, kötü form->handleRequest()yöntemin, verileri güncellemek için Model'in ayarlayıcı yöntemlerini kullanmamasıdır ( form->setData()daha fazla ayrıntı için içeri girin ).


Bu cevap kesinlikle zirveye çıkmalı. Form bileşeni, özelliklerinizin değerlerini almak ve ayarlamak için PropertyAccessor kullanır. Belki mülk erişimcisi mevcut olduğunda yöntemleri kullanmalıdır?
Xobb

1
boolean sütunları php varsayılanlarını desteklemez, bu nedenle yalnızca ek açıklamalar
Crusader

Bilgi formlardan gelirken işe yarayan tek çözüm budur. Ayrıca boole ile ilgili yukarıdaki yorumlara katılmıyorum. Varsayılan ek açıklamayı kabul etmezler.
BernardA

Symfony form bileşeni model ayarlayıcılarını kullanır, ancak yalnızca formun model biçimi verileri, model nesnesi örneğinin karşılık gelen alıcısı tarafından döndürülen verilerden farklı olduğunda kullanılır . Özel ayarlayıcı / alıcı yöntemleriniz varsa - "property_path" form seçeneğini (PropertyAccessor tarafından işlenir) veya özel DataMapper'ı (form ve model nesnesi arasında veri aktarım rutini manuel olarak tanımlamanıza olanak tanır) kullanın.
Arkemlar

1
Bu soru symfony ile değil doktrin ile ilgili, bu yüzden bu cevap gerçekten konu ile ilgili değil.
Omn

18

Kullandığım geçici çözüm bir LifeCycleCallback. Örneğin, daha fazla "yerel" yöntem olup olmadığını görmek için hala bekliyor@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
Gelecekteki okuyucular için, yaşam döngüsü geri çağrılarına güvenmeyin :) Marco Pivetta bile onlara karşı.
emix

Uyarı! Varlık zaten dtPosted özelliğini ayarladıysa, kodunuz özelliğin üzerine yazacaktır. Varsa daima erişimcileri kullanın! if (!$this->getDtPosted()) { $this->setDtPosted(new \DateTime()); }
Barh

13

Bunu xml kullanarak da yapabilirsiniz:

<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

İşte bunu kendim için çözdüm. Aşağıda, MySQL için varsayılan değeri olan bir Varlık örneği verilmiştir. Bununla birlikte, bu ayrıca varlığınızda bir kurucu kurulumu gerektirir ve orada varsayılan değeri ayarlamanız gerekir.

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'

Benim yapılandırma bu satır ile Doctrine her çalıştırdığımda varsayılan sütun bırakmaya çalışır. php app / console doktrini: şema: güncelleme
shapeshifter

1
Buradaki en kötü cevap bu. columnDefinitiondoğrudan veritabanından soyut olan bir ORM'ye sahip olma amacına yöneliktir. Bu çözüm taşınabilirliği bozacak, yazılımınızı DB satıcınıza bağlı tutacak ve Doktrin Geçiş araçlarını da bozacaktır.
Pedro Cordeiro

@PedroCordeiro Size tamamen katılıyorum. Bu, başka bir sorun ortaya çıkana kadar hızlı bir çözümdür.
Putna

7

Benim için de bir mysql veritabanı üzerinde çalışır:

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

Kimin ilgilendiği ek açıklama biçiminde: @ ORM \ Sütun (name = "Entity_name", type = "integer", options = {"default" = "1"})
Hannes

7

Bunların hiçbiri benim için işe yaramadı. Doktrin sitesinde, varsayılan değeri ayarlamak için değeri doğrudan ayarlayan bazı belgeler buldum.

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;

Bu istediğim değeri ekledi.


Lütfen bağlantıyı doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/… olarak değiştirin. Bkz. Nokta 3.2.2. Bir sütuna nasıl varsayılan değerler ekleyebilirim?
Tobi


3

@Romanb pırıltılı cevaba ekleniyor.

Bu, taşıma işlemine biraz ek yük getirir, çünkü null kısıtlaması olmayan ve varsayılan değeri olmayan bir alan oluşturamazsınız.

// 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");

Bu cevapla, neden ilk etapta veritabanında varsayılan değere ihtiyacınız olduğunu düşünmenizi öneririm. Ve genellikle, null kısıtlaması olmayan nesneler oluşturmaya izin vermektir.


3

Varlığınız için yaml tanımı kullanırsanız, postgresql veritabanında aşağıdakiler benim için çalışır:

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

1
$entity->setFieldName()Yıkamadan önce kullanmadıysanız ne olacak ? Doktrin varsayılan değeri null olarak tanımlamaktadır. YAML tek çözüm varsayılan değeri tanımlamaktır İÇİNDE -_- ... zaten YAML tanımlanan beri bana aptal görünüyor varlık sınıfında
J0K

1

Aynı sorunla mücadele ettim. Ben veritabanından varlıklar (otomatik olarak) varsayılan değeri olmasını istedim. Bilin bakalım ne yaptım :)

<?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
Birkaç yıldan bu yana bu yaklaşımı kullanmamanızı tavsiye ederim, gerçekten hack bir kesmek.
Steffen Brem

Kendi cevabınızı
Dragos

1

Yapıcıdaki değeri ayarlamak işe yarayacak olsa da, Doktrin Yaşam Döngüsü olaylarını kullanmak daha iyi bir çözüm olabilir.

prePersistYaşam Döngüsü Etkinliğinden yararlanarak, varlığınızdaki varsayılan değerinizi yalnızca ilk kalıcı olarak ayarlayabilirsiniz.


Yaşam döngüsü olaylarının kullanılması a hack. Asla korsanlara güvenmeyin.
emix

0

Özellik tanımında varsayılan değerleri ayarlarken dikkatli olun! Bunu problemsiz tutmak için yapıcıda yapın. Özellik tanımında tanımlarsanız, nesneyi veritabanında saklarsanız, kısmi bir yükleme yaparsanız, yüklenmeyen özellikler yine varsayılan değere sahip olacaktır. Nesneyi tekrar ısıtmak istiyorsanız bu tehlikelidir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.