landao/webman-core

Webman plugin landao/webman-core

v1.0.6 2025-08-13 04:41 UTC

This package is auto-updated.

Last update: 2025-08-13 04:52:04 UTC


README

  • landao/webman-core 已实现的模块有 路由注解、验证器注解、数据迁移、数据填充、枚举注解、命令生(model, migrate, seeder,validate,enum,Repository,)。

1、环境和安装

  • 在使用扩展前,先安装 composer require webman/console

1.1. 环境要求

2、注解使用

  • 框架使用注解,需要先在 config/plugin.php 中开启 landao/webman-core 插件 config/plugin/landao.webman-core.app
//annotation.route
 "annotation" => [
    //路由注解
    'route' => [
        'enable' => true,
        // 扫描的目录
        'directories' => [
            app_path('controller') => [
            ],
            base_path('plugin/system/app/controller/admin') => [
                'prefix' => '/admin-api/system',// 路由前缀
                'as'=>'system:',// 路由别名
                'namespace' => 'plugin\system\app\controller\admin\\'// 控制器命名空间
            ]
        ],
    ],
],

2.1. 路由注解

  • 在控制器中使用以下注解,快速创建一条路由

Tips: 需要 plugin.landao.webman-core.app.annotation.route.enable 开启 和 plugin.landao.webman-core.app.annotation.route.directories 扫描路径,否则将被排除扫描

<?php

namespace app\controller;

use Landao\WebmanCore\Annotation\Router\Get;
use Landao\WebmanCore\Annotation\Router\Group;
use Landao\WebmanCore\Annotation\Router\Post;
use support\Request;
use support\Response;

#[Group('/user')]
class UserController
{
    #[Get('/index')]
    public function index()
    {
        try {
            // 假设这里有一些业务逻辑
            $response = [
                'status' => 'success',
                'message' => 'Welcome to the user page!'
            ];

            return json($response);
        } catch (\Exception $e) {
            // 记录异常日志
            Log::error($e->getMessage());

            // 返回错误响应
            return json(['status' => 'error', 'message' => 'An error occurred'], 500);
        }
    }

    #[Post('/test/123')]
    public function test(): Response
    {
        return json('ceshi');
    }


}

2.2 验证器

2.2.1. 使用Validation注解快速开启一个验证器

<?php

namespace app\controller;

use Landao\WebmanCore\Annotation\Router\Get;
use Landao\WebmanCore\Annotation\Router\Group;
use Landao\WebmanCore\Annotation\Router\Post;
use Landao\WebmanCore\Annotation\Validation;
use Landao\WebmanCore\Annotation\Validation\Required;
use Landao\WebmanCore\Annotation\Validation\Regex;
use Landao\WebmanCore\Http\FormRequest;
use support\Log;
use support\Request;
use support\Response;

#[Group('/user')]
class UserController
{

    #[Post('/test/123')]
//    #[Regex("message", ruleValue: "~^\w+$~", attribute: "留言")]
    #[Validation(field: "message", rule: "required", attribute: "留言", message: ":attribute不能为空")]
    #[Validation(field: "title", rule: "required", attribute: "标题", message: ":attribute不能为空")]
    public function test(FormRequest $request): Response
    {
//        $validator = $request->validate([
//            'title' => 'required|unique:posts|max:255',
//            'body' => 'required',
//        ],
//            [
//                'title.required' => ':attribute不能为空',
//            ], [
//                'title' => '标题',
//            ]);
        return json('ceshi');
    }


    #[Post('/test/12')]
    #[Validation(class: UserRequest::class)]
    public function test2(FormRequest $request):Response
    {
        return json('ceshi2');
    }
}

2.2.1. 创建验证器类

不支持 unique、exists 等

<?php

namespace app\controller;


use Landao\WebmanCore\Validation\Validate;

class UserRequest extends Validate
{

    protected array $rules = [
        "title" => ["required", "alpha_dash"],
        "message" => 'required|callback:checkSafeTags',
    ], $attributes = [
        "username" => "用户名",
        "message" => "留言",
    ];
    
    /**
    * 自定义回调验证 
    * @return bool
    */
    protected function checkSafeTags() :bool
    {
        if(str_contains($this->data['message'],'<script'))
            return false;
        return true;
    }
}
<?php

namespace app\controller;

use Landao\WebmanCore\Annotation\Router\Get;
use Landao\WebmanCore\Annotation\Router\Group;
use Landao\WebmanCore\Annotation\Router\Post;
use Landao\WebmanCore\Annotation\Validation;
use Landao\WebmanCore\Annotation\Validation\Required;
use Landao\WebmanCore\Annotation\Validation\Regex;
use Landao\WebmanCore\Http\FormRequest;
use support\Log;
use support\Request;
use support\Response;

#[Group('/user')]
class UserController
{


    #[Post('/test/12')]
    #[Validation(class: UserRequest::class)]
    public function test2(FormRequest $request):Response
    {
        return json('ceshi2');
    }
}

3 数据迁移

3.1. 生成数据迁移文件

  • fields 选项允许你指定表的字段结构
  • plain 选项是一个布尔值选项,用于创建一个空白的迁移文件,不包含任何预设的表结构。当你需要编写一些特殊的数据库操作时,这个选项很有用。
# 创建带多个字段的用户表
php webman landao:make-migrate create_users_table --fields="name:string:nullable,email:string:unique,password:string,age:integer:unsigned"

# 创建带默认值的配置表
php webman landao:make-migrate create_settings_table --fields="key:string:unique,value:text,is_enabled:boolean:default:1"

# 添加字段到现有表
php webman landao:make-migrate add_columns_to_users_table --fields="phone:string:nullable,address:text"

# 删除字段到现有表

php webman landao:make-migrate delete_columns_to_users_table --fields="phone:string:nullable,address:text"

# 删除数据表的迁移文件
php webman landao:make-migrate drop_posts_table --fields="title:string,content:text"

3.2. 执行数据迁移

# 运行迁移
php webman landao:migrate

# 运行迁移并填充数据
php webman landao:migrate --seed

# 仅预览 SQL(不执行)
php webman landao:migrate --pretend

# 回滚最后一次迁移
php webman landao:migrate-rollback

# 回滚最后 3 次迁移
php webman landao:migrate-rollback --step=3

# 回滚所有迁移
php webman landao:migrate-rollback --all

3.3. 执行数据回滚迁移

# 回滚最后一次迁移
php webman landao:migrate-rollback

# 回滚最后 3 次迁移
php webman landao:migrate-rollback --step=3

# 回滚所有迁移
php webman landao:migrate-rollback --all

4、数据填充

4.1. 生成数据填充文件

Tips: 首次使用seeder,请手动创建 DatabaseSeeder 基础数据填充类

# 首次使用seeder,请手动创建 DatabaseSeeder 基础数据填充类
php webman landao:make-seeder DatabaseSeeder


php webman landao:make-seeder UserSeeder

4.2.执行数据填充

# 运行默认的 DatabaseSeeder
php webman landao:seeder

# 运行指定的 Seeder
php webman landao:seeder --class=UserSeeder

5、命令生成文件

5.1 生成枚举文件

生成枚举类名自动追加后缀 Enum

# 主应用生成枚举, 默认生成在 app/enums 目录下, 
php webman landao:make-enum UserStatus

# 主应用生成枚举, 默认生成在 app/enums 目录下, 并指定子目录
php webman landao:make-enum System\\UserStatus

# webman 插件plugin 生成枚举, foo 生成在 plugin/foo/app/enums 目录下,
php webman landao:make-enum UserStatus --plugin=foo

# 多应用生成枚举,--multi-app=api 生成在 app/api/enums 目录下, 
php webman landao:make-enum UserStatus --multi-app=api

5.2 生成 Repository

注意:该命令会附带生成对应的 Model,生成类名自动追加后缀 Repo

# 主应用生成,默认生成在 app/repositories,app/models 目录下,
php webman landao:make-repo User

# 主应用生成,默认生成在 app/repositories/System,app/models/System 目录下,
php webman landao:make-repo Seytem\\User

# webman 插件plugin 生成, foo 生成在 plugin/foo/app/repositories/System,app/models/System 目录下,
php webman landao:make-repo User --plugin=foo

# 多应用生成,,--multi-app=api 生成在 app/api/repositories,app/api/models 目录下, 
php webman landao:make-repo User --multi-app=api

5.3 生成 Model

注意:该命令生成类名自动追加后缀 Model

# 主应用生成,默认生成在 app/models 目录下,
php webman landao:make-model User

# 主应用生成,默认生成在 app/models/System 目录下,
php webman landao:make-model Seytem\\User

# webman 插件plugin 生成, foo 生成在 papp/models/System 目录下,
php webman landao:make-model User --plugin=foo

# 多应用生成,,--multi-app=api 生成在 app/api/models 目录下, 
php webman landao:make-model User --multi-app=api

5.4 生成验证器

注意:该命令生成类名自动追加后缀 Request,注解使用:#[Validation(class: UserRequest::class)]

# 主应用生成,默认生成在 app/requests 目录下,
php webman landao:make-request User

# 主应用生成,默认生成在 app/requests/System 目录下,
php webman landao:make-request Seytem\\User

# webman 插件plugin 生成, foo 生成在 papp/requests/System 目录下,
php webman landao:make-request User --plugin=foo

# 多应用生成,,--multi-app=api 生成在 app/api/requests 目录下, 
php webman landao:make-request User --multi-app=api

6、Exception 异常

6.1 异常接管

配置 config/exception.php 插件配置,例如:/plugin/system/config/exception.php

return [
    '' => \Landao\WebmanCore\Exceptions\LanDaoException::class,//support\exception\Handler::class,
];

6.2 输出错误信息

配置 config/app.php 开启调试模式

{
    "code": 401,
    "msg": "账号或密码错误",
    "data": {
        "domain": "127.0.0.1:8787",
        "method": "POST",
        "request_url": "POST /admin-api/system/auth/login?tenantName=****&username=peadmin&password=123456qwe@A2&code=brmam&captchaKey=$2y$10$bNg0RzZkvzhkBr8XZiSDJOJTjwFc8pdTd7LJ1a5E6ywF4t.KUCwgm",
        "timestamp": "2025-07-14 16:41:21",
        "client_ip": "172.0.0.1",
        "request_param": {
            "tenant_name": "****",
            "username": "peadmin",
            "password": "****",
            "code": "brmam",
            "captcha_key": "$2y$10$bNg0RzZkvzhkBr8XZiSDJOJTjwFc8pdTd7LJ1a5E6ywF4t.KUCwgm"
        },
        "error_message": "账号或密码错误",
        "error_trace": [
            "#0 /www/php/landao/webman/plugin/system/app/controller/admin/auth/AuthController.php(54): plugin\\system\\app\\repositories\\UserRepo->doLogin('\\xE6\\x99\\xBA\\xE6\\xB1\\x87\\xE9\\x80\\x9A\\xE8\\xBD\\xAF\\xE4\\xBB\\xB6', 'peadmin', '****', 'WEB')",
            "#20 {main}"
        ],
        "file": "/www/php/landao/webman/plugin/system/app/repositories/UserRepo.php",
        "line": 64
    }
}

不开启调试,返回

{
    "code": 401,
    "msg": "账号或密码错误",
    "data": []
}

6.3 自定义业务错误码

throw new UnauthorizedHttpException('账号或密码错误',['errorCode'=>40001]);

返回数据

{
    "code": 40001,
    "msg": "账号或密码错误",
    "data": []
}

6.4 统一业务异常处理,api直接返回

异常枚举定义

替换消息中的占位符,支持 {} 或 {0}, {1} 等格式

<?php

namespace plugin\system\app\enum;

use Landao\WebmanCore\Exceptions\ErrorCodeInterface;
use Landao\WebmanCore\Annotation\Description;
use Landao\WebmanCore\Enum\EnumExtend;

/**
 * 错误码枚举
 * 错误码规则:模块编号-功能编号-错误码编号-错误码序号 1_002_001_000
 */
enum ErrorCodeConstants: int implements ErrorCodeInterface
{
    use EnumExtend;

    // ========== 菜单模块 1-002-001-000 ==========
    #[Description('已经存在该名字的菜单')]
    case MENU_NAME_DUPLICATE = 1_002_001_000;
    #[Description('父菜单({})不存在<{}>')]
    case MENU_PARENT_NOT_EXISTS = 1_002_001_001;
    
    #[Description('不能设置{0}自己为父菜单{1}')]
    case MENU_PARENT_ERROR = 1_002_001_002;
    


    public function getValue(): int
    {
        return $this->value;
    }
}

抛出异常使用例子

ExceptionFactory::throwBusinessException(ErrorCodeConstants::MENU_NAME_DUPLICATE);
// 支持 {} 格式(按顺序替换)
ExceptionFactory::throwBusinessException(ErrorCodeConstants::MENU_PARENT_NOT_EXISTS, '新增');
// 支持 {0}, {1} 等索引格式
ExceptionFactory::throwBusinessException(ErrorCodeConstants::MENU_PARENT_ERROR, '新增','新增1');

7、枚举注解、枚举转换

方法:

  • static getMap() : 获取所有枚举键值对
  • static getKeys() : 获取所有枚举键
  • static getValues() : 获取所有枚举值
  • static include(string $value): bool : 检查键是否存在
  • static includeAll(array $names): bool : 检查多个键是否存在
  • equal() : 判断持久层返回的值是否相同
  • getEnumLabel(): stirng : 获取枚举注解说明
  • static getEnumMapLabel(): array : 获取枚举值和注解说明数组
  • static hasValue(mixed $value): bool: 判断值是否包含在枚举value中
  • static hasAllValues(array $values): bool: 判断多个值是否都包含在枚举value中
  • equals(self $enum): bool : 比较两个枚举实例是否相同
  • valueEquals(mixed $value): bool : 比较枚举值是否与给定值相同 使用示例:
// 假设我们有一个StatusEnum枚举
$status = StatusEnum::ENABLE;

// 比较两个枚举实例
$status->equals(StatusEnum::ENABLE); // true
$status->equals(StatusEnum::DISABLE); // false

// 比较枚举值
$status->valueEquals(1); // 如果ENABLE的值是1,则返回true
$status->valueEquals('active'); // 如果ENABLE的值是'active',则返回true

8、注解脱敏

<?php

namespace plugin\system\app\controller;

use Landao\WebmanCore\Annotation\Desensitize;
use Landao\WebmanCore\Traits\ApiResponse;
use support\Request;


#[Desensitize(field: 'mobile', rule: 'mobile')]
#[Desensitize(field: 'email', rule: ['pattern' => '/(.{3})[\w\-]+@/', 'replacement' => '$1***@'])]
#[Desensitize(field: 'user_indo.mobile', rule: 'mobile')]
#[Desensitize(field: 'user_indo.email', rule: ['pattern' => '/(.{3})[\w\-]+@/', 'replacement' => '$1***@'])]
#[Desensitize(field: 'user_indo.chaer.mobile', rule: 'mobile')]
#[Desensitize(field: 'user_indo.chaer.email', rule: ['pattern' => '/(.{3})[\w\-]+@/', 'replacement' => '$1***@'])]
class IndexController
{
    use ApiResponse;

//    #[Desensitize(field: 'id_card', rule: ['pattern' => '/(\d{6})\d{8}(\d{4})/', 'replacement' => '$1********$2'])]
    public function index()
    {
//        return $this->success([
//            'mobile' => '13800138000',
//            'email' => 'test@example.com',
//            'id_card' => '110101199001011234',
//            'user_indo'=>[
//                'mobile' => '13800138000',
//                'email' => 'test@example.com',
//                'id_card' => '110101199001011234',
//                'chaer'=>[
//                    'mobile' => '13800138000',
//                    'email' => 'test@example.com',
//                    'id_card' => '110101199001011234',
//                ]
//            ]
//        ]);
//        return $this->success([
//            [
//                'mobile' => '13800138000',
//                'email' => 'test@example.com',
//                'id_card' => '110101199001011234',
//            ],
//            [
//                'mobile' => '13800138000',
//                'email' => 'test@example.com',
//                'id_card' => '110101199001011234',
//            ],
//            [
//                'mobile' => '13800138000',
//                'email' => 'test@example.com',
//                'id_card' => '110101199001011234',
//            ]
//        ]);
        return $this->success([
            'page'=>1,
            'list'=>[
                [
                    'mobile' => '13800138000',
                    'email' => 'test@example.com',
                    'id_card' => '110101199001011234',
                    'user_info'=>[
                        'mobile' => '13800138000',
                        'email' => 'test@example.com',
                    ]
                ],
                [
                    'mobile' => '13800138000',
                    'email' => 'test@example.com',
                    'id_card' => '110101199001011234',
                ],
                [
                    'mobile' => '13800138000',
                    'email' => 'test@example.com',
                    'id_card' => '110101199001011234',
                ]
            ]
        ]);
    }

}