교리의 기본값


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몇 가지와 같은 분야에 대해 지원되지 않습니다, BLOBTEXT.


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.