php - 如何强制 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);
    })->orderBy('launch_order_id','DESC')->first();
}

这个函数简单地通过以下方式调用:

Mission::LastFromLaunchSite('someSite');

如果结果中至少有一行,此查询完全可以工作,但一旦没有,它就会返回一个非常冗长的 Builder 对象,该对象充满了递归,这实际上使我的崩溃浏览器。

我的问题是...

我如何才能检测到这一点并简单地返回类似 false“No results were found.”的内容。

我试过的...

我已经尝试使用 firstOrFail() 方法代替 first(),但这只会返回一个 ModelNotFoundException,这给了我两种解决方案:

  1. global.php 中用 App:error 处理它。这是不可取的,因为没有返回结果不是错误。只是众多可能结果中的一种。

  2. 捕获每个方法中的异常,这会导致代码重复。我实际上也无法让它工作。我尝试使用 ModelNotFoundException 类并捕获它,但它从未被捕获:

    use Illuminate\Database\Eloquent\ModelNotFoundException;
    
    // ...
    
    try {
        //my query
    } catch (Illuminate\Database\Eloquent\ModelNotFoundException $e) {
        return false;
    }
    
    // otherwise, return as normal
    

当对我的模型的查询未返回任何结果时,我如何简单地返回 false 或一些错误的值,而不是简单地打印出这个非常冗长的错误?

最佳答案

这里的问题是您没有像 Laravel 预期的那样使用作用域。 Laravel 实际上并不期望您实际在范围内执行查询。它更像是一个应用过滤器的工具。因此,当您的范围函数返回 NULL(或任何虚假值)时,Laravel 无论如何都会返回当前的 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。使用异常(但在你的 Controller 中)

我不太喜欢这样,但这是一种可能性。使用 firstOrFail 并在您的 Controller 中执行此操作:

try {
    $result = Mission::LastFromLaunchSite('someSite');
} catch (Illuminate\Database\Eloquent\ModelNotFoundException $e){
    $result = null;
}

2。正确使用范围

不要在范围内执行查询,而是在您的 Controller 中执行:

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');

关于php - 如何强制 Laravel Eloquent 很好地处理不返回任何结果的查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28122576/

相关文章:

php - symfony 形式的另一个日期之后的日期

MySQL - 从列重复的表中删除行

mysql - 在 Rails 中获得一个随机的、未投票的帖子

C++ 异常代码查找

WPF - DispatcherUnhandledException 似乎不起作用

php - 是否可以重定向发布数据?

php - 通过 id 检查 session 是否存在,而不更新 session 的生命周期

php - where 和 while 循环似乎不起作用

mysql - 使用 JDBC 抓取 mysql 查询并将其发送到 elasticsearch

Android NDK - 尝试用 NoMemoryError 捕获