Php firstOrFail从雄辩的查询生成器返回错误的记录
我的数据库中有一个名为Php firstOrFail从雄辩的查询生成器返回错误的记录,php,laravel,laravel-4,eloquent,Php,Laravel,Laravel 4,Eloquent,我的数据库中有一个名为计数的表,用于跟踪特定实体的计数。表中的两个关键字段是: 类型:实体的名称 计数:实体的计数 现在在表中我有两条记录,第一条记录的类型为硬盘驱动器,第二条记录的类型为监视器 我的存储库中有一种方法,用于增加计数表中特定记录的计数: public function decreaseCountBy($type, $number){ $countCollection = $this->tally->where('type', '=', $type )-&
计数
的表,用于跟踪特定实体的计数。表中的两个关键字段是:
- 类型:实体的名称
- 计数:实体的计数
现在在表中我有两条记录,第一条记录的类型为硬盘驱动器
,第二条记录的类型为监视器
我的存储库中有一种方法,用于增加计数表中特定记录的计数:
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;
}
当我向increment监视器发送请求时,用此方法查看故障排除模具和转储的输出,并获得以下输出:
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)
即使我使用监视器
作为查询中$type
的值,我也会得到硬盘驱动器
的记录
在此之后,我尝试更改方法以触发查询:
$countCollection = $this->tally->where('type', $type )->get();
然后我得到了正确的结果:
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)
如果查找记录时出错,我可以在这里停止并添加我自己的异常抛出,但是当我阅读构建器类的“methodfirstOrFail()
(很抱歉,我无法直接链接到它)时,该方法描述为:
执行查询并获得第一个结果或引发异常
我想使用内置的Laravel异常,当找不到记录时会抛出该异常,而不是使用我自己的异常
这里有我遗漏的东西吗?当我在laravel文档中查找其他示例时,看起来我正确地构建了查询
最重要的是,我想知道为什么它会失败,而不仅仅是一个变通办法
分辨率
以下是该方法的最终版本,旨在向所有人展示其最终结果:
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类的->first()
方法获得一个具有该记录信息的雄辩的模型
类实例
在firstOrFail()
的情况下,您要告诉查询生成器的是,您只需要找到第一条记录。因为您只会收到一条记录的数据,所以eloquent跳过收集并返回一个模型实例
在上面的代码中,我删除了“获取第一条记录的模型”的行,即$record=$countCollection->first()
,并重命名变量以更好地适应预期结果,即用$record
代替$countCollection
在您已经调用了firstOrFail()
之后,无需调用first()
。firstOrFail()已返回单个模型而不是集合,对模型调用first()
将触发一个全新的select语句(这次没有where
)
正如@Jarek Tkaczyk在下面指出的,使用您的代码,将对DB运行两个查询
type=?
从盘点中选择*
这意味着在您的情况下,第一个查询的结果将被第二个查询覆盖
一些背景资料
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));
}
不确定这是否是导致问题的原因,但在使用firstOrFail()
后,您肯定不需要调用first()
firstOrFail()
已返回单个模型,而不是必须已返回的集合。当我从记录中删除first()
时,它工作了。这也是有道理的,如果我首先调用单个talls
model实例,就像说“嘿,给我找到的记录,然后给我表中的第一条记录”。如果你想提交答案,我会给你支票。好的。当然可以:)谢谢你提供的额外细节。这并不是说再次调用没有意义。实际上,它返回完全不同的结果。引擎盖下有两个db查询:select*from-tallises,其中type=?
然后对第一次查询返回的模型调用select*from-tallises
。@JarekTkaczyk Ooops你说得对。我忽略了model类中的\u调用
,该调用创建了一个新的查询,因此运行了一个新的select语句。我会相应地更新答案。谢谢你指出这一点。