hmoe9 / tp-common
The ThinkPHP6 Common Package
1.0.5
2021-05-22 18:10 UTC
Requires
- topthink/framework: ^6.0.3
- topthink/think-helper: ^3.1
- topthink/think-migration: ^3.0.0
- topthink/think-multi-app: ^1.0
- topthink/think-orm: ^2.0.33
- topthink/think-queue: ^3.0
README
[toc]
基础
说明
该组件包基于多应用模式开发,使用前需安装多应用模式扩展。
组件安装
$ composer require hmoe9/tp-commmon
目录结构
tp-common
└─ src
├─ config.php 配置文件
│
└─package
├─ Base.php
├─ Service.php
│
├─command
│ ├─ TokenBucket.php
│ │
│ └─migrate 数据库迁移命令
│ ├─ MigrateTable.php
│ │
│ └─stubs
│ ├─ action_log.stub
│ ├─ error_log.stub
│ ├─ failed_jobs.stub
│ └─ success_jobs.stub
│
├─contract
│ ├─ DatabaseContract.php
│ ├─ JobContract.php
│ │
│ └─basic
│ ├─ ExceptionContract.php
│ ├─ LogContract.php
│ └─ ResponseContract.php
│
├─exception
│ ├─ ExceptionHandle.php 自定义异常处理类
│ └─ HttpExceptions.php http 异常处理类
│
├─job
│ └─ Base.php think-queue 队列父类
│
├─lang 语言包
│ └─zh-cn
│ ├─ error_code.php 错误码
│ └─ error_message.php 错误信息
│
├─middleware
│ ├─ SignMiddleware.php 签名校验中间件
│ └─ VerifyMiddleware.php 验证类中间件
│
├─service
│ ├─ BloomFilter.php 布隆过滤器
│ ├─ TokenBucket.php 令牌桶
│ ├─ Database.php 日志记录 db 类
│ │
│ └─basic
│ ├─ Entity.php 数据实体类
│ ├─ Exception.php 异常处理类
│ ├─ Hash.php 哈希函数类
│ ├─ Log.php 日志记录类
│ ├─ Redis.php Redis 类
│ ├─ Response.php 请求响应类
│ └─ Variable.php 自定义变量类
│
└─validate
└─ SignValidate.php 签名验证类
tp-common 配置文件
use tp\common\package\contract\basic\{ ExceptionContract, LogContract, ResponseContract }; use tp\common\package\service\basic\{ Exception, Log, Response }; return array( 'app_dev' => true, // 调试模式 'app_dev_version' => '1.0', // 调试模式匹配参数 'http_code' => 500, // 抛出异常时 http 状态码 // 校验表是否存在 // false: 如果表不存在,报错 // true: 如果表不存在,跳过日志记录操作 'table_exist_verify' => false, // 组件包使用的基础表 // stub 名 => 表名可修改(不含前缀) 'migrate_table' => array( 'action_log' => 'common_action_log', // 请求日志 'error_log' => 'common_error_log', // 异常日志 'failed_jobs' => 'common_failed_jobs', // 失败队列日志 'success_jobs' => 'common_success_jobs', // 成功队列日志 ), // 可重写方法的服务类 'bind' => array( ExceptionContract::class => Exception::class, LogContract::class => Log::class, ResponseContract::class => Response::class, ), // 日志记录时,过滤请求参数中的字段 'log_filter_field' => array( 'password', 'id_card', ), );
app_dev 调试模式说明
- 在关闭 tp 自带的 APP_DEBUG 调试模式时,可通过传参的形式动态的启用或关闭调试模式。
- 在请求数据中添加 dev_version 参数。值为 tp-common 中所配置。
数据库
迁移工具使用
配置 .env 中数据库信息
[DATABASE]
TYPE = mysql
HOSTNAME = 127.0.0.1
DATABASE = datebase
USERNAME = username
PASSWORD = root
HOSTPORT = password
CHARSET = utf8
PREFIX = t_
创建迁移文件
$ php think tp-common:migrate-table
执行数据库迁移
$ php think migrate:run
数据表说明
- action_log 请求成功记录请求信息
- error_log 请求异常时记录异常信息
- failed_jobs 队列操作失败时记录失败信息
- success_jobs 队列操作成功时记录成功信息
中间件
验证类中间件
在应用目录中添加验证配置
项目
├─ app
│ └─ 应用名
│ ├─ config
│ │ └─ verify_method.php 验证配置
│ │
│ ├─ controller
│ │ └─ index
│ │ └─ User.php
│ │
│ └─ validate
│ └─ index
│ └─ UserValidate.php 验证类明明规则(控制器名 + Validate)
├─ config
├─ extend
├─ public
├─ ...
verify_method.php 文件内容
// 控制器名,方法名不区分大小写 return array( // 多级控制器 => 方法 'index.user' => array( 'login' => 'get', // get 请求 'register' => 'post', // post 请求 ), );
User.php 控制器
namespace app\index\controller\index; use tp\common\package\middleware\VerifyMiddleware; class User { protected $middleware = array( VerifyMiddleware::class, ); public function login() { // ... } public function register() { // ... } }
UserValidate.php 验证类
namespace app\index\validate\index; class UserValidate extends \think\Validate { /** * 定义验证规则 * @var array */ protected $rule = array( 'test1' => array('require', ), 'test2' => array('require', ), ); /** * 定义错误信息 * @var array */ protected $message = array( 'test1' => array('require' => 'TEST_ERROR_1', ), 'test2' => array('require' => 'TEST_ERROR_2', ), ); /** * 定义验证场景,场景名必须小写 * @var array */ protected $scene = array( 'login' => array('test2', ), 'register' => array('test1', 'test2', ), ); }
语言包
组件自带语言包位于 src/package/zh-cn,可在应用目录中添加自定义语言包。
项目
├─ app
│ └─ 应用名
│ └─ lang
│ └─ zh-cn
│ ├─ error_code.php 错误码
│ └─ error_message.php 错误信息
│
├─ config
├─ extend
├─ public
├─ ...
error_code.php 文件内容
return array( 'TEST_ERROR_1' => '9000', 'TEST_ERROR_2' => '9001', );
error_message.php 文件内容
return array( '9000' => '测试错误信息1', '9001' => '测试错误信息2', );
队列
use tp\common\package\job\Base; use tp\common\package\contract\JobContract; use think\queue\Job; use Exception; use Throwable; class TestJob extends Base implements JobContract { public function fire(Job $job, $data): void { $this->job = $job; try { // 业务处理 ... // 操作成功日志记录 $this->success(); } catch (Exception $e) { $job->failed($e); } $job->delete(); } public function failed($data, Throwable $e): void { $this->error($e); } }
服务
常用
public $bind = array( 'exception' => ExceptionContract::class, 'response' => ResponseContract::class, 'system_log' => LogContract::class, 'redis' => Redis::class, 'var' => Variable::class, 'hash' => Hash::class, 'entity' => Entity::class, 'bloom_filter' => BloomFilter::class, 'token_bucket' => TokenBucket::class, ); // 服务的调用 // 方式一 app('服务名')->方法名(); // 方式二 // use tp\common\package\Base; $this->app->服务名->方法名();
response
public function index() { $data = array( 'key' => 'value', ); app('response')->setData($data); // 响应的数据 return app('response')->ajaxReturn(); // 支持链式操作 // return app('response')->setData($data)->ajaxReturn(); }
redis
配置 .env 中 redis 信息
[REDIS]
HOST = 127.0.0.1
PORT = 6379
PASSWORD =
TIMEOUT = 0
SELECT = 0
public function index() { $key = 'key'; $value = 'value'; app('redis')->set($key, $value); echo app('redis')->get($key); }
var
public function index() { app('var')->key = 123; echo app('var')->key; }
bloom_filter
public function index() { $value = strval('value'); app('bloom_filter')->setKey('prefix'); // 设置key app('bloom_filter')->add($value); // 添加值到过滤器中 $bool = app('bloom_filter')->has($value); // 只会返回 true 或 false,判断值是否存在过滤器中 // 支持链式操作 // $bool = app('bloom_filter')->setKey('prefix') // ->add($value) // ->has($value); }
entity
// model class OrderModel extends \think\Model { protected $name = 'order'; // 表名 // @Column: 当声明该标识时,说明属性是数据库中真实存在的字段。 // 访问修饰符为 private /** * @Column */ private $price; private $order_item; // 创建对应的 getter 和 setter 方法 public function getPrice() { return $this->price; } public function setPrice($price): void { $this->price = $price; } public function getOrderItem() { return $this->order_item; } public function setOrderItem($order_item): void { $this->order_item = $order_item; } } class OrderGoodsModel extends \think\Model { protected $name = 'order_goods'; /** * @Column */ private $goods_id; public function getGoodsId() { return $this->goods_id; } public function setGoodsId($goods_id): void { $this->goods_id = $goods_id; } } // controller class IndexController { public function index() { // 请求参数 // Content-type: application/json // body:{ // "price": 1, // "order_items": [{ // "goods_id": 1 // }, { // "goods_id": 2 // }] // } $order_obj = app('entity')->jsonToObject(OrderModel::class); // 可直接获取到对应的模型实例 $order_obj->save(); $order_goods_arr = app('entity')->mapToObject(OrderGoodsModel::class, $order_obj->getOrderItem()); foreach ($order_goods_arr as $order_goods_obj) { $order_goods_obj->save(); } } }
重写服务
// 步骤一: // 重写方法 namespace app\index\service; use tp\common\package\service\basic\Response\ResponseService; // use tp\common\package\contract\basic\ResponseContract; // 方法一: 继承组件提供的服务类重写、新增方法 // 方法二: 继承组件提供的接口类,重写方法 class Response extends ResponseService // implements ResponseContract { public function index() { echo 123; } } // 步骤二: // 替换 tp-common.php 中的 bind 数组 'bind' => array( // ... ResponseContract::class => \app\index\service\Response::class, ),
异常处理
替换异常处理类
可将 app/provider.php 中的 think\exception\Handle 替换成自定义的异常处理。
// use app\ExceptionHandle; // tp 自带异常处理 use app\Request; use tp\common\package\exception\ExceptionHandle; // 组件包定义的异常处理 // 容器 Provider 定义文件 return [ 'think\Request' => Request::class, 'think\exception\Handle' => ExceptionHandle::class, ];
异常类使用和含义
在启用调试模式时,均不会记录错误信息。关闭调试后根据抛出的异常类来进行相对于操作。
-
使用 InvalidArgumentException 和 ValidateException 抛出异常时,不会记录错误信息。
若未修改 tp-common.php 中 error_http_code,响应的 http 状态码为 500。
throw new InvalidArgumentException('TEST_ERROR_1'); // ValidateException 为 tp 验证类校验失败时调用。不需要手动调用。 // 在开启调试模式时自动行批量校验,显示所有未匹配的数据信息。 throw new ValidateException('TEST_ERROR_1');
-
使用 LogicException 抛出异常时根据异常 code 区分是否记录错误信息。
该异常 http 状态码为 200,无法修改。
无法使用语言包中定义的错误码。响应的 code 固定为 10000。错误信息可自定义。
// 异常类 code 值默认为0。 // boolval($e->getcode()) 为 true 时记录日志。 throw new LogicException('TEST_ERROR_1', '1'); // 记录日志 throw new LogicException('自定义错误信息2'); // 不记录日志
-
使用 HttpExceptions 抛出异常时可记录自定义的信息,可指定 http 状态码
注意: 这里使用的是组件包内重写的 HttpExceptions 类。
use tp\common\package\exception\HttpExceptions; $param = array( 'key' => 'custom', ); throw new HttpExceptions('TEST_ERROR_1', $param, 200);