当我在Symfony2项目中工作时,一个奇怪的bug野蛮地出现了(再次)。
我创建了一个包含dateCreated
属性和其他一些属性的实体Check
,这样我就可以将Check
链接到扩展ProductBase
的不同实体。以下是Check
和AProduct
:的样本
/**
* Check
*
* @ORMTable(name="check")
* @ORMEntity
*/
class Check
{
/**
* @var integer
*
* @ORMColumn(name="id", type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var DateTime
*
* @ORMColumn(name="date_created", type="datetime")
*/
private $dateCreated;
[...]
/**
* @ORMManyToOne(targetEntity="AcmeBlogBundleEntityAProduct", inversedBy="checks")
* @ORMJoinColumn(name="aproduct_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $aproduct;
[...]
}
/**
* AProduct
*
* @ORMTable(name="aproduct")
* @ORMEntity
*/
class AProduct extends ProductBase
{
[...]
/**
* @ORMOneToMany(targetEntity="AcmeBlogBundleEntityCheck", mappedBy="product")
* @ORMOrderBy({"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
正在显示正确的日期。。。
我看到您正在使用:
@ORMOrderBy({"dateCreated" = "DESC"})
可能很傻,但请检查返回的check实例的id。
我终于发现了我的问题,我在这里的帖子真的很愚蠢,与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'));
正在更改Checks
的dateCreated
属性的存储值。我不明白为什么它会影响它,因为我没有直接处理Check
实例。
解决此问题的快速方法是在添加DateInterval
:之前显式克隆DateTime
实例
$date = clone $date;
但我会在Check
或AProduct
实体中添加一个新字段来存储过期日期,而不是在每次更新时计算它。
更新:
我读到PHP将对象和数组作为引用而不是值传递。这就是我在这里遇到问题的原因。我不知道PHP是这样的。以后我会更加小心的!