macropay-solutions / laravel-crud-wizard-free
用于Laravel/Lumen CRUD操作(包括URL查询语言)的免费库
Requires
- php: ^8.0
- ext-json: *
- maatwebsite/excel: ^3.1
- nesbot/carbon: ^2.62
- psr/log: ^1.0 || ^2.0 || ^3.0
Requires (Dev)
- illuminate/contracts: ^9.36
- illuminate/database: ^9.36
- illuminate/http: ^9.36
- illuminate/pagination: ^9.36
- illuminate/routing: ^9.36
- illuminate/support: ^9.36
- illuminate/validation: ^9.52
- phpunit/phpunit: ^9.4
- symfony/http-foundation: ^6.0
Suggests
- barryvdh/laravel-ide-helper: *
- laravel/framework: >= 8.0
- laravel/lumen-framework: >= 8.0
- macropay-solutions/laravel-crud-wizard-demo: dev-production
README
这是付费版本Laravel crud wizard的简化版(已在laravel/lumen 8, laravel 9, laravel 10上测试,应也能在laravel 11上运行)。
适用于使用lumen/laravel 8-9-10-11的RESTful CRUD(微)服务的URL查询语言库
这不仅仅是一个CRUD库!
它具有内置的过滤功能,可用于列表,也可用于批量删除,因此可以称为CRUFD(创建、读取、更新、过滤和删除)库。
I. 安装
II. 开始使用
III. CRUD路由
III.1. 创建资源
III.2. 获取资源
III.3. 列表过滤资源
III.4. 更新资源(或创建)
III.5. 删除资源
I. 安装
composer install macropay-solutions/laravel-crud-wizard-free
II. 开始使用
在lumen或laravel中注册 \MacropaySolutions\LaravelCrudWizard\Providers\CrudProvider 和 \MacropaySolutions\LaravelCrudWizard\Http\Middleware\UnescapedJsonMiddleware::class。
在您的代码中创建一个常量
class DbCrudMap { public const MODEL_FQN_TO_CONTROLLER_MAP = [ BaseModelChild::class => ResourceControllerTraitIncludedChild::class, ... ]; }
扩展
- BaseModel(对于created_at和updated_at列,它需要datetime而不是timestamp)
- BaseResourceService
创建一个使用ResourceControllerTrait的控制器,并在其__construct方法中调用 $this->init()。
用于模型属性自动完成
-
扩展BaseModelAttributes,遵循与父级相同的FQN结构
\App\Models\ChildBaseModel paired with \App\Models\Attributes\ChildBaseModelAttributes \App\Models\Folder\ChildBaseModel paired with \App\Models\Folder\Attributes\ChildBaseModelAttributes
-
在其类文档块中使用 @property 添加所有模型属性/属性/列
-
在模型类文档块中添加 @property ChildBaseModelAttributes $a 和 @mixin ChildBaseModelAttributes
-
使用 $model->a-> 而不是 $model->
将此新资源添加到上面的映射中。
使用以下方法在您的应用程序中注册CRUD路由(例如,在Laravel中)
try { foreach ( ResourceHelper::getResourceNameToControllerFQNMap(DbCrudMap::MODEL_FQN_TO_CONTROLLER_MAP) as $resource => $controller ) { Route::get('/' . $resource, [$controller, 'list'])->name('apiinfo.list_' . $resource); Route::post('/' . $resource, [$controller, 'create'])->name('apiinfo.create_' . $resource); Route::put('/' . $resource . '/{identifier}', [$controller, 'update'])->name('apiinfo.update_' . $resource); Route::get('/' . $resource . '/{identifier}', [$controller, 'get'])->name('apiinfo.get_' . $resource); Route::delete('/' . $resource . '/{identifier}', [$controller, 'delete'])->name('apiinfo.delete_' . $resource); // Route::get('/' . $resource . '/{identifier}/{relation}', [$controller, 'listRelation']); // paid version only } } catch (Throwable $e) { \Illuminate\Support\Facades\Log::error($e->getMessage()); }
例如,对于lumen
try { foreach ( ResourceHelper::getResourceNameToControllerFQNMap( DbCrudMap::MODEL_FQN_TO_CONTROLLER_MAP ) as $resource => $controllerFqn ) { $controllerFqnExploded = \explode('\\', $controllerFqn); $controller = \end($controllerFqnExploded); //$router->get('/' . $resource . '/{identifier}/{relation}', [ // 'as' => $resource . '.listRelation', // 'uses' => $controller . '@listRelation', //]); // paid version only $router->get('/' . $resource, [ 'as' => $resource . '.list', 'uses' => $controller . '@list', ]); $router->post('/' . $resource, [ 'as' => $resource . '.create', 'uses' => $controller . '@create', ]); $router->put('/' . $resource . '/{identifier}', [ 'as' => $resource . '.update', 'uses' => $controller . '@update', ]); $router->get('/' . $resource . '/{identifier}', [ 'as' => $resource . '.get', 'uses' => $controller . '@get', ]); $router->delete('/' . $resource . '/{identifier}', [ 'as' => $resource . '.delete', 'uses' => $controller . '@delete', ]); } } catch (Throwable $e) { \Illuminate\Support\Facades\Log::error($e->getMessage()); }
在非生产环境中的.env文件中设置 LIVE_MODE=false。
III. CRUD路由
标识符可以是主键,或者如果是具有组合主键的资源,则可以是主键的组合,主键之间用_分隔!!!
见 \MacropaySolutions\LaravelCrudWizard\Models\BaseModel::COMPOSITE_PK_SEPARATOR
III.1 创建资源
POST /{resource}
头部
Authorization: Bearer ... // if needed. not coded in this lib
Accept: application/json
ContentType: application/json
主体
{
"column_name":"value",
...
}
JSON响应
201:
{
"column_name":"value",
...
}
400:
{
"message": "The given data was invalid.", // or other message
"errors": {
"column_name1": [
"The column name 1 field is required."
],
"column_name_2": [
"The column name 2 field is required."
],
...
}
}
上面的“错误”是可选的,仅出现在验证错误时,而“message”始终存在。
III.2 获取资源
GET /info/{resource}/{identifier}?withRelations[]=has_manyRelation&withRelations[]=has_oneRelation&withRelationsCount[]=has_manyRelation&withRelationsExistence[]=has_manyRelation
头部
Authorization: Bearer ... // if needed. not coded in this lib
Accept: application/json
JSON响应
200:
{
"identifier":"value",
"column_name":"value",
...
"index_required_on_filtering": [
"column_name_1",
"column_name2"
],
"has_oneRelation":{...},
"has_manyRelation":[
{
"id": ...,
"name": "...",
"pivot": {
"key1": 25,
"key2": 5
}
}
],
"has_manyRelation_count": 0,
"has_manyRelation_exist": false
}
400:
{
"message": ...
}
标识符可以由多个标识符组成,对于具有组合主键的枢纽资源。例如:/table1-table2-pivot/3_10
需要时,将检索关系。关系键不能用于过滤!!!
index_required_on_filtering
键不能用于过滤。
pivot
是可选的,仅在通过 pivot 关联的关联中显示。
III.3 列出过滤的资源
GET /{资源}?page=1&limit=10&column=2&sort[0][by]=updated_at&sort[0][dir]=ASC&withRelations[]=has_manyRelation&withRelations[]=has_oneRelation&withRelationsCount[]=has_manyRelation&withRelationsExistence[]=has_manyRelation // 高级过滤和聚合仅在付费版本中可用
GET /{资源}/{标识符}/{关联}?... // 仅在付费版本中可用
头部
Authorization: Bearer ... // if needed. not coded in this lib
Accept: application/json or application/xls
JSON响应
200:
{
"index_required_on_filtering": [
"column_name1",
"column_name2"
],
"current_page": 1, // not present when cursor is present in request
"data": [
{
"identifier":"value",
"column_name":"value",
...,
"has_oneRelation":{...},
"has_manyRelation":[
{
"id": ...,
"name": "...",
"pivot": {
"key1": 25,
"key2": 5
}
}
],
"has_manyRelation_count": 0,
"has_manyRelation_exist": false
}
],
"from": 1, // not present when cursor is present in request
"last_page": 1, // not present when cursor is present in request or when simplePaginate is true in controller or present in request
"per_page": 10,
"to": 1, // not present when cursor is present in request
"total": 1, // not present when cursor is present in request or simplePaginate is true in controller or present in request
"has_more_pages": bool,
"cursor": "..." // present only when cursor is present in request
}
对于 application/xls:二进制文件,内容来自 data
将被用作查询参数的保留词/参数是
page,
limit,
simplePaginate
cursor,
sort,
withRelations,
withRelationsCount,
withRelationsExistence,
默认值
page=1;
limit=10;
simplePaginate is false by default and only its presence is checked in request, not its value
cursor is not defined
sort[][dir]=DESC
注意。
index_required_on_filtering key CAN'T be used for filtering.
use ?cursor= for cursor pagination and ?simplePaginate=1 for simplePaginate. Use none of them for length aware paginator.
if \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class is used use ?cursor=1 instead of emtpy string
sort works also on aggregated colums for relation count and existence
III.4 更新资源(或创建)
PUT /{资源}/{标识符}
头部
Authorization: Bearer ... // if needed. not coded in this lib
Accept: application/json
ContentType: application/json
主体
{
"column_name":"value",
...
}
JSON响应
200 | 201:
{
// all resource's fields
}
400:
{
"message": "The given data was invalid.", // or other message
"errors": {
"column_name": [
"The column name field is invalid."
],
...
}
}
上面的“错误”是可选的,仅出现在验证错误时,而“message”始终存在。
标识符可以由多个标识符组成,用于具有复合主键的 pivot 资源(及其模型中的空字符串主键)。例如:/resources/3_10
某些资源上不可用更新。
UpdateOrCreate 仅在请求包含所有主键键(也存在于 getPrimaryKeyFilter 函数中)的情况下,且资源模型定义的 incrementing = false 的资源上可用。
更新将仅验证脏列,而不是所有发送的列,这意味着可以使用资源的所有列而不是仅更改的列进行更新。
III.5 删除资源
DELETE /{资源}/{标识符}
头部
Authorization: Bearer ... // if needed. not coded in this lib
JSON响应
204:
[]
400:
{
"message": ...
}
默认情况下不可用删除。