Wie setze ich in Lehre 2 einen Standardwert?
Wie setze ich in Lehre 2 einen Standardwert?
Antworten:
Datenbankstandardwerte werden nicht "portabel" unterstützt. Die Standardmethode für Datenbankwerte kann nur über das columnDefinition
Zuordnungsattribut verwendet werden, in dem Sie das SQL
Snippet ( DEFAULT
einschließlich Ursache) für die Spalte angeben, der das Feld zugeordnet ist.
Sie können verwenden:
<?php
/**
* @Entity
*/
class myEntity {
/**
* @var string
*
* @Column(name="myColumn", type="string", length="50")
*/
private $myColumn = 'myDefaultValue';
...
}
Standardwerte auf PHP-Ebene werden bevorzugt, da diese auch für neu erstellte und persistierte Objekte ordnungsgemäß verfügbar sind (Doctrine kehrt nach dem Persistieren eines neuen Objekts nicht zur Datenbank zurück, um die Standardwerte zu erhalten).
<?php
/**
* @Entity
*/
class myEntity {
/**
* @var string
*
* @ORM\Column(name="myColumn", type="integer", options={"default" : 0})
*/
private $myColumn;
...
}
Beachten Sie, dass hierfür SQL verwendet wird DEFAULT
, das für einige Felder wie BLOB
und nicht unterstützt wird TEXT
.
options={"default": 0}
Achten Sie darauf, "und nicht" zu verwenden, da dies Fehler in meiner Version der Doktrin verursacht.
Richten Sie einen Konstruktor in Ihrer Entität ein und legen Sie dort den Standardwert fest.
Verwenden:
options={"default":"foo bar"}
und nicht:
options={"default"="foo bar"}
Zum Beispiel:
/**
* @ORM\Column(name="foo", type="smallint", options={"default":0})
*/
private $foo
Ein weiterer Grund, warum das Lesen der Dokumentation zu Symfony niemals aus dem Trend geraten wird. Für meinen speziellen Fall gibt es eine einfache Lösung, bei der die field type
Option empty_data
auf einen Standardwert gesetzt wird.
Auch diese Lösung gilt nur für das Szenario, in dem eine leere Eingabe in einem Formular das DB-Feld auf null setzt.
Keine der vorherigen Antworten hat mir bei meinem speziellen Szenario geholfen, aber ich habe eine Lösung gefunden.
Ich hatte ein Formularfeld, das sich wie folgt verhalten musste:
Ich habe dann alle hier gegebenen Empfehlungen ausprobiert. Lassen Sie mich sie auflisten:
<?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';
}
...
}
Nichts davon hat funktioniert und alles aufgrund der Verwendung Ihrer Entity-Klasse durch Symfony.
Symfony-Formularfelder überschreiben die in der Entitätsklasse festgelegten Standardwerte.
Das bedeutet, dass in Ihrem Schema für Ihre Datenbank ein Standardwert definiert sein kann. Wenn Sie jedoch beim Senden Ihres Formulars ein nicht erforderliches Feld leer lassen, überschreibt die Methode form->handleRequest()
in Ihrer form->isValid()
Methode diese Standardwerte in Ihrer Entity
Klasse und setzt sie auf die Eingabefeldwerte. Wenn die Eingabefeldwerte leer sind, wird die Entity
Eigenschaft auf festgelegt null
.
http://symfony.com/doc/current/book/forms.html#handling-form-submissions
Stellen Sie den Standardwert auf Ihrem Controller nach form->handleRequest()
Ihrer form->isValid()
Methode ein:
...
if ($myEntity->getMyColumn() === null) {
$myEntity->setMyColumn('myDefaultValue');
}
...
Keine schöne Lösung, aber es funktioniert. Ich könnte wahrscheinlich ein machen , validation group
aber es kann sein , Menschen , die dieses Problem als siehe Datentransformation statt Datenvalidierung , ich überlasse es Ihnen zu entscheiden.
Ich habe auch versucht, den Entity
Setter folgendermaßen zu überschreiben :
...
/**
* Set myColumn
*
* @param string $myColumn
*
* @return myEntity
*/
public function setMyColumn($myColumn)
{
$this->myColumn = ($myColumn === null || $myColumn === '') ? 'myDefaultValue' : $myColumn;
return $this;
}
...
Dies funktioniert nicht , obwohl es sauberer aussieht . Der Grund dafür ist, dass die böse form->handleRequest()
Methode nicht die Setter-Methoden des Modells verwendet, um die Daten zu aktualisieren (siehe form->setData()
für weitere Details).
Die Problemumgehung, die ich verwendet habe, war a LifeCycleCallback
. Ich warte immer noch darauf, ob es zum Beispiel mehr "native" Methoden gibt @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()); }
Sie können dies auch mit XML tun:
<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>
So habe ich es für mich gelöst. Unten finden Sie ein Entitätsbeispiel mit dem Standardwert für MySQL. Dies erfordert jedoch auch die Einrichtung eines Konstruktors in Ihrer Entität und das Festlegen des Standardwerts dort.
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
geht direkt gegen den Zweck eines ORM, der Abstraktion von der Datenbank ist. Diese Lösung beeinträchtigt die Portabilität, hält Ihre Software von Ihrem DB-Anbieter abhängig und beeinträchtigt auch die Tools von Doctrine Migrations.
Funktioniert für mich auch in einer MySQL-Datenbank:
Entity\Entity_name:
type: entity
table: table_name
fields:
field_name:
type: integer
nullable: true
options:
default: 1
Nichts davon hat bei mir funktioniert. Ich habe auf der Website der Doktrin eine Dokumentation gefunden, die besagt, dass der Wert direkt festgelegt werden soll, um einen Standardwert festzulegen.
private $default = 0;
Dies fügte den Wert ein, den ich wollte.
Hinzufügen zu @romanb brillante Antwort.
Dies erhöht den Aufwand bei der Migration geringfügig, da Sie offensichtlich kein Feld ohne Null-Einschränkung und ohne Standardwert erstellen können.
// 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");
Mit dieser Antwort ermutige ich Sie zu überlegen, warum Sie überhaupt den Standardwert in der Datenbank benötigen. Und normalerweise ist es möglich, das Erstellen von Objekten ohne Null-Einschränkung zu ermöglichen.
Wenn Sie die Yaml-Definition für Ihre Entität verwenden, funktioniert Folgendes für mich in einer Postgresql-Datenbank:
Entity\Entity_name:
type: entity
table: table_name
fields:
field_name:
type: boolean
nullable: false
options:
default: false
$entity->setFieldName()
vor dem Spülen nicht verwendet haben? Doctrine scheint den Standardwert bei null zu definieren. Die einzige Lösung in yaml besteht darin, den Standardwert IN der Entitätsklasse zu definieren, der mir dumm erscheint, da er bereits in yaml definiert ist ... -_-
Ich hatte mit dem gleichen Problem zu kämpfen. Ich wollte den Standardwert aus der Datenbank in die Entitäten (automatisch) haben. Ratet mal, ich habe es geschafft :)
<?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";
Während das Festlegen des Werts im Konstruktor funktionieren würde, könnte die Verwendung der Doctrine Lifecycle-Ereignisse eine bessere Lösung sein.
Durch die Nutzung des prePersist
Lifecycle-Ereignisses können Sie Ihren Standardwert für Ihre Entität nur beim anfänglichen Fortbestehen festlegen.
hack
. Verlassen Sie sich niemals auf Hacks.
Seien Sie vorsichtig, wenn Sie Standardwerte für die Eigenschaftsdefinition festlegen! Tun Sie es stattdessen im Konstruktor, um es problemlos zu halten. Wenn Sie es in der Eigenschaftsdefinition definieren, das Objekt in der Datenbank beibehalten und dann teilweise laden, haben nicht geladene Eigenschaften wieder den Standardwert. Das ist gefährlich, wenn Sie das Objekt erneut beibehalten möchten.