교리의 기본값


338

Doctrine 2에서 기본값을 어떻게 설정합니까?


26
@ORM \ Column (name = "foo", type = "decimal", precision = 7, scale = 2, options = { "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 2016

Ahmed 이것은 Symfony 2.3의 부울에서는 작동하지 않는 것 같습니다. 그러나 options = { "default"= "0"})은 작동하며 정수는 따옴표로 묶습니다.
— Acyra

4
부울 인 경우, options = { "default": false}를 사용하지 않는 이유는 무엇입니까?
— robocoder

답변:


385

데이터베이스 기본값은 "이식 적으로"지원되지 않습니다. 데이터베이스 기본값을 사용하는 유일한 방법 은 필드가 맵핑되는 열에 대한 스 니펫 ( 원인 포함)을 columnDefinition지정하는 맵핑 속성을 사용하는 것입니다.SQLDEFAULT

당신이 사용할 수있는:

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

PHP 레벨 기본값은 새로 작성되고 지속되는 오브젝트에서도 올바르게 사용할 수 있으므로 선호됩니다 (기본 값을 얻기 위해 새 오브젝트를 지속 한 후 교리는 데이터베이스로 돌아 가지 않습니다).


11
그러나 여기에 문제가 있습니다 : "datetime"유형을 설정하면 어떻게됩니까?
— artragis

46
@artragis는 개체 생성자에 instanciation을 넣어
— 알랭 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몇 가지와 같은 분야에 대해 지원되지 않습니다, BLOB및 TEXT.


4
잘 잡아! 공식 문서에는 options = { "default"= 0} 옵션이없는 것 같습니다
— WayFarer

2
참고로, options매개 변수는 unsigned값 에도 유용 합니다. 이 답변보기
— yvoyer

5
나는 모든 기초를 다루기 위해이 대답과 대답을 모두 사용합니다. 또한 할 수있는 참고 사항 : options={"default": 0}내 버전의 교리에 오류가 발생하기 때문에 '가 아니라'를 사용하십시오.
— Scott Flack

28
이것이 정답입니다!
— Acelasi Eu

2
@Matt는 문서화되지 않은 기능이기 때문에 문서화되지 않은 기능이 제거되기 쉽다고 말했을 것입니다. 지금 문서화되었으므로 안전하게 사용해야합니다.
— JCM

62

엔터티에 생성자를 설정하고 기본값을 설정하십시오.


이것은 확실히 논리적 접근 방식처럼 보입니다. 생성자에서 기본값을 설정하는 데 문제가있는 사람이 있습니까?
— cantera


대답 +1해야 @ cantera25
— 필 Pafford

3
기본값을 가져야하는 새 필드를 추가하면 기존 엔티티가 업데이트되지 않습니다. 그래서 대답이되어서는 안됩니다. 정확히 무엇을해야하는지에 따라 다릅니다.
— Tomáš Tibenský

업데이트 목적으로도 작동하지 않습니다. 불행히도 필드를 비워서 (정수의 경우에도) 기본값으로 돌아가려면 작동하지 않습니다.
— ThEBiShOp


51

최신 정보

Symfony에 대한 문서 를 읽는 또 다른 이유 는 결코 추세에서 벗어나지 않을 것입니다. 내 경우에 대한 간단한 해결책이 있으며 field type옵션 empty_data을 기본값 으로 설정하는 것 입니다.

이 솔루션은 양식의 빈 입력이 DB 필드를 null로 설정하는 시나리오에만 해당됩니다.

배경

이전 답변 중 어느 것도 내 특정 시나리오에 도움이되지 않았지만 해결책을 찾았습니다.

다음과 같이 동작 해야하는 양식 필드가 있습니다.

  1. 필요하지 않습니다. 비워 둘 수 있습니다. ( '필수'=> false 사용)
  2. 비워두면 기본적으로 주어진 값으로 설정되어야합니다. 더 나은 사용자 경험을 위해 입력 필드에 기본값을 설정하지 않았지만 html 속성 'placeholder'는 덜 눈에 띄지 않기 때문에 사용했습니다.

그런 다음 여기에 제공된 모든 권장 사항을 시도했습니다. 그것들을 나열하겠습니다 :

  • 엔티티 속성에 대한 기본값을 설정하십시오.
<?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()입니다 (자세한 내용은 자세히 알아보십시오).


이 답변은 반드시 상단으로 가야합니다. 양식 구성 요소는 PropertyAccessor를 사용하여 속성 값을 가져오고 설정합니다. 어쩌면 속성 접근자는 메서드를 사용할 수있을 때 사용해야합니까?
— Xobb

1
부울 열은 PHP의 기본값을 지원하지 않으므로 주석 만 사용
— Crusader

정보가 양식에서 나올 때 작동하는 유일한 솔루션입니다. 또한 부울에 관한 위의 의견에 동의하지 않습니다. 기본 주석을 허용하지 않습니다.
— BernardA

Symfony 양식 컴포넌트 는 모델 세터를 사용 하지만 양식의 모델 형식 데이터가 모델 오브젝트 인스턴스의 해당 getter에 의해 리턴 된 데이터와 다른 경우에만 해당됩니다 . 사용자 정의 setter / getter 메소드가있는 경우 "property_path"양식 옵션 (PropertyAccessor에서 처리됨) 또는 사용자 정의 DataMapper (양식과 모델 오브젝트 간의 데이터 전송 루틴을 수동으로 정의 할 수 있음)를 사용하십시오.
— Arkemlar

1
이 질문은 교향곡이 아니라 교리에 관한 것이므로이 답변은 실제로 주제에 관한 것이 아닙니다.
— 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 특성을 설정 한 경우 코드는 단순히 특성을 겹쳐 씁니다. 접근자가 존재하는 경우 항상 사용하십시오! 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'

내 구성 에서이 줄을 사용하면 Doctrine은 실행할 때마다 열의 기본값을 삭제하려고합니다. PHP 응용 프로그램 / 콘솔 교리 : 스키마 : 업데이트
— shapeshifter

1
이것은 최악의 대답입니다. columnDefinition데이터베이스에서 추출한 ORM을 갖는 목적을 직접 거슬러 올라갑니다. 이 솔루션은 이식성을 깨고 소프트웨어를 DB 공급 업체에 의존하게하며 Doctrine Migrations 도구도 손상시킵니다.
— 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 (name = "Entity_name", type = "integer", options = { "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");

이 답변으로 데이터베이스의 기본값이 왜 처음에 필요한지 생각하는 것이 좋습니다. 그리고 일반적으로 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의 유일한 해결책은 기본값을 정의하는 것입니다 IN -_- ... 그것은 이미 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.