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)。有关更多信息,请参阅许可证文件。