# spes-old **Repository Path**: SimanX/spes-old ## Basic Information - **Project Name**: spes-old - **Description**: 一个简单(simple and easy)的基于attribute的模块化框架 - **Primary Language**: PHP - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2023-04-24 - **Last Updated**: 2025-09-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Spes 一个简单(simple and easy)的基于Loader驱动的模块化框架 ## 使用条件 + PHP >= 8.1 + Laravel >= 10.0 ## 安装 使用composer ```shell composer require simanx/spes ``` 如果你想要对spes的配置进行修改,可以发布配置文件到项目配置中 ```shell php artisan vendor:publish --provider="Simanx\Spes\Providers\SpesServiceProvider" ``` 得益于laravel包发现机制,SpesServiceProvider将被自动注册,如果你不希望在项目中使用该机制,则需要在config/app.php的providers数组中添加\Simanx\Spes\Providers\SpesServiceProvider::class ```php 'providers' => [ // ... /* * Package Service Providers... */ \Simanx\Spes\Providers\SpesServiceProvider::class, // ... ] ``` ## 特征 1. 基于Loader驱动的路由、事件、命令和定时任务(默认使用Attribute标记进行加载) 2. 模块化管理(旨在在一个文件夹中完成对应模块尽可能多的内容编辑) ## 使用 使用前请先查看spes的配置内容 ### Loader spes提供了基于Attribute标记的Loader #### 路由Attribute(Router, Get, Post, Patch, Put, Delete) Router Attribute有三个参数,分别指定路由的前缀,路由名前缀和路由组的共有中间件 Get等对应请求方法的Attribute的4个参数分别表示路由uri,路由名称,中间件和路由其他额外内容 **注意:只在类层面注册Router,spes不会进行路由注册,Router只指定控制器中所有路由的基础内容,目的是为了防止路由重复指定和模块的区分,对应Controller的共有方法上注册Get或其他RequestMethod方法的Attribute才会进行路由注册** ```php namespace App\Modules\Auth\Controllers; use Simanx\Spes\Attribute\Route\Attributes\Get; use Simanx\Spes\Attribute\Route\Attributes\Post; use Simanx\Spes\Attribute\Route\Attributes\Router; #[Router('/auth', 'auth', 'web')] class AuthController { #[Get('/login', 'index')] public function index() { return view('auth::index'); } #[Post('/login', 'login')] public function login(LoginRequest $request) { // ... } } ``` #### 权限Attribute(Can) Can可以为路由增加权限检测中间件, 其中权限使用PermissionManager进行管理,spes的权限与模块化深度集成,对于非模块化的路由权限,可以使用PermissionManager的add进行添加 ```php #[Router('/blog', 'blog', 'web'), Can('blog')] class BlogController { #[Get('/', 'index'), Can('index')] public function index() { return view('blog::index'); } #[Post('/create', 'create'), Can('create')] public function create() { // ... } } ``` spes也封装了纯净的request(Dto),只需要将Request类继承Simanx\Spes\Dto\Dto,设置请求对应参数内容,Spes便会从请求中获取对应参数并赋值对应Dto中的共有属性 你也可以在Dto的共有属性上指定数据类型以指导Dto解析器将对应参数 ```php class LoginRequest { // Validation(string $rule, string $message): 设置字段的验证规则,Spes将会自动解析并进行validate调用 #[\Simanx\Spes\Validation\Attributes\Validation('required|max:16', '账号必填且长度最大为16')] public string $account; // 指定数据类型(内置类型|Dto)以引导Dto解析器将参数解析为指定类型 #[\Simanx\Spes\Validation\Attributes\Validation('required|max:16', '密码必填且长度最大为16')] public string $password; } #[Router('/auth')] class AuthController { #[Post('/login')] public function login(LoginRequest $request) { // $request->account; // $request['account']; // $request->toArray(); // $request->toJson(); } } ``` #### 事件Attribute(Listen) spes会进行对应Listener进行监听,并且根据第二个参数指定的参数进行优先级排序(值越大越先监听) ```php use Simanx\Spes\Attribute\Event\Attributes\Listen; #[Listen(SomeEvent::class), Listen(SomeEvent2::class, 999)] class SomeEventListener { public function handle() { } } ``` #### Artisan命令Attribute(ArtisanCommand) spes会自动进行对应command的注册 ```php #[ArtisanCommand] class CreateUserCommand extends Command { protected $signature = 'app:create-user'; protected $description = '...'; public function handle() { // ... } } ``` #### Crontab Attribute(Cron) spes会对对应的cron进行定时任务注册(cron的类必须是一个command) ```php #[Cron('* * * * *')] class SomeCronCommand extends Command { // ... } ``` #### 自定义Loader 你也可以轻易地自定义Loader 假设你想从对应文件夹下面的route.php中进行路由的创建,你可以使用如下方法创建 创建加载器继承 Simanx\Spes\Attribute\Loader 并且重写load方法 ```php class MyRouteLoader extends \Simanx\Spes\Attribute\AttributeLoader { public function load() { foreach($this->files() as $file) { if (! ($this->app instanceof CachesRoutes && $this->app->routesAreCached())) { require $file->getRealPath(); } } } } ``` 将RouteAttributeLoader在spes配置文件中进行注册 ```php // config/spes.php return [ // ... 'loaders' => [ MyRouteLoader::class => [ 'path' => [ app_path('Http/Routes/') ], 'name' => 'route.php' ], ], // ... ] ``` #### 模块化 框架实现了简单的项目模块化管理,默认以 app/Modules/ 作为项目模块的根目录,你可以在spes配置文件中修改对应文件夹及其对应文件夹类型映射 spes将模块根目录下的一级目录名作为模块名,下面这个文件结构将作为两个模块(Auth和User),模块下的文件夹分别管理模块的部分内容(Controllers管理控制器,Commands管理模块特有命令等) + app + Modules + Auth + Controllers + Listeners + Commands + Components + Views + login.blade.php + Schedules + User 有些应用只提供api访问,而不需要对应view和component,则可以在spes配置文件中将view设置为false,spes将不会进行view和component的注册 默认,spes会对模块中的部分文件夹进行Attribute扫描,如:对Controllers下的对应类进行Router Attribute和对应请求方法的Attribute进行扫描,注册对应路由 ```php // app/Modules/Auth/AuthController.php #[Router('/auth', middleware: 'web')] class AuthController { #[Get('/login', 'login')] public function index() { return view('auth::login'); // 返回Auth模块下的 Views/login.blade.php } // ... } ``` ### 命令行支持 ```php spes:make-module // 创建模块,将创建对应dirs ``` #### 参与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request