2013-03-19 5 views
6

È possibile utilizzare il valore 0 anziché null per le relazioni (many-to-one, one-to-one) con Doctrine 2?Doctrine 2: Usa valori 0 predefiniti invece di null per la relazione

Ora ho un sacco di colonne NOT NULL che non posso passare a valori null. Cambiando il valore predefinito in MySQL a 0 esso non è la soluzione perché la docenza definisce sempre la colonna per l'inserimento/aggiornamento delle righe.

risposta

8

No, questo non è possibile.

NULL ha un significato molto specifico in SQL. Esso rappresenta "nessun valore", e si può verificare che la logica non funziona anche a livello di SQL:

CREATE TABLE foo (
    `id` INT(11) PRIMARY KEY AUTO_INCREMENT, 
    `bar_id` INT(11) 
); 

CREATE TABLE `bar` (`id` INT(11) PRIMARY KEY AUTO_INCREMENT); 

ALTER TABLE foo ADD FOREIGN KEY `bar_id_fk` (`bar_id`) REFERENCES `bar` (`id`); 

INSERT INTO `bar` VALUES (NULL); 
INSERT INTO `bar` VALUES (NULL); 
INSERT INTO `bar` VALUES (NULL); 
INSERT INTO `foo` VALUES (NULL, 1); 
INSERT INTO `foo` VALUES (NULL, 2); 
INSERT INTO `foo` VALUES (NULL, 3); 
INSERT INTO `foo` VALUES (NULL, 0); 

/* 
    ERROR 1452 (23000): 
     Cannot add or update a child row: a foreign key constraint fails 
     (`t2`.`foo`, CONSTRAINT `foo_ibfk_1` FOREIGN KEY (`bar_id`) 
     REFERENCES `bar` (`id`)) 
*/ 

INSERT INTO `foo` VALUES (NULL, 4); 

/* 
    ERROR 1452 (23000): 
     Cannot add or update a child row: a foreign key constraint fails 
     (`t2`.`foo`, CONSTRAINT `foo_ibfk_1` FOREIGN KEY (`bar_id`) 
     REFERENCES `bar` (`id`)) 
*/ 

INSERT INTO `foo` VALUES (NULL, NULL); /* VALID! */ 

Quindi no, non si può avere Dottrina ORM si comportano in modo che 0 viene interpretato come NULL, dal momento che non è consentito dallo stesso RDBMS.

Che cosa si può fare è l'inserimento di "falsi" voci di riferimento nel DB, che poi agire come null object quando idratata come entità:

INSERT INTO `bar` VALUES (NULL); 
UPDATE `bar` SET `id` = 0 WHERE `id` = 4; 

INSERT INTO `foo` VALUES (NULL, 0); /* now works! */ 

In termini di entità, sembra abbastanza simile.

(. Si prega di notare che public proprietà vengono supportati solo da ORM Doctrine 2.4, che non è ancora stato rilasciato Fanno le cose più facili da leggere qui, però)

Foo.php:

use Doctrine\ORM\Mapping as ORM; 

/** 
* @ORM\Entity() 
* @ORM\Table(name="foo") 
*/ 
class Foo 
{ 
    /** 
    * @ORM\Column(type="integer") 
    * @ORM\Id() 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    public $id; 

    /** 
    * @ORM\ManyToOne(targetEntity="Bar") 
    * @ORM\JoinColumn(name="bar_id", referencedColumnName="id", nullable=false) 
    */ 
    public $bar; 
} 

Bar .php:

use Doctrine\ORM\Mapping as ORM; 

/** 
* @ORM\Entity() 
* @ORM\Table(name="bar") 
*/ 
class Bar 
{ 
    /** 
    * @ORM\Column(type="integer") 
    * @ORM\Id() 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    public $id; 
} 

E poi il codice per produrre una nuova istanza Foo:

$nullBar = $entityManager->find('Bar', 0); 
$foo  = new Foo(); 
$foo->bar = $nullBar; 

$em->persist($foo); 
$em->flush(); 
+0

Nessun rancore, mi piace essere corretto :) – Sam

+1

Grazie per la risposta corretta e chiara. –

+0

So che è male, ma abbiamo appena usato un evento 'postLoad' per impostare zero valori di fk su' null'. Sembra funzionare. vedere la risposta qui sotto per il codice. – Florian