macropay-solutions/laravel-crud-wizard-free

用于Laravel/Lumen CRUD操作(包括URL查询语言)的免费库

3.2.5 2024-09-18 12:00 UTC

README

laravel-lumen-crud-wizard-logo

这是付费版本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。

另请参阅 Laravel crud wizard demo

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": ...
}

默认情况下不可用删除。