所以我试图在Doctrine中坚持一个实体。我希望持久化的对象看起来像是从Symfony dump()函数中拉出来的:
Time {#7751 ▼
-id: 3
-timeIn: DateTime {#7749 ▶}
-timeOut: null
-rateId: Rate {#7761 ▼
-id: 1
-amount: "30.00"
-name: "Technical"
-projectId: Project {#7756 ▶}
-groupId: 1
}
-description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
-userId: 1
-status: "Unpaid"
-total: null
-cost: "60.00"
-projectId: Project {#7756 ▼
-id: 1
-name: "Acme Corp"
-description: "Metals Company"
-contactId: 1
-organizationId: 1
-groupId: 1
}
-groupId: 1
}
现在我显然不能坚持这个,因为我的ID中有相应的对象。例如:rateId,projectId等等。为了弥补这一点,在我的clockOut函数中,我运行检查以用它们的ID替换对象以进行存储。请参阅下面的clockOut函数:
public function clockOut($time, $group = null){
dump($time);
if(gettype($time) == "object"){
if(gettype($time->getProjectId())=='object'){
$time->setProjectId($time->getProjectId()->getId());
}
if(gettype($time->getRateId())=='object'){
$time->setRateId($time->getRateId()->getId());
}
$this->persistClockout($time);
}
elseif(gettype($time) == "string"){
if($group == null){
return false;
}else {
$time = $this->findData($group, $time);
$this->persistClockout($time);
}
}else {
return false;
}
}
还有一个相应的persistClockout函数可以处理实际的时钟输出和小时计算。虽然我认为这与我遇到的问题没有任何关系,但我还是会把它包括在内,因为它是相关的。
/**
* Persist time
*/
private function persistClockout($time, $group = null){
if($time->getTimeOut() == null){
$time->setTimeOut(new DateTime("Now"));
}
$this->hours = $this->hoursCalculate($time->getTimeIn(), $time->getTimeOut());
$time->setTotal($this->hours);
dump($time);
die();
$this->persist($time);
}
/**
* Get the amount of hours spent in decimal format.
*/
private function hoursCalculate($past, $present){
$diff = $present->diff($past);
$hours = round($diff->s / 3600 + $diff->i / 60 + $diff->h + $diff->days * 24, 2);
return $hours;
}
现在您可以看到我在命令结束之前运行dump()函数,然后它仍然存在,因为我一直在尝试自己诊断此问题。根据dump()函数,数据如下所示:
Time {#7751 ▼
-id: 3
-timeIn: DateTime {#7749 ▶}
-timeOut: DateTime {#11571 ▶}
-rateId: 1
-description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
-userId: 1
-status: "Unpaid"
-total: 187.83
-cost: "60.00"
-projectId: 1
-groupId: 1
}
大!这是预期的结果。但问题来自于我开始尝试对数据库进行实际持久化。
An exception occurred while executing 'UPDATE rate SET project_id = ? WHERE id = ? AND group_id = ?' with params [{}, 1, 1]:
Notice: Object of class ProjectBundle\Entity\Project could not be converted to int
虽然我在运行persist函数之前检查了数据,但似乎仍然认为projectId仍然是一个对象,即使我确保将其设置为实际的Id而不是对象,它也会忽略我。
我进一步研究了Symfony剖析器并找到了教条用来更新和查看细节的部分,看看projectId是一个对象吗?即使那不是我传入的内容?
任何人都不知道发生了什么事吗?对于罗嗦的帖子感到抱歉,我只是想告诉大家一些你正在使用的信息。请忽略代码中的dump()和die()函数,我一直在使用它们来尝试和诊断这个,但我很困惑。值得注意的是我已经尝试过像php bin / console cache这样的工厂运行:清除,并重新启动服务器。
提前谢谢堆栈溢出!
编辑:
以下是为 - > persist()列出的代码
public function persist($entity, bool $flush = true)
{
$this->manager->persist($entity);
if ($flush) {
$this->flush();
}
return $this;
}
UPDATE
我尝试运行persist然后单独刷新但是没有用。得到了同样的例外。我老实说这里的人不知所措。
我想你需要使用这段代码:
$this->flush($time);
而不是$this->persist($time);
我想到了。事实证明,这是一个问题,教条如何识别不同的数据和它认为是相同的。我认为这与效率或缓存或某些事情有关。
无论如何,让我告诉你我是如何得出这个结论的。
我得到的第一个提示是,虽然rateId最初是一个对象,后来被转换为它的相应ID,但它没有像ProjectId那样抛出错误。
其次,我更仔细地检查了dump()函数并发现了一些东西。 (我将重复使用原始帖子中的示例)
Time {#7751 ▼
-id: 3
-timeIn: DateTime {#7749 ▶}
-timeOut: null
-rateId: Rate {#7761 ▼
-id: 1
-amount: "30.00"
-name: "Technical"
-projectId: Project {#7756 ▶} <---- Right Here
-groupId: 1
}
-description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
-userId: 1
-status: "Unpaid"
-total: null
-cost: "60.00"
-projectId: Project {#7756 ▼ <---- Right Here
-id: 1
-name: "Acme Corp"
-description: "Metals Company"
-contactId: 1
-organizationId: 1
-groupId: 1
}
-groupId: 1
}
Project对象后面的数字是相同的。所以我想出了一个理论,即doctrine将原始引用存储在某个地方的projectId(object)中,然后使用它而不是我继续设置的值作为相应的ID(Int)。
因此,为了测试这个理论,我写了两个函数来“展平”我的对象,从对象树的末尾开始(因为它实际上应该只有3个嵌套对象)到开头。这样,所有引用都匹配,即使它们最终被“删除”。
/**
* Undo all object associations and convert them back into their original IDs.
* @param object $data
* @param array $callable
*/
public function flattenObject($data, $callable){
$sorter = new SortingHelper;
foreach($callable as $call){
$getMethod = 'get'.ucfirst($call).'Id';
$setMethod = 'set'.ucfirst($call).'Id';
if(method_exists($data, $getMethod)){
$found = $data->$getMethod();
if(gettype($found) == 'object'){
$result = $this->flatten($found, $callable);
$data->$setMethod($result);
}
}
}
return $data;
}
/**
* @param object $data
* @param array $callable
*/
private function flatten($data, $callable){
for($i = 0; $i != count($callable); $i++){
$getMethod = 'get'.ucfirst($callable[$i]).'Id';
$setMethod = 'set'.ucfirst($callable[$i]).'Id';
if(method_exists($data, $getMethod)){
$result = $data->$getMethod();
if(gettype($result) == 'object'){
$data->$setMethod($result->getId());
}
}
}
return $data->getId();
}
运行flattenObject()函数允许我将对象持久化到数据库中,因为对ID的引用不再是对象。
巴姆。超级恼人的问题解决了。
我希望这会以某种方式帮助将来的某个人。谢谢大家的贡献! :)