barisbora/laravel-query-builder

此包已废弃,不再维护。未建议替代包。

轻松从API请求构建Eloquent查询

v1.4 2018-07-17 19:15 UTC

This package is not auto-updated.

Last update: 2024-06-26 23:41:57 UTC


README

轻松从API请求构建Eloquent查询

Latest Version on Packagist Build Status StyleCI Quality Score Total Downloads

此包允许您根据请求过滤、排序并包含Eloquent关系。在此包中使用的QueryBuilder扩展了Laravel默认的Eloquent构建器。这意味着您仍然可以使用所有您喜欢的方法和宏。查询参数名称尽可能遵循JSON API规范

基本用法

过滤API请求:/users?filter[name]=John

use Spatie\QueryBuilder\QueryBuilder;

// ...

$users = QueryBuilder::for(User::class)
    ->allowedFilters('name')
    ->get();
// all `User`s that contain the string "John" in their name

从API请求请求关系:/users?include=posts

$users = QueryBuilder::for(User::class)
    ->allowedIncludes('posts')
    ->get();
// all `User`s with their `posts` loaded

与现有查询配合良好

$query = User::where('active', true);

$user = QueryBuilder::for($query)
    ->allowedIncludes('posts', 'permissions')
    ->where('score', '>', 42) // chain on any of Laravel's query builder methods
    ->first();

排序API请求:/users?sort=name

$users = QueryBuilder::for(User::class)->get();
// all `User`s sorted by name

请查看下面的用法部分以获取高级示例和功能。

安装

您可以通过composer安装此包

composer require spatie/laravel-query-builder

您可以选择使用以下命令发布配置文件:

php artisan vendor:publish --provider="Spatie\QueryBuilder\QueryBuilderServiceProvider" --tag="config"

这是发布配置文件的内容

return [

    /*
     * By default the package will use the `include`, `filter`, `sort` and `fields` query parameters.
     *
     * Here you can customize those names.
     */
    'parameters' => [
        'include' => 'include',

        'filter' => 'filter',

        'sort' => 'sort',

        'fields' => 'fields',
    ],

];

用法

包含关系

使用include查询参数将在结果集合上加载任何Eloquent关系。默认情况下,不允许任何包含。所有包含都必须使用allowedIncludes()指定。

// GET /users?include=posts
$users = QueryBuilder::for(User::class)
    ->allowedIncludes('posts')
    ->get();

// $users will contain all users with their posts loaded

您可以通过逗号分隔来加载多个关系

// GET /users?include=posts,permissions
$users = QueryBuilder::for(User::class)
    ->allowedIncludes('posts', 'permissions')
    ->get();

// $users will contain all users with their posts and permissions loaded

您还可以将包含数组传递给allowedIncludes()方法。

// GET /users?include=posts,permissions
$users = QueryBuilder::for(User::class)
    ->allowedIncludes(['posts', 'permissions'])
    ->get();

// $users will contain all users with their posts and permissions loaded

您可以使用点(.)来加载嵌套关系

// GET /users?include=posts.comments,permissions
$users = QueryBuilder::for(User::class)
    ->allowedIncludes('posts.comments', 'permissions')
    ->get();

// $users will contain all users with their posts, comments on their posts and permissions loaded

当尝试包含使用allowedIncludes()不允许的关系时,将抛出InvalidIncludeQuery异常。

关系/包含名称将在查找模型上对应关系时转换为驼峰命名法。这意味着/users?include=blog-posts将尝试在User模型上加载blogPosts()关系。

一旦在结果集合上加载了关系,您就可以通过使用Eloquent API资源和条件关系来在响应中包含它们。

过滤

可以使用filter查询参数根据部分属性值、精确属性值或属性值是否存在于给定的值数组中过滤结果。您还可以为更复杂的查询指定自定义过滤器。

默认情况下,不允许任何过滤器。所有过滤器都必须使用allowedFilters()指定。当尝试在未使用allowedFilters()允许的属性上过滤时,将抛出InvalidFilterQuery异常。

// GET /users?filter[name]=john&filter[email]=gmail
$users = QueryBuilder::for(User::class)
    ->allowedFilters('name', 'email')
    ->get();
// $users will contain all users with "john" in their name AND "gmail" in their email address

您还可以将过滤器数组传递给allowedFilters()方法。

// GET /users?filter[name]=john&filter[email]=gmail
$users = QueryBuilder::for(User::class)
    ->allowedFilters(['name', 'email'])
    ->get();
// $users will contain all users with "john" in their name AND "gmail" in their email address

您可以通过传递逗号分隔的值列表来指定多个匹配的过滤器值

// GET /users?filter[name]=seb,freek
$users = QueryBuilder::for(User::class)
    ->allowedFilters('name')
    ->get();
// $users will contain all users that contain "seb" OR "freek" in their name

精确过滤器

当根据其ID、布尔值或字面字符串过滤模型时,您将希望使用精确过滤器。这样,/users?filter[id]=1不会匹配ID中包含数字1的所有用户。

可以在allowedFilters()方法中使用Spatie\QueryBuilder\Filter::exact('property_name')添加精确过滤器。

use Spatie\QueryBuilder\Filter;

// GET /users?filter[name]=John%20Doe
$users = QueryBuilder::for(User::class)
    ->allowedFilters(Filter::exact('name'))
    ->get();
// all users with the exact name "John Doe"

查询构建器将自动将'true''false'映射为布尔值,将逗号分隔的值列表映射为数组

use Spatie\QueryBuilder\Filter;

// GET /users?filter[id]=1,2,3,4,5&filter[admin]=true
$users = QueryBuilder::for(User::class)
    ->allowedFilters(Filter::exact('id'), Filter::exact('admin'))
    ->get();
// $users will contain all admin users with id 1, 2, 3, 4 or 5

作用域过滤器

有时你可能需要构建更高级的过滤查询。这时候作用域过滤和自定义过滤就派上用场了。

作用域过滤允许你通过向URL添加过滤条件,轻松地为查询添加局部作用域

考虑以下模型的作用域

public function scopeStartsBefore(Builder $query, $date): Builder
{
    return $query->where('starts_at', '>=', Carbon::parse($date));
}

要基于startsBefore作用域进行过滤,只需将其添加到查询构建器的allowedFilters

QueryBuilder::for(Event::class)
    ->allowedFilters([
        Filter::scope('starts_before'),
    ])
    ->get();

以下过滤器现在会将startsBefore作用域添加到底层查询中

GET /events?filter[starts_before]=2018-01-01

你甚至可以通过将逗号分隔的列表传递给过滤器来传递多个参数给作用域

GET /events?filter[starts_between]=2018-01-01,2018-12-31

自定义过滤器

你可以使用Filter::custom()方法指定自定义过滤器。自定义过滤器是简单的可调用类,它实现了\Spatie\QueryBuilder\Filters\Filter接口。这样你可以创建任何你想要的查询。

例如

use Spatie\QueryBuilder\Filters\Filter;
use Illuminate\Database\Eloquent\Builder;

class FiltersUserPermission implements Filter
{
    public function __invoke(Builder $query, $value, string $property) : Builder
    {
        return $query->whereHas('permissions', function (Builder $query) use ($value) {
            $query->where('name', $value);
        });
    }
}

use Spatie\QueryBuilder\Filter;

// GET /users?filter[permission]=createPosts
$users = QueryBuilder::for(User::class)
    ->allowedFilters(Filter::custom('permission', FiltersUserPermission::class))
    ->get();
// $users will contain all users that have the `createPosts` permission

排序

sort查询参数用于确定结果集合将按哪个属性排序。默认情况下,排序是升序的。在属性名称的开头添加一个连字符(-)将反转结果集合。

// GET /users?sort=-name
$users = QueryBuilder::for(User::class)->get();

// $users will be sorted by name and descending (Z -> A)

默认情况下,所有模型属性都可以用于排序结果。但是,你可以使用allowedSorts方法来限制哪些属性可以在请求中使用。

当你尝试根据未在allowedSorts()中指定的属性进行排序时,将抛出InvalidSortQuery异常。

// GET /users?sort=password
$users = QueryBuilder::for(User::class)
    ->allowedSorts('name')
    ->get();

// Will throw an `InvalidSortQuery` exception as `password` is not an allowed sorting property

要定义一个默认排序参数,它应该在请求中明确添加,你可以使用defaultSort方法。

// GET /users
$users = QueryBuilder::for(User::class)
    ->defaultSort('name')
    ->allowedSorts('name', 'street')
    ->get();

// Will retrieve the users sorted by name

你还可以将排序数组传递给allowedSorts()方法。

// GET /users?sort=name
$users = QueryBuilder::for(User::class)
    ->allowedSorts(['name', 'street'])
    ->get();

// Will retrieve the users sorted by name

你可以通过逗号分隔多个属性来按多个属性排序

// GET /users?sort=name,-street
$users = QueryBuilder::for(User::class)
    ->allowedSorts('name', 'street')
    ->get();

// $users will be sorted by name in ascending order with a secondary sort on street in descending order.

选择特定列

有时你可能只想获取几个字段以减少SQL查询的整体大小。这可以通过使用fields查询参数来完成。以下仅获取用户的有效idname

GET /users?fields[users]=id,name

SQL查询看起来像这样

SELECT "id", "name" FROM "users"

选择包含模型的字段的工作方式相同。这在需要包括整个关系但只需要几个列时特别有用。考虑以下示例

GET /posts?include=author&fields[author]=name

将获取所有帖子,包括作者的名字。

附加属性

有时你可能想将一些自定义属性附加到从模型获取的结果中。这可以通过使用append参数来完成。

class User extends Model{

    public function getFullnameAttribute()
    {
        return $this->firstname.' '.$this->lastname;
    }
}
// GET /users?append=fullname

$users = QueryBuilder::for(User::class)
    ->allowedAppends('fullname')
    ->get();

当然,你可以传递一个要附加的属性列表。

// GET /users?append=fullname,ranking

其他查询方法

由于QueryBuilder扩展了Laravel的默认Eloquent查询构建器,因此你可以使用任何你喜欢的函数或宏。你也可以指定一个基本查询而不是模型FQCN

QueryBuilder::for(User::where('id', 42)) // base query instead of model
    ->allowedIncludes('posts')
    ->where('activated', true) // chain on any of Laravel's query methods
    ->first(); // we only need one specific user

分页

此包不提供任何帮助您分页响应的方法。然而,如上所述,你可以使用Laravel的默认paginate()方法

如果你想完全遵守JSON API规范,你也可以使用我们自己的spatie/json-api-paginate

在前端构建查询

如果你使用Vue,你可能会对vue-api-query包感兴趣,由Robson Tenório提供。

测试

composer test

变更日志

有关最近更改的更多信息,请参阅变更日志

贡献

请参阅CONTRIBUTING以获取详细信息。

安全

如果您发现任何安全相关的问题,请发送电子邮件至freek@spatie.be,而不是使用问题跟踪器。

Postcardware

您可以使用此软件包,但如果它进入了您的生产环境,我们非常感激您从家乡给我们寄一张明信片,并说明您正在使用我们的哪个软件包。

我们的地址是:Spatie,Samberstraat 69D,2060 安特卫普,比利时。

我们将所有收到的明信片发布在我们的公司网站上

致谢

支持我们

Spatie是一家位于比利时的安特卫普网络设计公司。您可以在我们的网站上找到我们所有开源项目的概述。

您的业务是否依赖于我们的贡献?在Patreon上联系我们并支持我们。所有承诺都将用于分配人力进行维护和开发新酷炫的功能。

许可

MIT许可证(MIT)。请参阅许可文件以获取更多信息。