Làm cách nào để đặt giá trị mặc định trong Học thuyết 2?
Làm cách nào để đặt giá trị mặc định trong Học thuyết 2?
Câu trả lời:
Các giá trị mặc định của cơ sở dữ liệu không được "hỗ trợ" một cách hợp lý. Cách duy nhất để sử dụng các giá trị mặc định của cơ sở dữ liệu là thông qua columnDefinition
thuộc tính ánh xạ nơi bạn chỉ định SQL
đoạn mã ( DEFAULT
bao gồm nguyên nhân) cho cột mà trường được ánh xạ tới.
Bạn có thể dùng:
<?php
/**
* @Entity
*/
class myEntity {
/**
* @var string
*
* @Column(name="myColumn", type="string", length="50")
*/
private $myColumn = 'myDefaultValue';
...
}
Các giá trị mặc định ở cấp độ PHP được ưa thích vì chúng cũng có sẵn trên các đối tượng mới được tạo và tồn tại (Doctrine sẽ không quay lại cơ sở dữ liệu sau khi duy trì một đối tượng mới để lấy các giá trị mặc định).
<?php
/**
* @Entity
*/
class myEntity {
/**
* @var string
*
* @ORM\Column(name="myColumn", type="integer", options={"default" : 0})
*/
private $myColumn;
...
}
Lưu ý rằng điều này sử dụng SQL DEFAULT
, không được hỗ trợ cho một số trường như BLOB
và TEXT
.
options={"default": 0}
Cẩn thận sử dụng "chứ không phải", vì nó gây ra lỗi trong phiên bản giáo lý của tôi.
Thiết lập một hàm tạo trong thực thể của bạn và đặt giá trị mặc định ở đó.
Sử dụng:
options={"default":"foo bar"}
và không:
options={"default"="foo bar"}
Ví dụ:
/**
* @ORM\Column(name="foo", type="smallint", options={"default":0})
*/
private $foo
Thêm một lý do tại sao đọc tài liệu cho Symfony sẽ không bao giờ lỗi thời. Có một giải pháp đơn giản cho trường hợp cụ thể của tôi và là đặt field type
tùy chọn empty_data
thành giá trị mặc định.
Một lần nữa, giải pháp này chỉ dành cho kịch bản trong đó một đầu vào trống trong biểu mẫu đặt trường DB thành null.
Không có câu trả lời nào trước đây giúp tôi với kịch bản cụ thể của mình nhưng tôi đã tìm ra giải pháp.
Tôi đã có một trường mẫu cần hành xử như sau:
Sau đó tôi đã thử tất cả các khuyến nghị được đưa ra ở đây. Hãy để tôi liệt kê chúng:
<?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';
}
...
}
Không ai trong số đó hoạt động và tất cả vì cách Symfony sử dụng lớp Thực thể của bạn.
Các trường biểu mẫu Symfony ghi đè các giá trị mặc định được đặt trên lớp Thực thể.
Có nghĩa là, lược đồ cho DB của bạn có thể có một giá trị mặc định được xác định nhưng nếu bạn để trống một trường không bắt buộc khi gửi biểu mẫu của bạn, form->handleRequest()
bên trong form->isValid()
phương thức của bạn sẽ ghi đè các giá trị mặc định đó trên Entity
lớp của bạn và đặt chúng thành các giá trị trường đầu vào. Nếu các giá trị trường đầu vào trống, thì nó sẽ đặt thuộc Entity
tính thành null
.
http://symfony.com/doc/cản/book/forms.html#handling-form-submissions
Đặt giá trị mặc định trên bộ điều khiển của bạn sau form->handleRequest()
bên trong form->isValid()
phương thức của bạn :
...
if ($myEntity->getMyColumn() === null) {
$myEntity->setMyColumn('myDefaultValue');
}
...
Không phải là một giải pháp đẹp nhưng nó hoạt động. Tôi có thể có thể thực hiện validation group
nhưng có thể có người coi vấn đề này là chuyển đổi dữ liệu thay vì xác thực dữ liệu , tôi để bạn quyết định.
Tôi cũng đã cố gắng ghi đè Entity
setter theo cách này:
...
/**
* Set myColumn
*
* @param string $myColumn
*
* @return myEntity
*/
public function setMyColumn($myColumn)
{
$this->myColumn = ($myColumn === null || $myColumn === '') ? 'myDefaultValue' : $myColumn;
return $this;
}
...
Điều này, mặc dù nó trông sạch hơn, nhưng nó không hoạt động . Lý do là form->handleRequest()
phương thức tà ác không sử dụng các phương thức setter của Model để cập nhật dữ liệu (tìm form->setData()
hiểu thêm chi tiết).
Cách giải quyết tôi sử dụng là a LifeCycleCallback
. Vẫn đang chờ xem liệu có phương pháp "gốc" nào nữa không @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()); }
Bạn cũng có thể làm điều đó bằng 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>
Đây là cách tôi giải quyết nó cho chính mình. Dưới đây là một ví dụ thực thể với giá trị mặc định cho MySQL. Tuy nhiên, điều này cũng yêu cầu thiết lập một hàm tạo trong thực thể của bạn và để bạn đặt giá trị mặc định ở đó.
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
trực tiếp thực hiện lại mục đích có ORM, đó là sự trừu tượng hóa từ cơ sở dữ liệu. Giải pháp này sẽ phá vỡ tính di động, sẽ giữ cho phần mềm của bạn phụ thuộc vào nhà cung cấp DB của bạn và cũng sẽ phá vỡ các công cụ Di chuyển học thuyết.
Cũng hoạt động với tôi trên cơ sở dữ liệu mysql:
Entity\Entity_name:
type: entity
table: table_name
fields:
field_name:
type: integer
nullable: true
options:
default: 1
Không ai trong số này làm việc cho tôi. Tôi tìm thấy một số tài liệu trên trang web của học thuyết nói rằng đặt giá trị trực tiếp để đặt giá trị mặc định.
private $default = 0;
Điều này chèn giá trị tôi muốn.
Thêm vào câu trả lời tuyệt vời @romanb.
Điều này thêm một chút chi phí trong quá trình di chuyển, vì rõ ràng bạn không thể tạo một trường không có ràng buộc null và không có giá trị mặc định.
// 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");
Với câu trả lời này, tôi khuyến khích bạn nghĩ tại sao bạn cần giá trị mặc định trong cơ sở dữ liệu ngay từ đầu? Và thông thường, nó là cho phép tạo các đối tượng không ràng buộc null.
Nếu bạn sử dụng định nghĩa yaml cho thực thể của mình, thì công việc sau đây đối với tôi trên cơ sở dữ liệu postgresql:
Entity\Entity_name:
type: entity
table: table_name
fields:
field_name:
type: boolean
nullable: false
options:
default: false
$entity->setFieldName()
trước khi xả? Học thuyết dường như xác định giá trị mặc định ở mức null. Giải pháp duy nhất trong yaml là xác định giá trị mặc định IN lớp thực thể có vẻ ngu ngốc đối với tôi vì nó đã được định nghĩa trong yaml ... -_-
Tôi vật lộn với cùng một vấn đề. Tôi muốn có giá trị mặc định từ cơ sở dữ liệu vào các thực thể (tự động). Đoán xem, tôi đã làm nó :)
<?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";
Trong khi đặt giá trị trong hàm tạo sẽ hoạt động, sử dụng các sự kiện Vòng đời của Doctrine có thể là một giải pháp tốt hơn.
Bằng cách tận dụng prePersist
Sự kiện Vòng đời, bạn có thể chỉ đặt giá trị mặc định cho thực thể của mình trong lần duy trì ban đầu.
hack
. Không bao giờ dựa vào hack.
Hãy cẩn thận khi đặt giá trị mặc định trên định nghĩa thuộc tính! Làm điều đó trong constructor thay vào đó, để giữ cho nó không có vấn đề. Nếu bạn định nghĩa nó trên định nghĩa thuộc tính, sau đó duy trì đối tượng vào cơ sở dữ liệu, sau đó thực hiện tải một phần, sau đó các thuộc tính không được tải sẽ lại có giá trị mặc định. Điều đó là nguy hiểm nếu bạn muốn tiếp tục đối tượng một lần nữa.