alexmg86/laravel-sub-query

v1.9.9 2021-04-23 10:02 UTC

This package is auto-updated.

Last update: 2024-09-25 23:24:12 UTC


README

Social Card of Laravel Sub Query

Laravel 子查询

PHP Composer Total Downloads Latest Stable Version License

为什么需要这个包?

在使用Laravel的常规方式中,如果你想获取相关模型的和或最大列值,你将有两个数据库查询。如果你需要获取一百条记录的列表呢?使用这个方法,所有这些都将变成一个数据库查询,并且无需加载额外的数据。

我还添加了按相关模型排序的方法,或者当你只需要为每个模型获取一个最新或最旧的相关模型而不进行多次查询时。还有很多其他的方法可以加快你的开发和代码的可读性。

我经常在我的工作中使用这个包,希望它对你也有用!

变更日志

请参阅变更日志获取最近更改的更多信息。

感谢您

如果你喜欢这个包,请给我一个星标。

安装

通过composer安装

composer require alexmg86/laravel-sub-query

在你的模型中使用LaravelSubQueryTrait特质。

use Alexmg86\LaravelSubQuery\Traits\LaravelSubQueryTrait;
use Illuminate\Database\Eloquent\Model;

class Invoice extends Model
{
    use LaravelSubQueryTrait;

用法

如果你想通过一次数据库请求获取关系的结果而不实际加载它们,可以使用以下方法,这些方法将在你的结果模型上放置新的列。例如

$invoices = Invoice::withSum('items:price')
    ->withMin('items:price')
    ->withMax('items:price')
    ->withAvg('items:price')
    ->get();

echo $invoices[0]->items_price_sum;
echo $invoices[0]->items_price_min;
echo $invoices[0]->items_price_max;
echo $invoices[0]->items_price_avg;

结果值可以通过第三个参数进行类型转换。一些类型示例:日期、日期时间、时间、字符、有符号、无符号、二进制。

$invoices = Invoice::withSum('items:price:signed')->get();

以下方法适用于所有方法!!!

你可以对多个关系进行求和,也可以在查询中添加约束

use Illuminate\Database\Eloquent\Builder;

$invoices = Invoice::withSum(['items:price', 'goods:price,price2' => function (Builder $query) {
    $query->where('price','>',6);
}])->get();

echo $invoices[0]->items_price_sum;
echo $invoices[0]->goods_price_sum;
echo $invoices[0]->goods_price2_sum;

你也可以对关系的求和结果进行别名,允许在同一关系中添加多个求和

use Illuminate\Database\Eloquent\Builder;

$invoices = Invoice::withSum(['items:price', 'goods:price as sum_goods_price' => function (Builder $query) {
    $query->where('price','!=',1);
}])->get();

echo $invoices[0]->items_price_sum;
echo $invoices[0]->sum_goods_price;

如果你将withSumselect语句结合使用,确保在select方法之后调用withSum

$invoices = Invoice::select(['id'])->withSum('items:price')->get();

echo $invoices[0]->id;
echo $invoices[0]->items_price_sum;

此外,使用loadSum方法,你可以在检索父模型之后加载关系求和列

$invoice = Invoice::first();
$invoice->loadSum('items:price');

如果你需要在预加载查询上设置额外的查询约束,你可以传递一个键为数组的数组,键为你希望加载的关系。数组值应该是接受查询构建实例的闭包实例

$invoice = Invoice::first();
$invoice->loadSum(['items:price' => function ($query) {
    $query->where('price', '>', 5);
}]);

当然,所有这些都兼容模型中的范围。

排序

如果你想按相关模型中的字段排序,只需使用以下方法

$invoices = Invoice::orderByRelation('items:price')->get();

或者使用条件

$invoices = Invoice::orderByRelation(['items:price' => function (Builder $query) {
    $query->where('price', '>', 6);
}, 'desc', 'max'])->get();

默认情况下,排序是按maxdesc,你可以选择以下选项之一:maxminsumavgdescacs

$invoices = Invoice::orderByRelation('items:price', 'asc', 'sum')->get();

与列一起工作

要添加或乘以所需的列,请使用此方法

$items = Item::withMath(['invoice_id', 'price'])->get();
echo $items[0]->sum_invoice_id_price;

列将默认求和,你可以选择以下选项:+-*/并设置新名称。

$items = Item::withMath(['invoice_id', 'price', 'price2'], '*', 'new_column')->get();
echo $items[0]->new_column;

与日期一起工作

选择日期的更方便的方式。默认情况下,排序是按created_at

$invoices = Invoice::whereCurrentYear('column_name')->get();
$invoices = Invoice::whereCurrentMonth()->get();
$invoices = Invoice::whereCurrentDay()->get();

加载最新或最旧的关系

想象一下,你想要获取50个账户的列表,每个账户有100个项目。默认情况下,你将得到5000个位置,并为每个账户选择前几个。PHP在旁边紧张地抽搐。
哇!现在你可以只加载一个最新或最旧的相关模型

$invoices = Invoice::all();
$invoices->loadOneLatest('items');
$invoices->loadOneOldest('items');

或者使用条件

$invoices->loadOneLatest(['items' => function ($query) {
    $query->orderBy('id', 'desc')->where('price', '<', 6);
}]);

你可以使用此功能与关系类型hasManybelongsToManyhasManyThrough

限制关系

如果你想通过限制加载相关模型,只需使用以下方法

$invoices = Invoice::all();
$invoices->loadLimit('items:1');

或者使用条件

$invoices->loadLimit(['items:2', 'goods:1' => function ($query) {
    $query->orderBy('id', 'desc')->where('price', '<', 6);
}]);

请注意,首先写出关系的名称,然后是行数。

缓存

为了方便,现在您可以缓存接收到的数据。

// Get a the first user's posts and remember them for a day.
Invoice::withSum('items:price')->remember(now()->addDay())->posts()->get();

// You can also pass the number of seconds if you like
// (before Laravel 5.8 this will be interpreted as minutes).
Invoice::withSum('items:price')->remember(60 * 60 * 24)->get();

更详细的描述在这里

我厌倦了在方法中详细写一些事情,所以我决定将它们移除。
您可以在这里看到它