用Eloquent ORM获取Object及其所有关系


Get Object and all its relations with Eloquent ORM

我有两个数据库表。一个用于保存基本数据,另一个用于保存数据的历史记录。举个例子:我有一个表books和一个表book_data

现在,在books表中,我有一个像sales这样的列。这是今天这本书的销量。在book_data中,我还保存了sales数字,但另外为该计数添加了日期。例如,我可以看到这本书在过去7天里的销量。

按ID获取图书,我执行以下操作

try {
    $book = Book::findOrFail($id);
    return [
        'status'    => 'success',
        'data'      => $post
    ];
} catch (ModelNotFoundException $e) {
    return response()->json([
        'status'    => 'error',
        'data'      => 'No book with this id found'
    ], 400);
 }

但是现在,我还想获得销售的"历史"。这意味着,当我选择一本书时,我还想从book_data表中获得所有相关的值。因此,当我保存了过去4天的数据时,我也想在我的响应中显示这些数据。

在我的Book模型类我有

public function history()
{
    return $this->hasMany('App''Models''BookData');
}

我已经写了这段代码,它基本工作…

public function show($id)
{
    try {
        $post = Book::with('history')->get()->find($id);
        return [
            'status'    => 'success',
            'data'      => $post
        ];
    } catch (ModelNotFoundException $e) {
        return response()->json([
            'status'    => 'error',
            'data'      => 'No post with this id found'
        ], 400);
    }
}

…然而,我对这个解决方案有很多问题。

1:这是不是对性能不好,因为我首先得到所有的对象与他们的关系和,然后我过滤它的id?第二:当我传递一个不存在的ID时,不会抛出ModelNotFoundException

那么,我该如何做到这一点,最好的方法?对于性能和可读性和最佳情况。

首先,不需要get()。您可以单独使用find():

$post = Book::with('history')->find($id);

不查询所有记录,然后进行过滤。它基本上只是为id添加一个WHERE子句,并返回第一个(也是唯一的)结果。


ModelNotFoundException只在使用findOrFail()时抛出。find()将只返回null。这就是你想要的:

$post = Book::with('history')->findOrFail($id);