如何强制 Laravel Eloquent 很好地处理 returns 没有结果的查询?
How to force Laravel Eloquent to play nicely with a query which returns no results?
我在我的一个模型中将数据库查询设置为范围查询,在某些情况下可能 returned 没有结果,这样做完全没问题:
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');
如果结果中至少有一行,此查询完全正常,但一旦有 none,它 return非常冗长的 Builder 对象,其中充满了递归,这实际上会使我的浏览器崩溃。
我的问题是...
我怎样才能检测到这一点,只需 return 类似 false
或 "No results were found."
的东西?
我试过的...
我试过使用 firstOrFail()
方法代替 first()
,但这只是 return 一个 ModelNotFoundException
,这给了我两个解决方案:
用App:error
在global.php
处理。这是不可取的,因为没有 returned 结果不是错误。只是众多可能结果中的一种。
在每个方法中捕获异常,导致代码重复。我实际上也无法让它工作。我尝试 using
ModelNotFoundException
class 并捕获它,但它从未被捕获:
use Illuminate\Database\Eloquent\ModelNotFoundException;
// ...
try {
//my query
} catch (Illuminate\Database\Eloquent\ModelNotFoundException $e) {
return false;
}
// otherwise, return as normal
当对我的模型 return 的查询没有结果时,我如何简单地 return 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 实际上并不期望您实际在范围内执行查询。它更像是一个应用过滤器的工具。因此,当您的作用域函数 returns NULL
(或任何虚假值)Laravel 无论如何都会 return 当前的 Builder 对象:
Illuminate\Database\Eloquent\Builder
protected function callScope($scope, $parameters)
{
array_unshift($parameters, $this);
return call_user_func_array(array($this->model, $scope), $parameters) ?: $this;
}
以下是三种解决方案:
1。使用异常(但在你的控制器中)
我不太喜欢这样,但这是一种可能性。使用 firstOrFail
并在您的控制器中执行此操作:
try {
$result = Mission::LastFromLaunchSite('someSite');
} catch (Illuminate\Database\Eloquent\ModelNotFoundException $e){
$result = null;
}
2。使用正确的范围
不要在范围内执行查询,而是在您的控制器中执行:
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();
3。只需向您的模型添加一个具有相同功能的普通函数
public static function LastFromLaunchSite($site){
return $query->whereComplete()->whereHas('launchSite', function($q) use($site) {
$q->where('name',$site);
})->orderBy('launch_order_id','DESC')->first();
}
用法:
Mission::LastFromLaunchSite('someSite');
作用域不应该 return 查询结果,这就是为什么你会得到无休止的递归或其他错误,具体取决于你的代码。
将范围更改为:
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!';
说明:范围不需要 return 值。如果 scopeWhatevermethod returns anything that evaluates to
true`,那么它将替换基本查询,否则查询本身是 returned。也就是说,如果您希望 return 编辑单个模型,但没有行匹配条件,那么您会意外地得到查询对象。
你也可以这样做(我不会,但它也会起作用):
public function scopeLastFromLaunchSite($query, $site) {
$row = $query->whereComplete()->whereHas('launchSite', function($q) use($site) {
$q->where('name',$site);
})->orderBy('launch_order_id','DESC')->first();
return $row ?: 'nothing found!';
}
但是您需要执行 Model
或 string
并相应地调整您的代码以避免可能的 Trying to get property of non-object
错误。
我在我的一个模型中将数据库查询设置为范围查询,在某些情况下可能 returned 没有结果,这样做完全没问题:
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');
如果结果中至少有一行,此查询完全正常,但一旦有 none,它 return非常冗长的 Builder 对象,其中充满了递归,这实际上会使我的浏览器崩溃。
我的问题是...
我怎样才能检测到这一点,只需 return 类似 false
或 "No results were found."
的东西?
我试过的...
我试过使用 firstOrFail()
方法代替 first()
,但这只是 return 一个 ModelNotFoundException
,这给了我两个解决方案:
用
App:error
在global.php
处理。这是不可取的,因为没有 returned 结果不是错误。只是众多可能结果中的一种。在每个方法中捕获异常,导致代码重复。我实际上也无法让它工作。我尝试
using
ModelNotFoundException
class 并捕获它,但它从未被捕获:use Illuminate\Database\Eloquent\ModelNotFoundException; // ... try { //my query } catch (Illuminate\Database\Eloquent\ModelNotFoundException $e) { return false; } // otherwise, return as normal
当对我的模型 return 的查询没有结果时,我如何简单地 return 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 实际上并不期望您实际在范围内执行查询。它更像是一个应用过滤器的工具。因此,当您的作用域函数 returns NULL
(或任何虚假值)Laravel 无论如何都会 return 当前的 Builder 对象:
Illuminate\Database\Eloquent\Builder
protected function callScope($scope, $parameters)
{
array_unshift($parameters, $this);
return call_user_func_array(array($this->model, $scope), $parameters) ?: $this;
}
以下是三种解决方案:
1。使用异常(但在你的控制器中)
我不太喜欢这样,但这是一种可能性。使用 firstOrFail
并在您的控制器中执行此操作:
try {
$result = Mission::LastFromLaunchSite('someSite');
} catch (Illuminate\Database\Eloquent\ModelNotFoundException $e){
$result = null;
}
2。使用正确的范围
不要在范围内执行查询,而是在您的控制器中执行:
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();
3。只需向您的模型添加一个具有相同功能的普通函数
public static function LastFromLaunchSite($site){
return $query->whereComplete()->whereHas('launchSite', function($q) use($site) {
$q->where('name',$site);
})->orderBy('launch_order_id','DESC')->first();
}
用法:
Mission::LastFromLaunchSite('someSite');
作用域不应该 return 查询结果,这就是为什么你会得到无休止的递归或其他错误,具体取决于你的代码。
将范围更改为:
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!';
说明:范围不需要 return 值。如果 scopeWhatevermethod returns anything that evaluates to
true`,那么它将替换基本查询,否则查询本身是 returned。也就是说,如果您希望 return 编辑单个模型,但没有行匹配条件,那么您会意外地得到查询对象。
你也可以这样做(我不会,但它也会起作用):
public function scopeLastFromLaunchSite($query, $site) {
$row = $query->whereComplete()->whereHas('launchSite', function($q) use($site) {
$q->where('name',$site);
})->orderBy('launch_order_id','DESC')->first();
return $row ?: 'nothing found!';
}
但是您需要执行 Model
或 string
并相应地调整您的代码以避免可能的 Trying to get property of non-object
错误。