Php 如何迫使Laravel Elount很好地处理一个不返回结果的查询?
在我的一个模型中,我将一个数据库查询设置为作用域查询,在某些情况下可能不会返回任何结果,这样做完全可以:Php 如何迫使Laravel Elount很好地处理一个不返回结果的查询?,php,mysql,exception,laravel,eloquent,Php,Mysql,Exception,Laravel,Eloquent,在我的一个模型中,我将一个数据库查询设置为作用域查询,在某些情况下可能不会返回任何结果,这样做完全可以: public function scopeLastFromLaunchSite($query, $site) { return $query->whereComplete()->whereHas('launchSite', function($q) use($site) { $q->where('name',$site); })->or
public function scopeLastFromLaunchSite($query, $site) {
return $query->whereComplete()->whereHas('launchSite', function($q) use($site) {
$q->where('name',$site);
})->orderBy('launch_order_id','DESC')->first();
}
此函数仅通过以下方式调用:
Mission::LastFromLaunchSite('someSite');
如果结果中至少有一行,则此查询工作得非常好,但一旦没有一行,它就会返回一个非常长的生成器对象,其中充满了递归,这实际上会使我的浏览器崩溃
我的问题是。。。
我如何检测到这一点并简单地返回类似于false
或的内容“未找到任何结果”。
我试过的。。。
我尝试使用firstOrFail()
方法代替first()
,但这只会返回一个ModelNotFoundException
,它提供了两种解决方案:
App:error
在global.php
中处理它。这是不可取的,因为没有返回的结果不是错误。这只是众多可能结果之一使用ModelNotFoundException
类并捕获它,但它从未被捕获:
use Illuminate\Database\Eloquent\ModelNotFoundException;
// ...
try {
//my query
} catch (Illuminate\Database\Eloquent\ModelNotFoundException $e) {
return false;
}
// otherwise, return as normal
当对我的模型的查询没有返回结果时,我怎么能简单地返回
false
或某个假值,而不是简单地打印出这个非常长的错误?我从来没有做过这样的事情,但我首先想到的是这样的事情:
public function scopeLastFromLaunchSite($query, $site) {
$retVal = $query->whereComplete()->whereHas('launchSite', function($q) use($site) {
$q->where('name', $site);
})->orderBy('launch_order_id', 'DESC');
if ($retVal->count() > 0) {
return $retVal->first();
}
return "No results found";
}
这里的问题是,您没有像Laravel那样使用作用域。Laravel实际上并不期望您在范围内执行查询。它是一个应用过滤器的工具。因此,当作用域函数返回
NULL
(或任何falsy值)时,Laravel将只返回当前的生成器对象:
illumb\Database\elount\Builder
protected function callScope($scope, $parameters)
{
array_unshift($parameters, $this);
return call_user_func_array(array($this->model, $scope), $parameters) ?: $this;
}
以下是三种解决方案:
1.使用异常(但在控制器中)
我不太喜欢这个,但这是可能的。使用first或fail
并在控制器中执行此操作:
try {
$result = Mission::LastFromLaunchSite('someSite');
} catch (Illuminate\Database\Eloquent\ModelNotFoundException $e){
$result = null;
}
public function scopeLastFromLaunchSite($query, $site) {
return $query->whereComplete()->whereHas('launchSite', function($q) use($site) {
$q->where('name',$site);
})->orderBy('launch_order_id','DESC');
}
2.正确使用范围
不要在作用域中执行查询,而是在控制器中执行查询:
try {
$result = Mission::LastFromLaunchSite('someSite');
} catch (Illuminate\Database\Eloquent\ModelNotFoundException $e){
$result = null;
}
public function scopeLastFromLaunchSite($query, $site) {
return $query->whereComplete()->whereHas('launchSite', function($q) use($site) {
$q->where('name',$site);
})->orderBy('launch_order_id','DESC');
}
用法:
Mission::LastFromLaunchSite('someSite')->first();
Mission::LastFromLaunchSite('someSite');
3.只需在模型中添加一个普通函数即可
用法:
Mission::LastFromLaunchSite('someSite')->first();
Mission::LastFromLaunchSite('someSite');
作用域不应该返回查询结果,这就是为什么根据您的代码,您会得到永无止境的递归或其他错误 将范围更改为:
public function scopeLastFromLaunchSite($query, $site) {
$query->whereComplete()->whereHas('launchSite', function($q) use($site) {
$q->where('name',$site);
})->orderBy('launch_order_id','DESC');
}
然后就地执行:
$result = $yourQuery->lastFromLaunchSite($site)->first();
// then do whatever you need with the result
return ($result) ?: 'nothing found!';
说明:作用域不需要返回值。如果scopewhater
方法返回的值为
true`,则它将替换基本查询,否则将返回查询本身。也就是说,如果您希望返回单个模型,但没有行匹配条件,那么您会意外地得到查询对象
您可以这样做(我不会,但也可以):
但是,您需要体验
模型
或字符串
,并相应地调整代码,以避免可能的尝试获取非对象属性
错误。如何调用此函数?添加到问题中。您无需调用查询两次。只需检查结果的计算结果是否为true