【问题标题】:Laravel ORM relationship returns error when value not present in DB当数据库中不存在值时,Laravel ORM 关系返回错误
【发布时间】:2015-05-21 09:30:23
【问题描述】:

我在查询关系时遇到问题。 我正在查询项目、公司和产品之间的关系。但是,只要数据库中不存在项目 ID,就会抛出致命异常:

在非对象上调用成员函数 Companies()

public function index($i) {
    return $this->returnTop($i, Array(
        'projectid' => 5,
        'products' => Array(1, 2, 3)
        )
    );
}

public function returnTop($count = 6, $args = Array()) {
    $companies = Project::find($args['projectid'])->companies()->whereHas('products', function($q) use($args) {
        $q->whereIn('products.id', $args['products']);
    })->with('products')->limit($count)->get();

    return Response::json($companies);
}

现在,我知道数据库中不存在项目 id 5,这很可能是导致此错误的原因,但我想返回一条消息而不是应用程序抛出致命错误....

有什么想法吗?

【问题讨论】:

    标签: laravel orm eloquent fatal-error


    【解决方案1】:

    只需检查find() 是否返回null。像这样的:

    $project = Project::find($args['projectid']);
    if(is_null($project)){
        return Response::json(['message' => 'Project not found']);
    }
    $companies = $project->companies()->whereHas('products', function($q) use($args) {
        $q->whereIn('products.id', $args['products']);
    })->with('products')->limit($count)->get();
    
    return Response::json($companies);
    

    另一种选择是findOrFail,它会抛出ModelNotFoundException。您可以全局处理异常或在控制器中捕获它:

    try {
    
        $companies = Project::findOrFail($args['projectid'])->companies()->whereHas('products', function($q) use($args) {
            $q->whereIn('products.id', $args['products']);
        })->with('products')->limit($count)->get();
    
        return Response::json($companies);
    
    } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e){
        return Response::json(['message' => 'Project not found']);
    }
    

    【讨论】:

    • 感谢您提供这些解决方案。我希望我可以投票,但我刚刚注册了一个帐户,我的声誉太低了..
    • 别担心,反正我有足够的网点;)
    • 使用异常方法,更简洁,我认为文档缺少放置此类代码的位置(如果你想让它成为全局),请在 /Exceptions/Handlers/Handler.php 内部方法 render() 中进行操作。 @lukasgeiter 你把例外放在哪里?您是否在需要的地方捕获异常?有没有更清洁的方法? (我已经阅读了关于 SO 和 laracasts 的帖子。我想听听你对此事的看法。)
    • @Kyslik 我同意。老实说,我在需要全局异常处理的 Laravel 5 上没有做任何大事。但是,如果应用程序变得更大,我肯定会在全局范围内处理最多抛出的异常(在渲染方法内)
    • @Kyslik 好的提示,我实际上打算在全球范围内处理这类异常。谢谢!
    【解决方案2】:

    您首先必须测试返回的对象是否实际上不为空。盲目假设数据库查询成功就是在等待 sh*t 撞上风扇。

    public function returnTop($count = 6, $args = Array()) {
        $project = Project::find($args['projectid']);
        if($project) {
            $companies = $project->companies()->whereHas('products', function($q) use($args) {
                $q->whereIn('products.id', $args['products']);
            })->with('products')->limit($count)->get();
    
            return Response::json($companies);
        }
        else {
            return; // .. your error or whatever
        }
    }
    

    此外,“对非对象的成员函数的调用”非常具体,它告诉您由于您试图在非对象上调用它而无法调用方法(成员函数)。对象。

    【讨论】:

    • 事实上,我盲目地假设查询会失败 :) 但我希望 laravel 返回不同的输出。不过,您的回答对我有所帮助。谢谢!
    • 每当条目不存在时抛出错误,ORM 会有什么用处。正确的结果是说; “没有条目”被翻译成null。但是,在没有适当验证的情况下盲目假设一切正常,这是一个常见的陷阱。一直在“这里”发生。
    猜你喜欢
    • 1970-01-01
    • 2017-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 1970-01-01
    • 2021-07-02
    • 2015-06-11
    相关资源
    最近更新 更多