2013-03-19 18 views
6

Czy można używać wartości 0 zamiast wartości zerowej dla relacji (wiele do jednego, jeden do jednego) z Doctrine 2?Doctrine 2: Użyj wartości 0 zamiast wartości zerowej dla relacji

Teraz mam wiele kolumn NOT NULL, których nie mogę zmienić na wartości puste. Zmiana domyślnej wartości w MySQL na 0 nie jest rozwiązaniem, ponieważ doktryna zawsze ustawia kolumnę do wstawiania/aktualizowania wierszy.

Odpowiedz

8

Nie, nie jest to możliwe.

NULL ma bardzo konkretne znaczenie w SQL. To oznacza „bez wartości”, można sprawdzić, czy logika nie będzie działać nawet na poziomie 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! */ 

Więc nie, nie można mieć Doctrine ORM zachowywać się tak, że 0 jest interpretowany jako NULL, ponieważ to nie jest dozwolone przez sam RDBMS.

Co można zrobić jest wstawianie „fałszywe” odwołuje się wpisy w Twojej DB, który będzie następnie działać jako null object gdy uwodnione jako podmioty:

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

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

Pod względem jednostki, wygląda dość podobnie.

(. Proszę pamiętać, że public właściwości są obsługiwane tylko z Doctrine ORM 2.4, który nie został jeszcze wydany Robią rzeczy łatwiej przeczytać tutaj, choć)

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; 
} 

A potem kod produkować nowy Foo instancja:

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

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

Bez żadnych uczuć, lubię być poprawiany :) – Sam

+1

Dzięki za poprawną i jasną odpowiedź. –

+0

Wiem, że jest źle, ale po prostu użyliśmy zdarzenia 'postLoad', aby ustawić zero wartości fk na wartość' null'. Wydaje się działać. zobacz odpowiedź poniżej dla kodu. – Florian

Powiązane problemy