allyson/arch-laravel

为 Laravel 项目提供的 CRUD 架构。

2.0.3 2024-03-05 23:47 UTC

This package is auto-updated.

Last update: 2024-09-06 00:55:55 UTC


README

Allyson Arch-Laravel 是一个 PHP 包,提供了一种简单优雅的方式来组织您的 Laravel 应用程序架构。它的目标是促进模块化和可扩展性,提供一套工具和约定,简化您的应用程序基础代码模块化结构。

安装

您可以通过 composer 安装此包。

composer require allyson/arch-laravel

如何使用

BaseRequest

  1. 文件:./Example/ExampleRequest.php
<?php

namespace App\Http\Requests\Example;

use ArchCrudLaravel\App\Http\Requests\BaseRequest;
use App\Models\Example;

abstract class ExampleRequest extends BaseRequest
{
    protected $model = Example::class;

    protected function hasGroupPermission(): bool
    {
        // Code...
    }

    protected function isOwner(string $method): bool
    {
        // Code...
    }
}

抽象类 BaseRequest 提供了方法:indexRules()updateRules()destroyRules(),它们返回一个数组,包含允许 BaseService 方法 index()update()destroy() 正确运行的规则。可以与您自己的业务规则组合使用。还需要实现方法 hasGroupPermission()isOwner(),这些方法可以根据应用程序需求和业务规则进行实现,以授权对资源的访问和使用。

  1. 文件:./Example/IndexRequest.php
<?php

namespace App\Http\Requests\Example;

class IndexRequest extends ExampleRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize(): bool
    {
        return $this->hasGroupPermission();
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules(): array
    {
        return $this->indexRules();
    }
}

indexRules() 方法允许通过分页进行导航,定义每页的项目数量,并设置查询的排序和过滤条件。

JSON 请求示例

{
    "perPage": 15,
    "page": 1,
    "orderBy": {
        "id": "asc"
    },
    "wheres": [
        {
            "column": "name",
            "condition": "like",
            "search": "%zeck%"
        },
        {
            "column": "years",
            "condition": ">",
            "search": "18"
        }
    ],
    "orWheres": [
        {
            "column": "id",
            "condition": "=",
            "search": "50"
        }
    ]
}

详情

  • page (integer):此参数用于指定要检索的结果页码。必须是一个整数。
  • perPage (integer):此参数用于指定每页要检索的项目数量。必须是一个整数。
  • orderBy (array):此参数用于指定查询的排序条件。必须是一个包含一个或多个排序条件的数组。每个排序条件是一个包含两个元素的数组:排序的列和排序方向(升序或降序)。列名将经过验证以确保它存在于由变量 $table 指定的表中,排序方向将验证以确保它是 'asc''desc'
  • wheres (array):此参数用于指定查询的过滤条件。必须是一个包含一个或多个过滤条件的数组。每个过滤条件是一个包含三个元素的数组:过滤的列、过滤条件(例如,'=', '<', '>=', 'like' 等)和要搜索的值。列名将经过验证以确保它存在于由变量 $table 指定的表中,过滤条件将验证以确保它是 $conditionsOperators 中指定的允许条件之一。
  • wheres.*.column (string):此参数是要过滤的列的名称。它是一个必需的字符串值,必须存在于模型的 $searchable 数组中,并且必须存在于由变量 $table 指定的表中。
  • wheres.*.condition (string):此参数是要用于指定列的过滤条件的条件。它是一个必需的字符串值,必须是由 $conditionsOperators 中指定的允许条件之一。
  • wheres.*.search (字符串):此参数是要在指定列中搜索的值。这是一个必需的 字符串
  • orWheres (数组):此参数用于指定查询的附加过滤条件。它的工作方式与 wheres 参数相同,但使用的是 OR 操作符来组合过滤条件,而不是 AND 操作符。
  • orWheres.*.column (字符串):此参数是要过滤的列的名称。这是一个必需的 字符串 值,必须存在于模型的 $searchable 数组中,并且必须存在于由 $table 变量指定的表中。
  • orWheres.*.condition (字符串):此参数是要用于指定列的过滤条件的条件。这是一个必需的 字符串 值,必须是 $conditionsOperators 常量指定的允许条件之一。
  • orWheres.*.search (字符串):此参数是要在指定列中搜索的值。这是一个必需的 字符串
public array $conditionsOperators = ['=', '!=', '<>', '<', '>', '<=', '>=', 'LIKE', 'NOT LIKE', 'IS NULL', 'IS NOT NULL'];
  1. 文件: ./Example/DestroyRequest.php
<?php

namespace App\Http\Requests\Example;

class DestroyRequest extends ExampleRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize(): bool
    {
        return $this->hasGroupPermission();
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules(): array
    {
        return $this->destroyRules();
    }
}

destroyRules() 方法旨在允许 BaseService 以永久方式删除资源,包括其依赖项,或执行轻量级删除。在应用 destroyRules() 方法时,只需在请求中提供 force: true 参数,结构就会以递归方式永久删除资源及其关联。如果请求中没有提供 force 参数或其值等于 false,则默认行为是仅当资源未使用时永久删除资源。如果资源正在使用中,则会执行轻量级删除。无论是永久删除(硬删除)还是轻量级删除(软删除),都是递归执行的。

JSON 请求示例

{
    "force": true
}
  1. 文件: ./Example/UpdateRequest.php
<?php

namespace App\Http\Requests\Example;

class UpdateRequest extends ExampleRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize(): bool
    {
        return $this->hasGroupPermission();
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules(): array
    {
        return [
            ...$this->updateRules()
            'field' => 'bail|required|integer',
            'field2' => 'bail|nullable|string'
        ];
    }
}

updateRules() 方法提供了一组验证,使得 BaseService 能够恢复记录及其关联。为此,只需在请求中提供 $model::DELETED_AT 作为 null,结构就会以递归方式恢复记录。

JSON 请求示例

{
    "deleted_at": null
}

BaseModel

BaseModel 类是一个抽象类,可以扩展以在 Laravel 应用中创建模型。下面是一个使用 BaseModel 类创建 Paises 模型的示例。

  1. 文件: ./Example/Paises.php
<?php

namespace App\Models;

use ArchCrudLaravel\App\Models\BaseModel;
use Illuminate\Database\Eloquent\Relations\{
    HasMany
};

class Paises extends BaseModel
{
    public $table = 'paises';
    protected $fillable = [
        'nome',
        self::DELETED_AT
    ];

    public array $searchable = [
        'nome',
        self::DELETED_AT
    ];

    public function estados(): HasMany
    {
        return $this->hasMany(Estados::class, 'paisId');
    }
}

在上面的示例中,属性 $searchable 允许您指定在通过 BaseService 类的 index() 方法进行搜索时可以搜索哪些字段。这在实现应用程序中的搜索功能时非常有用。

此外,BaseModel 类提供了 DELETED_ATUPDATED_ATCREATED_AT 常量,以允许轻松引用 Laravel 的标准时间戳。但是,您也可以通过提供包含表列名称的字符串来覆盖这些常量。

为了正确执行 $service->destroy() 方法,关系必须 必须 类型化。

BaseCollection

BaseResource

BaseService

BaseService 是由 Arch-Laravel 提供的一个类,可用于简化 Laravel 中的服务创建。下面是如何使用它的示例。

  1. 文件: ./Example/BaseService.php
<?php

namespace App\Services\Api;

use App\Http\Resources\Tratamentos\ExampleCollection;
use App\Http\Resources\Tratamentos\ExampleResource;
use App\Models\Tratamentos\Example;
use ArchCrudLaravel\App\Services\BaseService;

class ExampleService extends BaseService
{
    protected $nameModel = Example::class;
    protected $nameCollection = ExampleCollection::class;
    protected $nameResource = ExampleResource::class;
}

在此示例中,我们创建了一个名为 ExampleService 的新服务,该服务扩展了 BaseService 类。

属性

  • $nameModel:服务使用的模型类的名称。如果服务不使用模型,则不需要提供此属性。
  • $nameCollection:服务在请求多个模型实例时返回的资源集合类的名称。使用此属性是可选的。
  • $nameResource:服务在请求单个模型实例时返回的资源类的名称。使用此属性是可选的。
  • $onTransaction:控制当发生异常时数据库回滚是否执行。默认值是 true
  • $onCache:控制是否将 show()index() 方法的返回结果存储在缓存中。方法 update() 创建并更新缓存值。默认值是 true
  • $relationships:您可以插入一个包含要显示的关系的数组。可以使用 getRelationshipNames() 方法获取所有关系。默认值是 [](一个空数组)。
  • $ignoreRelationships:您可以插入一个数组,包含在 hardDelete() 方法中要忽略的关系名称。可以使用 getRelationshipNames() 方法获取所有关系。默认值是 [](一个空数组)。
  • $ignoreTypesOfRelationships:您可以插入一个数组,包含在 hardDelete() 方法中要忽略的关系类型。默认值是 [](一个空数组)。

所有这些属性都可以在 __constructor() 方法或 CRUD 方法中定义,具体取决于您的应用程序需求。

方法

BaseService 提供了一些方法,可以根据您的应用程序需求调整处理流程。

  • beforeInsert():在插入数据之前执行。
  • afterInsert():在插入数据之后执行。
  • beforeList():在列出数据之前执行。
  • afterList():在列出数据之后执行。
  • beforeSelect():在选择记录之前执行。
  • afterSelect():在选择记录之后执行。
  • beforeModify():在修改记录之前执行。
  • afterModify():在修改记录之后执行。
  • beforeDelete():在删除记录之前执行。
  • afterDelete():在删除记录之后执行。

此外,还有一些控制方法可能对您的服务中的某些情况很有用。这些方法包括

  • hasRelationships():如果模型定义了关系,则返回 true
  • getRelationshipNames():返回模型的关系名称。
  • setCustomExceptionMappings():允许自定义异常处理,以标准化 API 的响应。参数 $mappings 中的每个项必须是 CustomExceptionMapping 的实例。

优势

使用 BaseService 类带来许多优势,例如

  • 标准 CRUD 操作BaseService 提供一组标准的 CRUD 操作(创建、读取、更新和删除),这有助于在派生服务中实现这些功能。
  • 一致的响应:该类提供一组标准的响应代码,确保整个应用程序中响应的一致性和标准化。
  • 关系管理:当提供 $nameModel 属性时,BaseServicedestroy() 方法会检查资源是否被数据库中的其他实体使用,使用模型中声明的关系。如果存在链接,则默认执行软删除。但是,可以通过使用参数 force: true 来强制永久删除资源及其相关实体。
  • 软删除恢复:可以通过更新记录的 $model::DELETED_AT 字段来撤销软删除,恢复操作将以递归方式执行。

通过扩展 BaseService 类,您为应用程序的服务提供了一个坚固和一致的基础,从而加快了开发并简化了维护。

控制器

以下是如何使用由 Arch-Laravel 提供的 BaseController 与之前创建的 ExampleService 的示例

  1. 文件:./Example/BaseController.php
<?php

namespace App\Http\Controllers\Api;

use ArchCrudLaravel\App\Http\Controllers\BaseController;
use App\Http\Requests\Example\{
    DeleteRequest,
    indexRules,
    StoreRequest,
    ShowRequest,
    UpdateRequest
};
use App\Services\Api\ExampleService;
use Illuminate\Http\Response;

class ExampleController extends BaseController
{
    protected $nameService = ExampleService::class;

    // These methods are optional and correspond to standard CRUD actions
    public function store(StoreRequest $request): Response
    {
        return $this->service->store($request->validated());
    }

    public function index(IndexRequest $request): Response
    {
        return $this->service->index($request->validated());
    }

    public function show(ShowRequest $request, int $id): Response
    {
        return $this->service->show($request->validated(), $id);
    }

    public function update(UpdateRequest $request, int $id): Response
    {
        return $this->service->update($request->validated(), $id);
    }

    public function destroy(DeleteRequest $request, int $id): Response
    {
        return $this->service->destroy($request->validated(), $id);
    }

    // Additional methods for custom actions or endpoints can be defined as needed
    public function customAction(Request $request): Response
    {
        // ...
    }
}

在这个例子中,我们创建了一个名为 ExampleController 的新控制器,它扩展了 BaseController 类。我们还定义了一个属性 $nameService 来指示此控制器使用哪个服务。使用 ExampleService 服务来处理底层的 CRUD 操作,并根据操作结果返回正确的响应。

控制器中的每个方法都对应一个标准的 CRUD 操作。方法 store() 处理创建新资源,方法 index() 处理资源列表,方法 show() 处理显示特定资源,方法 update() 处理更新现有资源,方法 destroy() 处理删除现有资源。它们返回 Laravel 中 Response 类的实例,表示控制器返回的 HTTP 响应。

所有 CRUD 方法都接收一个 Request 类的实例(例如,StoreRequestUpdateRequest),用于验证和恢复客户端发送的数据。必须始终使用 $request->validated() 方法来恢复请求中的验证数据。

致谢

许可证

MIT 许可证(MIT)。有关更多信息,请参阅许可证文件