我的数据库中有一个名为tallies
的表,用于跟踪特定实体的count
。表中的两个关键字段是:
现在我在表格中有两条记录,第一个记录的类型为hardDrives
,第二个的类型为{{1} }。
我的存储库中有一个方法用于递增monitors
表中特定记录的计数:
tallies
当我发送请求以递增public function decreaseCountBy($type, $number){
$countCollection = $this->tally->where('type', '=', $type )->firstOrFail();
$record = $countCollection->first();
// Troubleshooting output
die(var_dump([$type, $record->toArray()]));
// The rest of the method
$record->count -= $number;
$result = $record->save();
if(!$result){
throw new \Exception('Error saving decrementation');
}
return $record->count;
}
并查看故障排除模具的输出并在此方法中转储并获得以下输出:
monitors
即使我在查询中使用array (size=2)
0 => string 'monitors' (length=8)
1 =>
array (size=5)
'id' => int 4
'type' => string 'hardDrives' (length=10)
'count' => int 15
'created_at' => string '2014-12-21 03:50:04' (length=19)
'updated_at' => string '2014-12-21 14:35:28' (length=19)
作为monitors
的值,我也会获得$type
的记录。
在此之后,我尝试更改方法以触发查询:
hardDrives
然后我得到了正确的结果:
$countCollection = $this->tally->where('type', $type )->get();
如果找到记录时出错,我可以在这里停止添加我自己的异常抛出,但是当我读取API Documentation的Builder类'方法array (size=2)
0 => string 'monitors' (length=8)
1 =>
array (size=5)
'id' => int 5
'type' => string 'monitors' (length=8)
'count' => int 3
'created_at' => string '2014-12-21 03:50:04' (length=19)
'updated_at' => string '2014-12-21 03:50:04' (length=19)
时(对不起,我不能直接链接到它),该方法描述为:
执行查询并获取第一个结果或抛出异常。
我想使用内置的Laravel Exception,当找不到记录而不是使用我自己的记录时会抛出它。
这里有什么我想念的吗?当我在laravel Eloquent文档中查找其他示例时,看起来我正在构建查询。
最重要的是,我想知道为什么它失败而不只是一个解决方案。
解决
这是该方法的最终版本,只是为了向大家展示它是如何结束的:
firstOrFail()
通常,当您执行public function decreaseCountBy($type, $number){
$record = $this->tally->where('type', '=', $type )->firstOrFail();
$record->count -= $number;
$result = $record->save();
if(!$result){
throw new \Exception('Error saving decrementation');
}
return $record->count;
}
检索数据时,结果是一个包含多个记录的雄辩->get();
实例。从那里,如果您只想检索第一条记录,可以使用Collection类的Collection
方法获取具有该记录信息的雄辩->first()
类实例。
对于Model
,您告诉查询构建器的是您只需要找到第一条记录。因为您只会收到一条记录的数据,所以eloquent会跳过该集合并返回一个模型实例。
在上面的代码中,我删除了“抓取第一条记录的模型”的行,即firstOrFail()
,并重命名变量以更好地符合预期结果,即$record = $countCollection->first();
到位$record
。
答案 0 :(得分:1)
在您调用first()
后,无需致电firstOrFail()
。 firstOrFail()已经返回单个模型而不是集合,并且在模型上调用first()
会触发一个全新的select语句(这次没有where
)
正如@Jarek Tkaczyk在下面指出的那样,使用您的代码,将对数据库运行两个查询
select * from tallies where type = ?
select * from tallies
这意味着在您的情况下,第一个查询的结果会被第二个查询覆盖。
firstOrFail()
只会调用first()
,然后在first()
返回null
时抛出异常
public function firstOrFail($columns = array('*'))
{
if ( ! is_null($model = $this->first($columns))) return $model;
throw (new ModelNotFoundException)->setModel(get_class($this->model));
}