2017-03-20 1 views
0

je l'entité suivante:doctrine stocke la valeur erronée dans le DB à partir d'un objet DateTime

use Doctrine\ORM\Mapping as ORM; 
use Gedmo\Timestampable\Traits\TimestampableEntity; 

/** 
* @ORM\Entity 
* @ORM\Table(name="quote") 
* @ORM\Entity(repositoryClass="QuoteBundle\Entity\Repository\QuoteRepository") 
*/ 
class Quote 
{ 
    use SourceTrait; 
    use TimestampableEntity; 

    /** 
    * @ORM\Id 
    * @ORM\Column(type="integer",unique=true,nullable=false) 
    * @ORM\GeneratedValue 
    */ 
    private $quoteId; 

    ... 

    /** 
    * @var \DateTime 
    * 
    * @ORM\Column(name="StartDate", type="datetime", nullable=true) 
    */ 
    private $startDate; 

    /** 
    * @var \DateTime 
    * 
    * @ORM\Column(name="EndDate", type="datetime", nullable=false) 
    */ 
    private $endDate; 

    ... 

    /** 
    * @return \DateTime 
    */ 
    public function getStartDate(): ?\DateTime 
    { 
     return $this->startDate; 
    } 

    /** 
    * @param \DateTime $startDate 
    */ 
    public function setStartDate(\DateTime $startDate) 
    { 
     $this->startDate = $startDate; 
    } 

    /** 
    * @return \DateTime 
    */ 
    public function getEndDate(): ?\DateTime 
    { 
     return $this->endDate; 
    } 

    /** 
    * @param \DateTime $endDate 
    */ 
    public function setEndDate(\DateTime $endDate) 
    { 
     $this->endDate = $endDate; 
    } 

    ... 
} 

et j'ai cette méthode dans la classe QuoteRepository:

/** 
* @param Agreement $agreement 
* 
* @return int 
*/ 
public function createQuoteHeader(Agreement $agreement): int 
{ 
    $em  = $this->getEntityManager(); 
    $QuoteID = $this->getNewQuoteId(); 
    $year = $agreement->getEndDate()->diff($agreement->getStartDate(), true)->y > 0 
     ? $agreement->getEndDate()->diff($agreement->getStartDate(), true)->y 
     : 0; 

    dump($year); 
    dump(gettype($year)); 
    dump($agreement->getEndDate()); 

    $entity = new Quote(); 
    ... 
    $entity->setStartDate($agreement->getEndDate()->modify('+1 day')); 
    dump($agreement->getStartDate()); 
    $entity->setEndDate($agreement->getEndDate()->modify("+1 day +{$year} year")); 
    dump($agreement->getEndDate()); 
    ... 

    $em->persist($entity); 
    $em->flush(); 

    return $entity->getQuoteId(); 
} 

La sortie du dump() ci-dessus sont comme suit (même ordre que dans le code):

0 
"integer" 
DateTime {#3005 
    +"date": "2017-03-21 00:00:00.000000" 
    +"timezone_type": 3 
    +"timezone": "UTC" 
} 
DateTime {#3004 
    +"date": "2016-03-22 00:00:00.000000" 
    +"timezone_type": 3 
    +"timezone": "UTC" 
} 
DateTime {#3005 
    +"date": "2017-03-23 00:00:00.000000" 
    +"timezone_type": 3 
    +"timezone": "UTC" 
} 

D'une certaine façon la w Les valeurs rong sont insérées dans DB:

enter image description here

Peut-être que je manque quelque chose, mais ne devrait pas être StartDate égal à 2016-03-22 00:00:00 ??

Répondre

2

Parcourons votre code ligne par ligne.

$entity->setStartDate($agreement->getEndDate()->modify('+1 day')); 

modify()mute l'objet DateTime il est appelé. Cette ligne a ajouté +1 jour à $agreement->getEndDate() ET le même DateHeure est passée à $entity->setStartDate(). Donc, à la fois $agreement->getEndDate() et $entity->getStartDate() reviendra 2017-03-22!

dump($agreement->getStartDate()); 

Vous avez sauvegardé la mauvaise date, d'où 2016-03-22, masquant l'erreur. Devrait être dump($entity->getStartDate()); et vous auriez remarqué.

$entity->setEndDate($agreement->getEndDate()->modify("+1 day +{$year} year")); 

Depuis $agreement->getEndDate() est maintenant égal à 22/03/2017, 1 jour 0 années se traduira par $entity->getEndDate() étant égale à 23/03/2017.

Je recommande d'utiliser DateTimeImmutable pour éviter tous ces problèmes inutiles avec les références d'objet.

1

Il semble que ce soit un problème avec l'objet que vous essayez de conserver. Vous obtenez le bon résultat lorsque vous faites dump(), mais l'objet datetime est en cours de modification, donc lorsque vous persistez, l'objet reçoit toutes les valeurs du dernier résultat datetime. Je vous recommande de faire "cloner" dans vos objets datetime, et de définir les valeurs séparément, quelque chose comme ceci:

$oDatetime1 = clone($agreement->getEndDate()); 
$oDatetime2 = clone($agreement->getEndDate()); 

$entity->setStartDate($oDatetime1->modify('+1 day')); 
$entity->setEndDate($oDatetime2->modify("+1 day +{$year} year"));