tomblakemore/laravel-jsonapi-http

支持JSON:API规范的Laravel项目的包

v1.3.2 2017-05-07 12:12 UTC

This package is not auto-updated.

Last update: 2024-09-28 20:35:41 UTC


README

描述

一个支持JSON:API规范的Laravel项目的包。

包支持的特性

  • 关系
  • 包含
  • 过滤
  • 分页
  • 排序

有关JSON:API规范的完整详细信息,请参阅https://jsonapi.fullstack.org.cn/format

使用Composer安装

使用 Composer 安装此包。如果您尚未安装Composer,请按照文档进行安装。

在您的应用程序文件夹内运行

composer require tomblakemore/laravel-jsonapi-http

设置

将服务提供者添加到 config/app.php 文件。

'providers' => [
    ...

    JsonApiHttp\RequestServiceProvider::class
],

将以下中间件组添加到 app\Http\Kernel.php 类。

protected $middlewareGroups = [
    ...

    'jsonapi' => [
        \JsonApiHttp\Middleware\SetRequest::class,
        \JsonApiHttp\Middleware\CheckAcceptHeaders::class,
        \JsonApiHttp\Middleware\CheckForContentTypeHeader::class,
        \JsonApiHttp\Middleware\VerifyContentTypeHeader::class,
        \JsonApiHttp\Middleware\VerifyContent::class,
        \JsonApiHttp\Middleware\SetResponseHeaders::class
    ],

    'relationships' => [
        \JsonApiHttp\Middleware\VerifyRelationship::class,
        \JsonApiHttp\Middleware\AddRelationshipToModel::class,
        \JsonApiHttp\Middleware\RemoveRelationshipFromModel::class
    ],

    'resources' => [
        \JsonApiHttp\Middleware\VerifyResource::class,
        \JsonApiHttp\Middleware\AddResourceAttributesToModel::class,
        \JsonApiHttp\Middleware\AddResourceRelationshipsToModel::class,
        \JsonApiHttp\Middleware\RemoveResourceRelationshipsFromModel::class
    ]
];

基本用法

以下是一个简单的模型和控制器示例,用于显示人员列表和获取特定人员。

创建 people 表。

php artisan make:migration create_people_table --create=people

将以下内容添加到迁移文件。

/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::create('people', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->timestamps();
    });
}

创建 Person 模型并填写属性 $type。类型是JSON:API资源类型,应该是模型名称的复数形式,因此在这种情况下是 people

<?php

namespace App;

use JsonApiHttp\AbstractModel;

class Person extends AbstractModel
{
    /**
     * The resource type.
     *
     * @var string
     */
    protected $type = 'people';
}

一个控制器,包含两个操作来获取人员和人员。

<?php

namespace App\Http\Controllers;

use App\Person;

use JsonApiHttp\Controller;
use JsonApiHttp\Request;

class PersonController extends Controller
{
    /**
     * The resource type.
     *
     * @var string
     */
    protected $type = 'people';

    /**
     * Display a list of people.
     *
     * @param \JsonApiHttp\Request $request
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $query = Person::query();

        $request->filter($query)->sort($query);

        $people = $request->paginate($query, Person::perPage());
        $people->appends($request->query());

        $resources = $this->resources($request, $people);

        return response($resources);
    }

    /**
     * Display a person.
     *
     * @param \JsonApiHttp\Request $request
     * @param \App\Person $person
     * @return \Illuminate\Http\Response
     */
    public function show(Request $request, Person $person)
    {
        $resource = $this->resource($request, $person);
        return response($resource);
    }
}

两个路由将请求定向到两个控制器操作。

Route::group(['middleware' => ['jsonapi', 'resources']], function () {
    Route::get('/people', 'PersonController@index')->name('people.index');
    Route::get('/people/{person}', 'PersonController@show')->name('people.show');
});

资源现在可以在以下端点上访问

  • GET /people
  • GET /people/:id

关系

可以使用JSON:API关系端点来表示对象。我们将创建一个简单的 Patient > Doctor 关系作为示例。

创建 doctors 表。

php artisan make:migration create_doctors_table --create=doctors

将以下内容添加到迁移文件。

/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::create('doctors', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->timestamps();
    });
}

创建 Doctor 模型并创建 patients 关系。

<?php

namespace App;

use JsonApiHttp\AbstractModel;

class Doctor extends AbstractModel
{
    /**
     * The resource type.
     *
     * @var string
     */
    protected $type = 'doctors';

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function patients()
    {
        return $this->hasMany(Patient::class);
    }

    /**
     * Return any the relations to display in the JSON:API output.
     *
     * @return array
     */
    public function relations()
    {
        return ['patients'];
    }
}

创建一个用于关系的控制器。

<?php

namespace App\Http\Controllers;

use App\Doctor;

use JsonApiHttp\RelationshipsController;
use JsonApiHttp\Request;

class DoctorRelationshipsController extends RelationshipsController
{
    /**
     * The resource type.
     *
     * @var string
     */
    protected $type = 'doctors';

    /**
     * Display a relation or collection of relations.
     *
     * @param \JsonApiHttp\Request $request
     * @param \App\Doctor $doctor
     * @param string $relation
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request, Doctor $doctor, $relation)
    {
        $relations = $this->relations($request, $doctor, $relation);
        return response($relations);
    }

    /**
     * Display a relationship.
     *
     * @param \JsonApiHttp\Request $request
     * @param \App\Doctor $doctor
     * @param string $relation
     * @return \Illuminate\Http\Response
     */
    public function show(Request $request, Doctor $doctor, $relation)
    {
        $relationship = $this->relationship($request, $doctor, $relation);
        return response($relationship);
    }
}

创建 patients 表。

php artisan make:migration create_patients_table --create=patients

将以下内容添加到迁移文件。

/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::create('patients', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('doctor_id')->unsigned()->index();
        $table->foreign('doctor_id')->references('id')->on('doctors');
        $table->string('name');
        $table->timestamps();
    });
}

创建 Patient 模型并创建 doctor 关系。

<?php

namespace App;

use JsonApiHttp\AbstractModel;

class Patient extends AbstractModel
{
    /**
     * The resource type.
     *
     * @var string
     */
    protected $type = 'patients';

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function doctor()
    {
        return $this->belongsTo(Doctor::class);
    }

    /**
     * Return any the relations to display in the JSON:API output.
     *
     * @return array
     */
    public function relations()
    {
        return ['doctor'];
    }
}

创建一个用于关系的控制器。

<?php

namespace App\Http\Controllers;

use App\Patient;

use JsonApiHttp\RelationshipsController;
use JsonApiHttp\Request;

class PatientRelationshipsController extends RelationshipsController
{
    /**
     * The resource type.
     *
     * @var string
     */
    protected $type = 'patients';

    /**
     * Display a relation or collection of relations.
     *
     * @param \JsonApiHttp\Request $request
     * @param \App\Patient $patient
     * @param string $relation
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request, Patient $patient, $relation)
    {
        $relations = $this->relations($request, $patient, $relation);
        return response($relations);
    }

    /**
     * Display a relationship.
     *
     * @param \JsonApiHttp\Request $request
     * @param \App\Patient $patient
     * @param string $relation
     * @return \Illuminate\Http\Response
     */
    public function show(Request $request, Patient $patient, $relation)
    {
        $relationship = $this->relationship($request, $patient, $relation);
        return response($relationship);
    }
}

创建将请求定向到两个关系控制器的路由。

Route::group(['middleware' => ['jsonapi', 'relationships']], function () {

    Route::get(
        'doctors/{doctor}/{relation}',
        'DoctorRelationshipsController@index'
    )
    ->where('relation', 'patients')
    ->name('doctors.relations.index');

    Route::get(
        'doctors/{doctor}/relationships/{relation}',
        'DoctorRelationshipsController@show'
    )
    ->where('relation', 'patients')
    ->name('doctors.relations.show');

    Route::get(
        'patients/{patient}/{relation}',
        'PatientRelationshipsController@index'
    )
    ->where('relation', 'doctor')
    ->name('patients.relations.index');

    Route::get(
        'patients/{patient}/relationships/{relation}',
        'PatientRelationshipsController@show'
    )
    ->where('relation', 'doctor')
    ->name('patients.relations.show');

});

关系现在可以在以下端点上访问

  • GET /doctors/:id/patients
  • GET /doctors/:id/relationships/patients
  • GET /patients/:id/doctor
  • GET /patients/:id/relationships/doctor

包含

要获取单个请求中的相关对象,请使用 ?include 查询参数。

GET /patients/1?include=doctor

您还可以使用点表示法来返回关系的嵌套关系。

GET /patients/1?include=doctor.patients

过滤

要过滤结果集,请将 filter 参数传递到查询字符串中。

值可以是逗号分隔的值(AND)和/或管道分隔的值(OR)的组合。

可以使用括号实现AND和OR操作的嵌套。

要查询的属性和属性/值对由冒号字符连接。

支持的运算符包括 ! (不等于),< <= => > <> (小于和大于运算符,包括一个替代的不等于运算符),^ !^ (以/不以开头),$ !$ (以/不以结尾),^$ !^$ (包含/不包含)。

要按单个属性(精确值)进行过滤。

GET /patients?filter=name:tom

要按单个属性的多个值进行过滤。

GET /patients?filter=name:(tom|ben)

关系可以查询,值是一个或多个相关资源的ID。支持属于和拥有多个类型的关系。

GET /patients?filter=doctor:1

分页

使用 pageperPage 查询参数来控制结果集的分页。

GET /patients?page=1&perPage=10

排序

使用 sort 查询参数来排序结果集。值应该是模型的一个属性。使用 - 符号前缀进行降序排序。可以指定多个属性,用逗号分隔。

GET /patients?sort=-name

测试

这些功能很快就会添加!