weapnl / laravel-junction
轻松创建具有扩展功能的REST API,例如预加载、搜索、筛选等。
Requires
- php: ^8.2
- laravel/framework: ^8.0 || ^9.0 || ^10.0 || ^11.0
Requires (Dev)
- laravel/pint: ^1.17
Suggests
- spatie/laravel-medialibrary: For using the temporary media upload functionality.
README
此项目允许您轻松使用Laravel创建REST API。它具有扩展功能,例如预加载、搜索、筛选等。
目录
安装
composer require weapnl/laravel-junction
Js 支持
我们很高兴地宣布,这个Laravel-Junction包现在有一个配套的JavaScript/TS库!这个新增功能将我们的Laravel包的功能扩展到前端,为您的Web应用程序提供无缝集成。
开发
为了轻松在本地工作并使用该包在其他本地项目中,请执行以下操作
- 在您想包含Laravel-Junction的项目中,向
composer.json
文件添加一个存储库
"repositories": { "laravel-junction": { "type": "path", "url": "./laravel-junction", "options": { "symlink": true } } }
- 如果您的其他项目在docker中运行,请添加一个指向Laravel-Junction所在文件夹的卷
services: api: image: ... volumes: - ../laravel-junction:/var/www/laravel-junction
- 安装本地包。您之前在存储库中设置的
symlink
选项确保您只需这样做一次,而不是每次代码更改时都这样做。
composer require weapnl/laravel-junction dev-main
快速入门
// app/Http/Controllers/API/UserController.php namespace App\Http\Controllers\API; use Weap\Junction\Http\Controllers\Controller; class UserController extends Controller { /** * The class name of the model for which the controller should implement CRUD actions. * * @var string */ public $model = User::class; /** * Define the relations which can be loaded in a request using "array" notation. * * @return array */ public function relations(): array { return [ 'orders', ]; }
// routes/api.php Junction::apiResource('users', 'UserController');
现在您已经准备好了。您现在可以向/api/users
端点发出请求。尝试一个POST请求来创建新用户,或一个GET请求来检索所有用户。
用法
设置控制器
为了让控制器可以通过API访问,您需要扩展Weap\Junction\Http\Controllers\Controller
类。这个类扩展了默认的Laravel控制器,并添加了一些额外功能。定义控制器非常简单,请查看快速入门部分的基本示例。我们现在将介绍一些额外功能。
// app/Http/Controllers/API/UserController.php namespace App\Http\Controllers\API; use Weap\Junction\Http\Controllers\Controller; // Make sure to import the Controller class from the Weap/Junction package. class UserController extends Controller { /** * The class name of the model for which the controller should implement CRUD actions. * * @var string */ public $model = User::class; /** * The class name of Resource to be used for the show and index methods. * * @var string $resource */ public $resource = UserResource::class; /** * Define the relations which can be loaded in a request using "array" notation. * * @return array */ public function relations(): array { return [ 'orders', // Define all your relations here with should be accessible through the API. ]; }
示例用法
/api/users?orders[0][column]=id&orders[0][direction]=asc&&search_value=john&search_columns[]=name&search_columns[]=email
示例响应
即使您没有使用分页,响应也始终包含属性items
、total
和page
。
{ "items": [ { "id": 2, "name": "John Doe", "email": "john.doe@app.com", "orders": [], "comments": [ { "id": 1, "body": "Hello world!" } ] } ], "total": 1, // Total amount of items "page": 1 // The current page }
筛选器
筛选器应用于查询。筛选器使用数组键定义。可用的筛选器
修改器
修改器在查询运行后应用。可用的修改器
分页
分页在数据库级别应用(在应用所有筛选器之后)。以下参数可用于设置分页
简单分页
简单分页几乎与上述分页相同。但简单分页不返回项目总数或页码。这对于大型数据库表很有用,因为正常分页太慢。
关系
要限制可以使用with
筛选器加载的关系,您可以在控制器上覆盖relations
方法。此方法应返回一个包含关系(支持点表示法)的数组。要向关系查询添加筛选器,您可以使用关系名称作为键,闭包作为值。
注意:当使用点表示法时,如果为较高层次的关系提供了一个闭包,则该闭包将应用于查询。例如,如果关系实现如下,加载关系user.activities
将应用isAdmin
作用域到用户查询。
public function relations() { return [ 'user' => fn($query) => $query->isAdmin(), 'user.activities', ]; }
搜索
此包支持针对给定模型和关系的搜索功能。在您的控制器中,添加以下定义的可搜索属性。当您想要搜索一个模型时,请在请求中添加 "search_value"。可选地,您可以添加 "search_columns" 来覆盖控制器中的列。
public $searchable = [ 'id', 'name', 'orders.order_number', ];
资源
要使用资源,请在控制器中设置 resource
变量。您的资源必须扩展 \Weap\Junction\Http\Controllers\Resources
。
这允许您指定将返回哪些属性、访问器和关系。为此,覆盖相应的方法
availableAttributes
。返回一个字符串数组,指定将返回哪些属性。主键始终包含在内。availableAccessors
。返回一个字符串数组,指定将返回哪些访问器。availableRelations
。返回一个键/值对数组,其中键是关系的名称,值是另一个资源。
在这些方法中的任何一种中返回 null
以允许返回 ALL
属性/访问器/关系。
示例
class UserResource extends BaseResource { /** * @return array|null */ protected function availableAttributes(): ?array { return [ 'first_name' ]; } /** * @return array|null */ protected function availableAccessors(): ?array { return [ 'fullName' ]; } /** * @return array|null */ protected function availableRelations(): ?array { return [ 'orders' => OrderResource::class, ]; } }
操作
此包还支持动作路由。
在您的控制器中添加动作方法
/** * @param null|Model $model */ protected function actionSomeName($model = null) { // }
- 如果您正在使用策略,则您的策略应实现
action
策略,该策略接受模型作为参数。 - 现在,您可以通过以下路由作为
PUT
请求进行调用:/api/users
。在主体中,添加以下内容(id是可选的)
{ "action": "someName", "id": 1 }
- 您可以根据需要添加尽可能多的动作。只需确保将方法前缀为
action
。
验证
FormRequest验证
要验证传入的请求,您可以创建一个 FormRequest
并扩展 Weap\Junction\Http\Controllers\Requests\DefaultFormRequest
类。此类扩展了默认的Laravel FormRequest
类,并添加了一些额外功能。
标准验证
要验证请求,为您的模型创建一个请求文件并将其添加到控制器中。
/** * The class name of FormRequest to be used for the store and update methods. * * @var string */ public $formRequest = ModelRequest::class;
- 在
ModelRequest
的rules()
方法中添加规则。
/** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'first_name' => 'required', ]; } /** * Define validation rule messages for store and update requests. * * @return array */ public function messages() { return [ 'first_name.required' => 'The first name is required.', ]; }
保存可填充属性
默认情况下,调用store/update路由时只保存经过验证的属性。要保存可填充属性,请在控制器中设置以下内容
/** * Set to true to save fillable instead of validated attributes in store/update methods. * * @var bool */ protected $saveFillable = true;
使用 Spatie Medialibrary 的临时媒体文件
步骤 1:通过API上传文件
要通过API上传文件,请使用 /media/upload
端点。在请求体中包含一个位于 files
键下的文件数组。这些文件将临时存储在媒体库中,并与 MediaTemporaryUpload
模型关联。
示例上传请求
{ "files": [<uploaded file here>, ...] }
步骤 2:将文件附加到模型
示例 A:更新现有模型
要将文件附加到现有模型,请将媒体ID包含在 PUT
请求中。例如,如果您想将身份证件附加到员工身上,您的 PUT
请求可能如下所示,假设身份证件存储在 Employee
模型上的 IdentityFiles
集合 中
{ "first_name": "John", "last_name": "Doe", "_media": { "IdentityFiles": [1] } }
API将在请求体中搜索 _media
键并将指定的媒体ID与正确的集合关联起来。在此示例中,媒体ID 1将附加到ID为3的 Employee
的 IdentityFiles
集合中。
示例 B:创建新模型
您还可以在创建新模型时通过 POST
请求附加文件。例如,如果您正在创建新的 Employee
并希望附加一张个人照片,您的 POST
请求可能如下所示
{ "first_name": "Jane", "last_name": "Smith", "_media": { "ProfilePicture": [2] } }
这将把媒体ID 2附加到新创建的 Employee
的 ProfilePicture
集合中。
在嵌套结构中使用 _media
键
在请求数据体中,_media
键也可以嵌套使用,例如,可以嵌套在contact
键内部。在这种情况下,API会将媒体文件附加到Employee
的contact
关系上,无论您是在创建新模型还是更新现有模型。
嵌套_media
键的示例请求(用于创建)
{ "first_name": "Jane", "last_name": "Smith", "contact": { "phone": "123-456-7890", "_media": { "ProfilePicture": [3] } } }
在这个示例中,当创建一个新的Employee
时,媒体ID 3将被附加到新Employee
的contact
关系中的ProfilePicture
集合中。