2013-12-20 135 views
0

当我在处理我的Symfony2项目时,(又一次)出现了一个奇怪的bug。Symfony2/Doctrine2 - 从数据库获取日期时间时的问题

我创建含有dateCreated属性的实体Check和一些其他属性,以便我可以链接Check到被延伸的ProductBase不同的实体。下面是Check样品和AProduct

/** 
* Check 
* 
* @ORM\Table(name="check") 
* @ORM\Entity 
*/ 
class Check 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var \DateTime 
    * 
    * @ORM\Column(name="date_created", type="datetime") 
    */ 
    private $dateCreated; 
    [...] 


/** 
* @ORM\ManyToOne(targetEntity="Acme\BlogBundle\Entity\AProduct", inversedBy="checks") 
* @ORM\JoinColumn(name="aproduct_id", referencedColumnName="id", onDelete="CASCADE") 
*/ 
protected $aproduct; 
    [...] 
} 


/** 
* AProduct 
* 
* @ORM\Table(name="aproduct") 
* @ORM\Entity 
*/ 
class AProduct extends ProductBase 
{ 
    [...] 


    /** 
    * @ORM\OneToMany(targetEntity="Acme\BlogBundle\Entity\Check", mappedBy="product") 
    * @ORM\OrderBy({"dateCreated" = "DESC"}) 
    */ 
    protected $checks; 
    [...] 
} 

所以我的问题是,当我试图下面显示在我的控制器之一dateCreated属性,看代码,Symfony2的(或Doctrine2)被加入整整一个月存储在数据库中的日期,我不知道为什么它的发生:

[...] 
$aproduct = $aproducts[0]; 
$checks = $aproduct->getChecks(); 
$lastCheck = $checks->toArray()[0]; //I know it's not 'safe' but it's shorter to expose my problem 
var_dump($lastCheck->getDateCreated()); 

结果:

object(DateTime)[854] 
    public 'date' => string '2014-01-20 16:21:41' (length=19) 
    public 'timezone_type' => int 3 
    public 'timezone' => string 'UTC' (length=3) 

价值存储在数据库:

2013-12-20 16:21:41 

我不明白最重要的是,在另一个控制器,具有完全相同的方法,但在不同的产品(BProduct例如),我得到正确的日期... 有没有人已经面对这个问题,或者有什么线索来解决它?

再次感谢您。如果您需要更多的信息,只需询问,我会尽可能提供帮助。

编辑:存储在aproducts其余aproduct都显示正确的日期......

+0

您是否使用了此处建议的自定义日期时间类型? http://docs.doctrine-project.org/en/2.0.x/cookbook/working-with-datetime.html#handling-different-timezones-with-the-datetime-type – YRM

+0

@YRM为什么时区会影响DateTime整整一个月? – sjagr

+0

我会打印 - 调试发生在Doctrine \ DBAL \ Types \ DateTimeType :: convertToPHPValue()中,问题可能出现在您自己的代码中。 –

回答

0

嗯,我终于发现我的问题,我的帖子真的很无聊,完全与Symfony或Doctrine无关,对此感到抱歉。 我在显示他们之前对我的aproduct检查的最后一个实例执行了一些“测试”,这些“测试”影响dateCreated值。 下面是我在做什么:

public static function updateAProductStatus(AProduct $product){ 
    if(($check = $product->getChecks()->first()) instanceof Check){ 
     $date = $check->getDateCreated(); 
     $expiracyDate = $date->add(new \DateInterval('P1M')); //this line is the problem 
     $status = self::getStatus($expiracyDate); //this is only returning 'expired', 'expiring' or 'good' based on the difference between today's date and dateCreated + 1 month 
    } else { 
     $status = 'expired'; 
    } 
    return $status; 
} 

所以,写在代码中,$date->add(new \DateInterval('P1M'));正在改变ChecksdateCreated属性的存储值。我不明白为什么它会影响它,因为我不直接在Check实例上工作。

快速的方法来解决这个问题是要增加一个DateInterval之前明确克隆DateTime实例:

$date = clone $date; 

但我会在我的CheckAProduct实体添加一个新字段来存储expiracy日期,而不是计算它在每一次更新。

更新:

我读PHP通过对象和数组作为参考,而不是作为值。这就是为什么我在这里遇到问题。我不知道PHP是这样的。那么我将在未来更加小心!

0

我看你使用:

@ORM\OrderBy({"dateCreated" = "DESC"}) 

可能是愚蠢的,但检查返回检查实例的ID。

+0

这不是愚蠢的。但是'Check'实例的ID是很好的。 – Ianlet

+0

好的。 ProductBase.php中有一些重要的代码吗?你在__construct中放置了'$ this-> checks = new ArrayCollection()'吗? – Zeljko

+0

此行存在。 'ProductBase'中没有重要的代码,只有基本的getter和setters ...没有其他代码与这些实体中的检查进行交互...明天,我将继续到处寻找可能发现这个问题来自哪里。谢谢大家试图帮助我 – Ianlet