allyson / arch-laravel
为 Laravel 项目提供的 CRUD 架构。
Requires
- php: ^8.2
- guzzlehttp/guzzle: ^7.2
- laravel/framework: ^10.10
- laravel/sanctum: ^2.14.1|^3.0
- laravel/tinker: ^2.7
Requires (Dev)
- fakerphp/faker: ^1.9.1
- laravel/sail: ^1.0.1
- mockery/mockery: ^1.4.4
- nunomaduro/collision: ^6.1
- phpunit/phpunit: ^9.5.10
- spatie/laravel-ignition: ^1.0
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
- 文件:
./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(),这些方法可以根据应用程序需求和业务规则进行实现,以授权对资源的访问和使用。
- 文件:
./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'];
- 文件:
./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
}
- 文件:
./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 模型的示例。
- 文件:
./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_AT、UPDATED_AT 和 CREATED_AT 常量,以允许轻松引用 Laravel 的标准时间戳。但是,您也可以通过提供包含表列名称的字符串来覆盖这些常量。
为了正确执行 $service->destroy() 方法,关系必须 必须 类型化。
BaseCollection
BaseResource
BaseService
BaseService 是由 Arch-Laravel 提供的一个类,可用于简化 Laravel 中的服务创建。下面是如何使用它的示例。
- 文件:
./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属性时,BaseService的destroy()方法会检查资源是否被数据库中的其他实体使用,使用模型中声明的关系。如果存在链接,则默认执行软删除。但是,可以通过使用参数force: true来强制永久删除资源及其相关实体。 - 软删除恢复:可以通过更新记录的
$model::DELETED_AT字段来撤销软删除,恢复操作将以递归方式执行。
通过扩展 BaseService 类,您为应用程序的服务提供了一个坚固和一致的基础,从而加快了开发并简化了维护。
控制器
以下是如何使用由 Arch-Laravel 提供的 BaseController 与之前创建的 ExampleService 的示例
- 文件:
./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 类的实例(例如,StoreRequest 或 UpdateRequest),用于验证和恢复客户端发送的数据。必须始终使用 $request->validated() 方法来恢复请求中的验证数据。
致谢
许可证
MIT 许可证(MIT)。有关更多信息,请参阅许可证文件。