This commit is contained in:
2024-07-10 17:24:15 +08:00
parent f3f1ff211b
commit 08ca839caf
962 changed files with 231139 additions and 0 deletions

8
digital_doctor_admin/.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
.idea
/.vscode
#/vendor
*.log
#thinkphp
.env
.DS_Store
.well-known

View File

@@ -0,0 +1,42 @@
sudo: false
language: php
branches:
only:
- stable
cache:
directories:
- $HOME/.composer/cache
before_install:
- composer self-update
install:
- composer install --no-dev --no-interaction --ignore-platform-reqs
- zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip .
- composer require --update-no-dev --no-interaction "topthink/think-image:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0"
- composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0"
- zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip .
script:
- php think unit
deploy:
provider: releases
api_key:
secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw=
file:
- ThinkPHP_Core.zip
- ThinkPHP_Full.zip
skip_cleanup: true
on:
tags: true

View File

@@ -0,0 +1,946 @@
## V5.1.41 LTS2021-1-11
本版本为PHP8兼容更新
## V5.1.40 LTS2020-10-09
本版本为常规更新,主要包括:
* 改进redis驱动`has`方法
* 修正XA事务
* 修正`HasManyThrough`关联
* 增加mysql json类型字段->>方式获取支持
* 改进路由加载 避免加载编辑器临时文件影响
* 修复关联模型的属性直接附加到当前模型,当关联模型字段名为name时获取的值为模型的属性name值
* 修复多态关联预加载`field`无效
* 改进Collection类的`column`方法的PHP兼容性问题
* 改进mysql驱动
* 改进`parseclosure`方法
* SoftDelete删除条件做空判断
* 改进验证类`append`方法
## V5.1.39 LTS2019-11-18
本次更新为常规更新,主要包括:
* 修正`memcached`驱动
* 改进`HasManyThrough`关联查询
* 改进`Request``isJson`方法
* 改进关联查询
* 改进`redis`驱动
* 增加 Model类`getWhere`方法对复合主键的支持
* 改进`newQuery`方法
* 改进闭包查询的参数绑定
* 修正`Validate`
* 修复某些情况下URL会多一个冒号
* 调整composer.json
* 修复使用`Cache::clear()`时,报错缓存文件不存在问题
* 使用File类的unlink方法进行文件删除
* 改进`paraseData`方法
* 修正image验证方法
* 改进Url生成
* 改进空操作对数字的支持
* 改进一处PHP7.4兼容性问题
## V5.1.38 LTS2019-8-8
本次更新为常规更新,主要包括:
* `Request`类增加`isJson`方法
* 改进浮点型查询
* 修正关联查询关联外键为空的查询错误
* 远程一对多支持关联统计和预载入查询
* 远程一对多关联支持`has`/`hasWhere`查询
* 优化`parseIn`解析
* 改进`parseLike`查询
* 改进Url生成
* 改进模型的`toArray`方法
* 修正`notIn`查询
* 改进`JSON`字段查询
* 改进Controller类`display`/`fetch`方法返回`ViewResponse`对象
* 改进`param`方法
* 改进`mysql`驱动`getExplain`方法
* 改进时间查询
* 改进模型关联的`has`/`hasWhere`方法对软删除的支持
* 修正社区反馈的BUG
## V5.1.37 LTS2019-5-26
本次更新为常规更新,主要更新如下:
* 改进关联数据更新
* 修正关联动态获取器
* 改进`redis`驱动
* 修复验证规则里面出现二维数组时的错误
* 改进跨域请求支持
* 完善模型`hidden`方法对关联属性的支持
* 改进`where`查询方法传入`Query`对象的支持`bind`数据
* 改进数据集对象的`load`方法
* 修正缓存类`clear`方法对`tag`的支持
## V5.1.36 LTS2019-4-28
本次更新为常规更新,主要更新如下:
* 修正`chunk`方法一处异常抛出的错误
* 修正模型输出的`visible`
* 改进环境变量加载
* 改进命令行日志的`level`配置支持
* 修复设置有缓存前缀时,无法清空缓存标签的问题
* HasMony对象`saveAll`方法兼容`Collection`格式参数格式
* 修正`whereOr`查询使用字符串的问题
* 改进`dateFormat`设置对写入数据的影响
* 修正查询缓存
* 记住指定的跳转地址
* 改进软删除
* 改进聚合查询SQL去除limit 1
* 改进缓存驱动
## V5.1.35 LTS2019-3-2
本次主要为常规更新,修正了一些反馈的问题。
* 修正验证类自定义验证方法执行两次的问题
* 模型增加`isEmpty`方法用于判断是否空模型
* 改进获取器对`append`的支持
* 修正一对多关联的`withCount`自关联问题
* facade类注释调整
* 改进关联属性的`visible``hidden`判断
* 修正路由分组的`MISS`路由
* 改进pgsql.sql
## V5.1.34 LTS2019-1-30
本次更新为常规更新,修正了一些反馈的问题。
* 改进Request类的`has`方法,支持`patch`
* 改进`unique`验证的多条件支持
* 修复自定义上传验证,检测文件大小
* 改进`in`查询支持表达式
* 改进路由的`getBind`方法
* 改进验证类的错误信息获取
* 改进`response`助手函数默认值
* 修正mysql的`regexp`查询
* 改进模型类型强制转换写入对`Expression`对象的支持
## V5.1.33 LTS2019-1-16
* 修复路由中存在多个相同替换的正则BUG
* 修正whereLike查询
* join方法支持参数绑定
* 改进union方法
* 修正多对多关联的attach方法
* 改进验证类的正则规则自定义
* 改进Request类method方法
* 改进File日志类型的CLI日志写入
* 改进文件日志time_format配置对JSON格式的支持
## V5.1.32 LTS2018-12-24
本次主要为常规更新,修正了一些反馈的问题。
* 改进多对多关联的`attach`方法
* 改进聚合查询的`field`处理
* 改进关联的`save`方法
* 修正模型`exists`方法返回值
* 改进时间字段写入和输出
* 改进控制器中间件的调用
* 改进路由变量替换的性能
* 改进缓存标签的处理机制
## V5.1.31 LTS (2018-12-9)
本次版本包含一个安全更新,建议升级。
* 改进`field`方法
* 改进`count`方法返回类型
* `download`函数增加在浏览器中显示文件功能
* 修正多对多模型的中间表数据写入
* 改进`sqlsrv`驱动支持多个Schemas模式查询
* 统一助手函数与\think\response\Download函数文件过期时间
* 完善关联模型的`save`方法 增加`make`方法仅创建对象不保存
* 修改条件表达式对静态变量的支持
* 修正控制器名获取
* 改进view方法的`field`解析
## V5.1.30 LTS2018-11-30
该版本为常规更新,修正了一些社区反馈的问题。
主要更新如下:
* 改进查询类的`execute`方法
* 判断路由规则定义添加对请求类型的判断
* 修复`orderRaw`异常
* 修正 `optimize:autoload`指令
* 改进软删除的`destroy`方法造成重复执行事件的问题
* 改进验证类对扩展验证规则 始终验证 不管是否`require`
* 修复自定义验证`remove`所有规则的异常
* 改进时间字段的自动写入支持微秒数据
* 改进`Connection`类的`getrealsql`方法
* 修正`https`地址的URL生成
* 修复 `array_walk_recursive` 在低于PHP7.1消耗内部指针问题
* 改进手动参数绑定使用
* 改进聚合查询方法的`field`参数支持`Expression`
## V5.1.29 LTS2018-11-11
该版本主要改进了参数绑定的解析问题和提升性能,并修正了一些反馈的问题。
* 改进手动参数绑定
* 修正MISS路由的分组参数无效问题
* 行为支持对象的方法
* 修正全局查询范围
* 改进`belongsto`关联的`has`方法
* 改进`hasMany`关联
* 改进模型观察者多次注册的问题
* 改进`query`类的默认查询参数处理
* 修正`parseBetween`解析方法
* 改进路由地址生成的本地域名支持
* 改进参数绑定的实际URL解析性能
* 改进`Env`类的`getEnv``get`方法
* 改进模板缓存的生成优化
* 修复验证类的多语言支持
* 修复自定义场景验证`remove`规则异常
* File类添加是否自动补全扩展名的选项
* 改进`strpos`对子串是否存在的判断
* 修复`choice`无法用值选择第一个选项问题
* 验证器支持多维数组取值验证
* 改进解析`extend``block`标签的正则
## V5.1.28 LTS2018-10-29
该版本主要修正了上一个版本存在的一些问题,并改进了关联查询
* 改进聚合查询方法的字段支持DISTINCT
* 改进定义路由后url函数的端口生成
* 改进控制器中间件对`swoole`等的支持
* 改进Log类`save`方法
* 改进验证类的闭包验证参数
* 多对多关联支持指定中间表数据的名称
* 关联聚合查询支持闭包方式指定聚合字段
* 改进Lang类`get`方法
* 多对多关联增加判断关联数据是否存在的方法
* 改进关联查询使用`fetchsql`的情况
* 改进修改器的是否已经执行判断
* 增加`afterWith``beforeWith`验证规则 用于比较日期字段
## V5.1.27 LTS2018-10-22
该版本主要修正了路由绑定的参数改进了修改器的执行多次问题并正式宣布为LTS版本
* 修正路由绑定的参数丢失问题
* 修正路由别名的参数获取
* 改进修改器会执行多次的问题
## V5.1.262018-10-12
该版本主要修正了上一个版本的一些问题,并改进了全局查询范围的支持,同时包含了一个安全更新。
* 修正单一模块下注解路由无效的问题
* 改进数据库的聚合查询的字段处理
* 模型类增加`globalScope`属性定义 用于指定全局的查询范围
* 模型的`useGlobalScope`方法支持传入数组 用于指定当前查询需要使用的全局查询范围
* 改进数据集的`order`方法对数字类型的支持
* 修正上一个版本`order`方法解析的一处BUG
* 排序字段不合法或者错误的时候抛出异常
* 改进`Request`类的`file`方法对上传文件的错误判断
## V5.1.252018-9-21
该版本主要改进了查询参数绑定的性能和对浮点型的支持,以及一些细节的完善。
* 修正一处命令行问题
* 改进`Socketlog`日志驱动,支持自定义默认展开日志类别
* 修正`MorphMany`一处bug
* 跳转到上次记住的url并支持默认值
* 改进模型的异常提示
* 改进参数绑定对浮点型的支持
* 改进`order`方法解析
* 改进`json`字段数据的自动编码
* 改进日志`log_write`可能造成的日志写入死循环
* Log类增加`log_level`行为标签位置,用于对某个类型的日志进行处理
* Route类增加`clear`方法清空路由规则
* 分布式数据库配置支持使用数组
* 单日志文件也支持`max_files`参数
* 改进查询参数绑定的性能
* 改进别名路由的URL后缀参数检测
* 控制器前置方法和控制器中间件的`only``except`定义不区分大小写
## V5.1.242018-9-5
该版本主要增加了命令行的表格输出功能,并增加了查看路由定义的指令,以及修正了社区的一些反馈问题。
* 修正`Request`类的`file`方法
* 修正路由的`cache`方法
* 修正路由缓存的一处问题
* 改进上传文件获取的异常处理
* 改进`fetchCollection`方法支持传入数据集类名
* 修正多级控制器的注解路由生成
* 改进`Middleware``clear`方法
* 增加`route:list`指令用于[查看定义的路由](752690) 并支持排序
* 命令行增加`Table`输出类
* `Command`类增加`table`方法用于输出表格
* 改进搜索器查询方法支持别名定义
* 命令行配置增加`auto_path`参数用于定义自动载入的命令类路径
* 增加`make:command`指令用于[快速生成指令](354146)
* 改进`make:controller`指令对操作方法后缀的支持
* 改进命令行的定义文件支持索引数组 用于指令对象的惰性加载
* 改进`value``column`方法对后续查询结果的影响
* 改进`RuleName`类的`setRule`方法
## V5.1.232018-8-23
该版本主要改进了数据集对象的处理,增加了`findOrEmpty`方法并且修正了一些社区反馈的BUG。
* 数据集类增加`diff`/`intersect`方法用于获取差集和交集(默认根据主键值比较)
* 数据集类增加`order`方法支持指定字段排序
* 数据集类增加`map`方法使用回调函数处理数据并返回新的数据集对象
* Db增加`allowEmpty`方法允许`find`方法在没有数据的时候返回空数组或者空模型对象而不是null
* Db增加`findOrEmpty`方法
* Db增加`fetchCollection`方法用于指定查询返回数据集对象
* 改进`order`方法的数组方式解析,增强安全性
* 改进`withSearch`方法,支持第三个参数传入字段前缀标识,用于多表查询字段搜索
* 修正`optimize:route`指令开启类库后缀后的注解路由生成
* 修正redis缓存及session驱动
* 支持指定`Yaconf`的独立配置文件
* 增加`yaconf`助手函数用于配置文件
## V5.1.222018-8-9
该版本主要增加了模型搜索器和`withJoin`方法,完善了模型输出和对`Yaconf`的支持修正了一些社区反馈的BUG。
* 改进一对一关联的`table`识别问题
* 改进内置`Facade`
* 增加`withJoin`方法支持`join`方式的[一对一关联](一对一关联.md)查询
* 改进`join`预载入查询的空数据问题
* 改进`Config`类的`load`方法支持快速加载配置文件
* 改进`execute`方法和事务的断线重连
* 改进`memcache`驱动的`has`方法
* 模型类支持定义[搜索器](搜索器.md)方法
* 完善`Config`类对`Yaconf`的支持
* 改进模型的`hidden/visible/append/withAttr`方法,支持在[查询前后调用](数组访问.md),以及支持数据集对象
* 数据集对象增加`where`方法根据字段或者关联数据[过滤数据](模型数据集.md)
* 改进AJAX请求的`204`判断
## V5.1.212018-8-2
该版本主要增加了下载响应对象和数组查询对象的支持,并修正了一些社区反馈的问题。
* 改进核心对象的无用信息调试输出
* 改进模型的`isRelationAttr`方法判断
* 模型类的`get``all`方法并入Db类
* 增加[下载响应对象](文件下载.md)和`download`助手函数
* 修正别名路由配置定义读取
* 改进`resultToModel`方法
* 修正开启类库后缀后的注解路由生成
* `Response`类增加`noCache`快捷方法
* 改进路由对象在`Swoole`/`Workerman`下面参数多次合并问题
* 修正路由`ajax`/`pjax`参数后路由变量无法正确获取的问题
* 增加清除中间件的方法
* 改进依赖注入的参数规范自动识别(便于对接前端小写+下划线规范)
* 改进`hasWhere`的数组条件的字段判断
* 增加[数组查询对象](高级查询.md)`Where`支持(喜欢数组查询的福音)
* 改进多对多关联的闭包支持
## V5.1.202018-7-25
该版本主要增加了Db和模型的动态获取器的支持并修正了一些已知问题。
* Db类添加[获取器支持](703981)
* 支持模型及关联模型字段[动态定义获取器](354046)
* 动态获取器支持`JSON`字段
* 改进路由的`before`行为执行(匹配后执行)
* `Config`类支持`Yaconf`
* 改进Url生成的端口问题
* Request类增加`setUrl``setBaseUrl`方法
* 改进页面trace的信息显示
* 修正`MorphOne`关联
* 命令行添加[查看版本指令](703994)
## V5.1.19 2018-7-13
该版本是一个小幅改进版本,针对`Swoole``Workerman``Cookie`支持做了一些改进,并修正了一些已知的问题。
* 改进query类`delete`方法对软删除条件判断
* 修正分表查询的软删除问题
* 模型查询的时候同时传入`table``name`属性
* 容器类增加`IteratorAggregate``Countable`接口支持
* 路由分组支持对下面的资源路由统一设置`only/except/vars`参数
* 改进Cookie类更好支持扩展
* 改进Request类`post`方法
* 改进模型自关联的自动识别
* 改进Request类对`php://input`数据的处理
## V5.1.18 2018-6-30
该版本主要完善了对`Swoole``Workerman``HttpServer`运行支持,改进`Request`类,并修正了一些已知的问题。
* 改进关联`append`方法的处理
* 路由初始化和检测方法分离
* 修正`destroy`方法强制删除
* `app_init`钩子位置移入`run`方法
* `think-swoole`扩展更新到2.0版本
* `think-worker`扩展更新到2.0版本
* 改进Url生成的域名自动识别
* `Request`类增加`setPathinfo`方法和`setHost`方法
* `Request`类增加`withGet`/`withPost`/`withHeader`/`withServer`/`withCookie`/`withEnv`方法进行赋值操作
* Route类改进`host`属性的获取
* 解决注解路由配置不生效的问题
* 取消Test日志驱动改为使用`close`设置关闭全局日志写入
* 修正路由的`response`参数
* 修正204响应输出的判断
## V5.1.17 2018-6-18
该版本主要增加了控制器中间件的支持,改进了路由功能,并且修正了社区反馈的一些问题。
* 修正软删除的`delete`方法
* 修正Query类`Count`方法
* 改进多对多`detach`方法
* 改进Request类`Session`方法
* 增加控制器中间件支持
* 模型类增加`jsonAssoc`属性用于定义json数据是否返回数组
* 修正Request类`method`方法的请求伪装
* 改进静态路由的匹配
* 分组首页路由自动完整匹配
* 改进sqlsrv的`column`方法
* 日志类的`apart_level`配置支持true自动生成对应类型的日志文件
* 改进`204`输出判断
* 修正cli下页面输出的BUG
* 验证类使用更高效的`ctype`验证机制
* 改进Request类`cookie`方法
* 修正软删除的`withTrashed`方法
* 改进多态一对多的预载入查询
* 改进Query类`column`方法的缓存读取
* Query类增加`whereBetweenTimeField`方法
* 改进分组下多个相同路由规则的合并匹配问题
* 路由类增加`getRule`/`getRuleList`方法获取定义的路由
## V5.1.16 2018-6-7
该版本主要修正了社区反馈的一些问题并对Request类做了进一步规范和优化。
* 改进Session类的`boot`方法
* App类的初始化方法可以单独执行
* 改进Request类的`param`方法
* 改进资源路由的变量替换
* Request类增加`__isset`方法
* 改进`useGlobalScope`方法对软删除的影响
* 修正命令行调用
* 改进Cookie类`init`方法
* 改进多对多关联删除的返回值
* 一对多关联写入支持`replace`
* 路由增加`filter`检测方法,用于通过请求参数检测路由是否匹配
* 取消Request类`session/env/server`方法的`filter`参数
* 改进关联的指定属性输出
* 模型删除操作删除后不清空对象数据仅作标记
* 调整模型的`save`方法返回值为布尔值
* 修正Request类`isAjax`方法
* 修正中间件的模块配置读取
* 取消Request类的请求变量的设置功能
* 取消请求变量获取的默认修饰符
* Request类增加`setAction/setModule/setController`方法
* 关联模型的`delete`方法调用Query类
* 改进URL生成的域名识别
* 改进URL检测对已定义路由的域名判断
* 模型类增加`isExists``isForce`方法
* 软删除的`destroy``restore`方法返回值调整为布尔值
## V5.1.15 2018-6-1
该版本主要改进了路由缓存的性能和缓存方式设置增加了JSON格式文件日志的支持并修正了社区反馈的一些问题。
* 容器类增加`exists`方法 仅判断是否存在对象实例
* 取消配置类的`autoload`方法
* 改进路由缓存大小提高性能
* 改进Dispatch类`init`方法
* 增加`make:validate`指令生成验证器类
* Config类`get`方法支持默认值参数
* 修正字段缓存指令
* 改进App类对`null`数据的返回
* 改进模型类的`__isset`方法判断
* 修正`Query`类的`withAggregate`方法
* 改进`RuleItem`类的`setRuleName`方法
* 修正依赖注入和参数的冲突问题
* 修正Db类对第三方驱动的支持
* 修正模型类查询对象问题
* 修正File缓存驱动的`has`方法
* 修正资源路由嵌套
* 改进Request类对`$_SERVER`变量的读取
* 改进请求缓存处理
* 路由缓存支持指定单独的缓存方式和参数
* 修正资源路由的中间件多次执行问题
* 修正`optimize:config`指令
* 文件日志支持`JSON`格式日志保存
* 修正Db类`connect`方法
* 改进Log类`write`方法不会自动写入之前日志
* 模型的关联操作默认启用事务
* 改进软删除的事件响应
## V5.1.14 2018-5-18
该版本主要对底层容器进行了一些优化改进,并增加了路由缓存功能,可以进一步提升路由性能。
* 依赖注入的对象参数传入改进
* 改进核心类的容器实例化
* 改进日期字段的读取
* 改进验证类的`getScene`方法
* 模型的`create`方法和`save`方法支持`replace`操作
* 改进`Db`类的调用机制
* App类调整为容器类
* 改进容器默认绑定
* `Loader`类增加工厂类的实例化方法
* 增加路由变量默认规则配置参数
* 增加路由缓存设计
* 错误处理机制改进
* 增加清空路由缓存指令
## V5.1.13 2018-5-11
该版本主要增加了MySQL的XA事务支持模型事件支持观察者以及对Facade类的改进。
* 改进自动缓存
* 改进Url生成
* 修正数据缓存
* 修正`value`方法的缓存
* `join`方法和`view`方法的条件支持使用`Expression`对象
* 改进驱动的`parseKey`方法
* 改进Request类`host`方法和`domain`方法对端口的处理
* 模型增加`withEvent`方法用于控制当前操作是否需要执行模型事件
* 模型`setInc/setDec`方法支持更新事件
* 模型添加`before_restore/after_restore`事件
* 增加模型事件观察者
* 路由增加`mobile`方法设置是否允许手机访问
* 数据库XA事务支持
* 改进索引数组查询对`IN`查询的支持
* 修正`invokeMethod`方法
* 修正空数据写入返回值的BUG
* redis驱动支持`predis`
* 改进`parseData`方法
* 改进模块加载
* App类初始化方法调整
* 改进数组查询对表达式`Expression`对象支持
* 改进闭包的依赖注入调用
* 改进多对多关联的中间表模型更新
* 增加容器中对象的自定义实例化
## V5.1.12 2018-4-25
该版本主要改进了主从查询的及时性,并支持动态设置请求数据。
* 支持动态设置请求数据
* 改进`comment`方法解析
* 修正App类`__unset`方法
* 改进url生成的域名绑定
* 改进主从查询的及时性
* 修正`value`的数据缓存功能
* 改进分页类的集合对象方法调用
* 改进Db类的代码提示
* SQL日志增加主从标记
## V5.1.11 2018-4-19
该版本为安全和修正版本改进了JSON查询的参数绑定问题和容器类对象实例获取并包含一处可能的安全隐患建议更新。
* 支持指定JSON数据查询的字段类型
* 修正`selectInsert`方法
* `whereColumn`方法支持数组方式
* 改进容器类`make`方法
* 容器类`delete`方法支持数组
* 改进`composer`自动加载
* 改进模板引擎
* 修正`like`查询的一处安全隐患
## V5.1.10 2018-4-16
该版本为修正版本修正上一个版本的一些BUG并增强了`think clear`指令。
* 改进`orderField`方法
* 改进`exists`查询
* 修改cli模式入口文件位置计算
* 修正`null`查询
* 改进`parseTime`方法
* 修正关联预载入查询
* 改进`mysql`驱动
* 改进`think clear`指令 支持 `-c -l -r `选项
* 改进路由规则对`/`结尾的支持
## V5.1.9 2018-4-12
该版本主要是一些改进和修正,并包含一个安全更新,是一个推荐更新版本。
* 默认模板渲染规则支持配置保持操作方法名
* 改进`Request`类的`ip`方法
* 支持模型软删除字段的默认值定义
* 改进路由变量规则对中文的支持
* 使用闭包查询的时候使用`cache(true)` 抛出异常提示
* 改进`Loader``loadComposerAutoloadFiles`方法
* 改进查询方法安全性
* 修正路由地址中控制器名驼峰问题
* 调整上一个版本的`module_init``app_begin`的钩子顺序问题
* 改进CLI命令行执行的问题
* 修正社区反馈的其它问题
## V5.1.8 2018-4-5
该版本主要改进了中间件的域名和模块支持,并同时修正了几个已知问题。
* 增加`template.auto_rule` 参数设置默认模板渲染的操作名自动转换规则
* 默认模板渲染规则改由视图驱动实现
* 修正路由标识定义
* 修正控制器路由方法
* 改进Request类`ip`方法支持自定义代理IP参数
* 路由注册中间件支持数组方式别名
* 改进命令行执行下的`composer`自动加载
* 添加域名中间件注册支持
* 全局中间件支持模块定义文件
* Log日志配置支持`close`参数可以全局关闭日志写入
* 中间件方法中捕获`HttpResponseException`异常
* 改进中间件的闭包参数传入
* 改进分组路由的延迟解析
* 改进URL生成对域名绑定的支持
* 改进文件缓存和文件日志驱动的并发支持
## V5.1.7 2018-3-28
该版本主要修正了路由的一些问题,并改进了查询的安全性。
* 支持`middleware`配置文件预先定义中间件别名方便路由调用
* 修正资源路由
* 改进`field`方法 自动识别`fieldRaw`
* 增加`Expression`
* Query类增加`raw`方法
* Query类的`field`/ `order`` where`方法都支持使用`raw`表达式查询
* 改进`inc/dec`查询 支持批量更新
* 改进路由分组
* 改进Response类`create`方法
* 改进composer自动加载
* 修正域名路由的`append`方法
* 修正操作方法的初始化方法获取不到问题
## V5.1.6 2018-3-26
该版本主要改进了路由规则的匹配算法,大幅提升了路由性能。并正式引入了中间件的支持,可以在路由中定义或者全局定义。另外包含了一个安全更新,是一个建议更新版本。
* 改进URL生成对路由`ext`方法的支持
* 改进查询缓存对不同数据库相同表名的支持
* 改进composer自动加载的性能
* 改进空路由变量对默认参数的影响
* mysql的`json`字段查询支持多级
* Query类增加`option`方法
* 优化路由匹配
* 修复验证规则数字键名丢失问题
* 改进路由Url生成
* 改进一对一关联预载入查询
* Request类增加`rootDomain`方法
* 支持API资源控制器生成 `make:controller --api`
* 优化Template类的标签解析
* 容器类增加删除和清除对象实例的方法
* 修正MorphMany关联的`eagerlyMorphToMany`方法一处错误
* Container类的异常捕获改进
* Domain对象支持`bind`方法
* 修正分页参数
* 默认模板的输出规则不受URL影响
* 注解路由支持多级控制器
* Query类增加`getNumRows`方法获取前次操作影响的记录数
* 改进查询条件的性能
* 改进模型类`readTransform`方法对序列化类型的处理
* Log类增加`close`方法可以临时关闭当前请求的日志写入
* 文件日志方式增加自动清理功能(设置`max_files`参数)
* 修正Query类的`getPk`方法
* 修正模板缓存的布局开关问题
* 修正Query类`select`方法的缓存
* 改进input助手函数
* 改进断线重连的信息判断
* 改进正则验证方法
* 调整语言包的加载顺序 放到`app_init`之前
* controller类`fetch`方法改为`final`
* 路由地址中的变量支持使用`<var>`方式
* 改进XMLResponse 支持传入编码过的xml内容
* 修正Query类`view`方法的数组表名支持
* 改进路由的模型闭包绑定
* 改进分组变量规则的继承
* 改进`cli-server`模式下的`composer`自动加载
* 路由变量规则异常捕获
* 引入中间件支持
* 路由定义增加`middleware`方法
* 增加生成中间件指令`make:middleware`
* 增加全局中间件定义支持
* 改进`optimize:config`指令对全局中间件的支持
* 改进config类`has`方法
* 改进时间查询的参数绑定
* 改进`inc/dec/exp`查询的安全性
## V5.1.5 2018-1-31
该版本主要增强了数据库的JSON查询并支持JSON字段的聚合查询改进了一些性能问题修正了路由的一些BUG主要更新如下
* 改进数据集查询对`JSON`数据的支持
* 改进聚合查询对`JSON`字段的支持
* 模型类增加`getOrFail`方法
* 改进数据库驱动的`parseKey`方法
* 改进Query类`join`方法的自关联查询
* 改进数据查询不存在不生成查询缓存
* 增加`run`命令行指令启动内置服务器
* `Request``pathinfo`方法改进对`cli-server`支持
* `Session`类增加`use_lock`配置参数设置是否启用锁机制
* 优化`File`缓存自动生成空目录的问题
* 域名及分组路由支持`append`方法传递隐式参数
* 改进日志的并发写入问题
* 改进`Query`类的`where`方法支持传入`Query`对象
* 支持设置单个日志文件的文件名
* 修正路由规则的域名条件约束
* `Request`类增加`subDomain`方法用于获取当前子域名
* `Response`类增加`allowCache`方法控制是否允许请求缓存
* `Request`类增加`sendData`方法便于扩展
* 改进`Env`类不依赖`putenv`方法
* 改进控制台`trace`显示错误
* 改进`MorphTo`关联
* 改进完整路由匹配后带斜线访问出错的情况
* 改进路由的多级分组问题
* 路由url地址生成支持多级分组
* 改进路由Url生成的`url_convert`参数的影响
* 改进`miss``auto`路由内部解析
* 取消预载入关联查询缓存功能
## V5.1.4 2018-1-19
该版本主要增强了数据库和模型操作,主要更新如下:
* 支持设置 `deleteTime`属性为`false` 关闭软删除
* 模型增加`getError`方法
* 改进Query类的`getTableFields`/`getFieldsType`方法 支持表名自动获取
* 模型类`toCollection`方法增加参数指定数据集类
* 改进`union`查询
* 关联预载入`with`方法增加缓存参数
* 改进模型类的`get``all`方法的缓存 支持关联缓存
* 支持`order by field`操作
* 改进`insertAll`分批写入
* 改进`json`字段数据支持
* 增加JSON数据的模型对象化操作
* 改进路由`ext`参数检测
* 修正`rule`方法的`method`参数使用 `get|post` 方式注册路由的问题
## V5.1.3 2018-1-12
该版本主要改进了路由及调整函数加载顺序,主要更新如下:
* 增加`env`助手函数;
* 增加`route`助手函数;
* 增加视图路由方法;
* 增加路由重定向方法;
* 路由默认区分最后的目录斜杆(支持设置不区分);
* 调整公共文件和配置文件的加载顺序(可以在配置文件中直接使用助手函数);
* 视图类增加`filter`方法设置输出过滤;
* `view`助手函数增加`filter`参数;
* 改进缓存生成指令;
* Session类的`get`方法支持获取多级;
* Request类`only`方法支持指定默认值;
* 改进路由分组;
* 修正使用闭包查询的时候自动数据缓存出错的情况;
* 废除`view_filter`钩子位置;
* 修正分组下面的资源路由;
* 改进session驱动;
## V5.1.2 2018-1-8
该版本改进了配置类及数据库类,主要更新如下:
* 修正嵌套路由分组;
* 修正自定义模板标签界定符后表达式语法出错的情况;
* 修正自关联的多次调用问题;
* 修正数组查询的`null`条件查询;
* 修正Query类的`order``field`的一处可能的BUG
* 配置参数设置支持三级;
* 配置对象支持`ArrayAccess`
* App类增加`path`方法用于设置应用目录;
* 关联定义增加`selfRelation`方法用于设置是否为自关联;
## V5.1.1 2018-1-3
修正一些反馈的BUG包括
* 修正Cookie类存取数组的问题
* 修正Controller的`fetch`方法
* 改进跨域请求
* 修正`insertAll`方法
* 修正`chunk`方法
## V5.1.0 2018-1-1
主要更新如下:
* 增加注解路由支持
* 路由支持跨域请求设置
* 增加`app_dispatch`钩子位置
* 修正多对多关联的`detach`方法
* 修正软删除的`destroy`方法
* Cookie类`httponly`参数默认为false
* 日志File驱动增加`single`参数配置记录同一个文件(不按日期生成)
* 路由的`ext``denyExt`方法支持不传任何参数
* 改进模型的`save`方法对`oracle`的支持
* Query类的`insertall`方法支持配合`data``limit`方法
* 增加`whereOr`动态查询支持
* 日志的ip地址记录改进
* 模型`saveAll`方法支持`isUpdate`方法
* 改进`Pivot`模型的实例化操作
* 改进Model类的`data`方法
* 改进多对多中间表模型类
* 模型增加`force`方法强制更新所有数据
* Hook类支持设置入口方法名称
* 改进验证类
* 改进`hasWhere`查询的数据重复问题
* 模型的`saveall`方法返回数据集对象
* 改进File缓存的`clear`方法
* 缓存添加统一的序列化机制
* 改进泛三级域名的绑定
* 改进泛域名的传值和取值
* Request类增加`panDomain`方法
* 改进废弃字段判断
* App类增加`create`方法用于实例化应用类库
* 容器类增加`has`方法
* 改进多数据库切换连接
* 改进断线重连的异常捕获
* 改进模型类`buildQuery`方法
* Query类增加`unionAll`方法
* 关联统计功能增强支持Sum/Max/Min/Avg
* 修正延迟写入
* chunk方法支持复合主键
* 改进JSON类型的写入
* 改进Mysql的insertAll方法
* Model类`save`方法改进复合主键包含自增的情况
* 改进Query类`inc``dec`方法的关键字处理
* File缓存inc和dec方法保持原来的有效期
* 改进redis缓存的有效期判断
* 增加checkRule方法用于单独数据的多个验证规则
* 修正setDec方法的延迟写入
* max和min方法增加force参数
* 二级配置参数区分大小写
* 改进join方法自关联的问题
* 修正关联模型自定义表名的情况
* Query类增加getFieldsType和getTableFields方法
* 取消视图替换功能及view_replace_str配置参数
* 改进域名绑定模块后的额外路由规则问题
* 改进mysql的insertAll方法
* 改进insertAll方法写入json字段数据的支持
* 改进redis长连接多编号库的情况
## RC3版本2017-11-6
主要更新如下:
* 改进redis驱动的`get`方法
* 修正Query类的`alias`方法
* `File`类错误信息支持多语言
* 修正路由的额外参数解析
* 改进`whereTime`方法
* 改进Model类`getAttr`方法
* 改进App类的`controller``validate`方法支持多层
* 改进`HasManyThrough`
* 修正软删除的`restore`方法
* 改进`MorpthTo`关联
* 改进数据库驱动类的`parseKey`方法
* 增加`whereField`动态查询方法
* 模型增加废弃字段功能
* 改进路由的`after`行为检查和`before`行为机制
* 改进路由分组的检查
* 修正mysql的`json`字段查询
* 取消Connection类的`quote`方法
* 改进命令行的支持
* 验证信息支持多语言
* 修正路由模型绑定
* 改进参数绑定类型对枚举类型的支持
* 修正模板的`{$Think.version} `输出
* 改进模板`date`函数解析
* 改进`insertAll`方法支持分批执行
* Request类`host`方法支持反向代理
* 改进`JumpResponse`支持区分成功和错误模板
* 改进开启类库后缀后的关联外键自动识别问题
* 修正一对一关联的JOIN方式预载入查询问题
* Query类增加`hidden`方法
## RC2版本2017-10-17
主要更新如下:
* 修正视图查询
* 修正资源路由
* 修正`HasMany`关联 修正`where`方法的闭包查询
* 一对一关联绑定属性到父模型后 关联属性不再保留
* 修正应用的命令行配置文件读取
* 改进`Connection`类的`getCacheKey`方法
* 改进文件上传的非法图像异常
* 改进验证类的`unique`规则
* Config类`get`方法支持获取一级配置
* 修正count方法对`fetchSql`的支持
* 修正mysql驱动对`socket`支持
* 改进Connection类的`getRealSql`方法
* 修正`view`助手函数
* Query类增加`leftJoin` `rightJoin``fullJoin`方法
* 改进app_namespace的获取
* 改进`append`方法对一对一`bind`属性的支持
* 改进关联的`saveall`方法的返回值
* 路由标识设置异常修复
* 改进Route类`rule`方法
* 改进模型的`table`属性设置
* 改进composer autofile的加载顺序
* 改进`exception_handle`配置对闭包的支持
* 改进app助手函数增加参数
* 改进composer的加载路径判断
* 修正路由组合变量的URL生成
* 修正路由URL生成
* 改进`whereTime`查询并支持扩展规则
* File类的`move`方法第二个参数支持`false`
* 改进Config类
* 改进缓存类`remember`方法
* 惯例配置文件调整 Url类当普通模式参数的时候不做`urlencode`处理
* 取消`ROOT_PATH``APP_PATH`常量定义 如需更改应用目录 自己重新定义入口文件
* 增加`app_debug``Env`获取
* 修正泛域名绑定
* 改进查询表达式的解析机制
* mysql增加`regexp`查询表达式 支持正则查询
* 改进查询表达式的异常判断
* 改进model类的`destroy`方法
* 改进Builder类 取消`parseValue`方法
* 修正like查询的参数绑定问题
* console和start文件移出核心纳入应用库
* 改进Db类主键删除方法
* 改进泛域名绑定模块
* 取消`BIND_MODULE`常量 改为在入口文件使用`bind`方法设置
* 改进数组查询
* 改进模板渲染的异常处理
* 改进控制器基类的架构方法参数
* 改进Controller类的`success``error`方法
* 改进对浏览器`JSON-Handle`插件的支持
* 优化跳转模板的移动端显示
* 修正模型查询的`chunk`方法对时间字段的支持
* 改进trace驱动
* Collection类增加`push`方法
* 改进Redis Session驱动
* 增加JumpResponse驱动
## RC12017-9-8
主要新特性为:
* 引入容器和Facade支持
* 依赖注入完善和支持更多场景
* 重构的(对象化)路由
* 配置和路由目录独立
* 取消系统常量
* 助手函数增强
* 类库别名机制
* 模型和数据库增强
* 验证类增强
* 模板引擎改进
* 支持PSR-3日志规范
* RC1版本取消了5.0多个字段批量数组查询的方式

View File

@@ -0,0 +1,32 @@
ThinkPHP遵循Apache2开源协议发布并提供免费使用。
版权所有Copyright © 2006-2018 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
Apache Licence是著名的非盈利开源组织Apache采用的协议。
该协议和BSD类似鼓励代码共享和尊重原作者的著作权
允许代码修改,再作为开源或商业软件发布。需要满足
的条件:
1 需要给代码的用户一份Apache Licence
2 如果你修改了代码,需要在被修改的文件中说明;
3 在延伸的代码中(修改和有源代码衍生的代码中)需要
带有原来代码中的协议,商标,专利声明和其他原来作者规
定需要包含的说明;
4 如果再发布的产品中包含一个Notice文件则在Notice文
件中需要带有本协议内容。你可以在Notice中增加自己的
许可但不可以表现为对Apache Licence构成更改。
具体的协议参考http://www.apache.org/licenses/LICENSE-2.0
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,36 @@
# digital_doctor
#### Description
数智人医生,疼痛科数智人医生
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

View File

@@ -0,0 +1,37 @@
# digital_doctor
#### 介绍
数智人医生,疼痛科数智人医生
#### 软件架构
软件架构说明
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 特技
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

View File

@@ -0,0 +1 @@
deny from all

View File

@@ -0,0 +1,72 @@
<?php
/*
* description
* authorwh
* email
* createTime{2023/1/21} {16:22}
*/
namespace app\api\controller;
use app\common\model\TabConf;
use think\Controller;
use think\Db;
use think\Request;
use wanghua\general_utility_tools_php\framework\BaseController;
use wanghua\general_utility_tools_php\tool\Tools;
class BaseCommonController extends BaseController
{
function __construct()
{
parent::__construct();
}
/**
* desc检查路径维护状态
*
* “===”完全匹配不能使用like
*
* authorwh
*/
protected function checkMaintain(){
$configs = Db::table(TabConf::$fa_sys_maintain_config)
->where('status','1')
->cache()
->select();
//模块
$strmodule = request()->module();
foreach ($configs as $config){
if($strmodule == $config['url']){
//模块维护中
return ['is_maintain'=>true,'msg'=>$config['msg'],'openid'=>$config['openid']];
}
}
//模块/控制器
$strcontroller = strtolower(request()->module().'/'.request()->controller());
foreach ($configs as $config){
if($strcontroller == $config['url']){
//模块维护中
return ['is_maintain'=>true,'msg'=>$config['msg'],'openid'=>$config['openid']];
}
}
//模块/控制器/方法
$straction = strtolower(request()->module().'/'.request()->controller().'/'.request()->action());
foreach ($configs as $config){
if($straction == $config['url']){
//模块维护中
return ['is_maintain'=>true,'msg'=>$config['msg'],'openid'=>$config['openid']];
}
}
//未维护
return ['is_maintain'=>false,'msg'=>'服务运行中'];
}
}

View File

@@ -0,0 +1,34 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/4/22} {11:52}
*/
namespace app\api\controller;
use app\index\controller\BaseCommonController;
use think\App;
use think\Controller;
use think\Exception;
use wanghua\general_utility_tools_php\tool\Ip;
class BaseHttpApi extends BaseCommonController
{
/**
http请求专用
*/
public function __construct()
{
parent::__construct();
//ip校验
//$ip = request()->ip();
//$res = Ip::ip_is_china($ip,false);
//if(!$res){
// throw new Exception('ip不合法');
//}
}
}

View File

@@ -0,0 +1,34 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/4/5} {19:55}
*/
namespace app\api\controller;
class BaseWssApi extends BaseCommonController
{
/**
* descsocket专用json格式
*
* authorwh
* @param $action
* @param string $msg
* @param array $items
* @param string $method
* @return false|string
*/
static function json_wss($action,$msg='', $items=[], $method='response'){
$json = [
'action'=>$action,
'method'=>$method,
'msg'=>$msg,
'items'=>$items
];
return json_encode($json, JSON_UNESCAPED_UNICODE);
}
}

View File

@@ -0,0 +1,187 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/4/3} {15:43}
*/
namespace app\api\controller;
use app\api\logic\DouLogic;
use app\common\model\TabConf;
use think\Db;
use wanghua\general_utility_tools_php\douyin\DouYinMiniGame;
use wanghua\general_utility_tools_php\image\Image;
use wanghua\general_utility_tools_php\tool\Tools;
class Douyin extends BaseHttpApi
{
public function __construct()
{
//$logic = new DouLogic();
//$logic->realTimeGetAccessToken();
}
/**
* desc
*
* api/Douyin/getaccesstoken
*
* authorwh
*/
function getaccesstoken(){
$logic = new DouYinMiniGame();
//tp5.1必须带app.
$logic->appid = config('app.douyin_config_mini_game.appid');
$logic->secret = config('app.douyin_config_mini_game.secret');
$res = $logic->realTimeGetAccessToken();
return json($res);
}
/**
* desctt.login触发调用
* 参数code或anonymous_code
*
* api/Douyin/jscode2session
*
* "{\"anonymous_openid\":\"\",\"error\":0,\"openid\":\"_0007vGUSinv-twIOjY9MzYvzlj6U_xHa3Or\",\"session_key\":\"495rArUkMUXa4JoeT7wEVg==\",\"unionid\":\"7e1b9701-a346-5b44-9925-0acc40873cff\"}
*
* authorwh
*/
function jscode2session(){
//{"nickName":"fish","avatarUrl":"https://p26.douyinpic.com/aweme/100x100/f831000cb79d741e8c7e.jpeg?
//from=3782654143",
//"gender":0,"city":"","province":"","country":"","language":""}
try {
$clientid = input('clientid');
if(empty($clientid)){
return json(Tools::set_fail('clientid error'));
}
$json = input('json');
$json_arr = json_decode($json, true);
$logic = new DouYinMiniGame();
//tp5.1必须带app.
$logic->appid = config('app.douyin_config_mini_game.appid');
$logic->secret = config('app.douyin_config_mini_game.secret');
//tt.login 接口返回的匿名登录凭证code 和 anonymous_code 至少要有一个)
$code = input('code');
$anonymous_code = input('anonymous_code');
$res = $logic->jscode2session($code,$anonymous_code);
//保存用户信息
if($res['code'] != 200){
return json($res);
}
$openid = $res['data']['openid'];
$user = Db::table(TabConf::$fa_users)
->where('openid',$openid)
->find();
if(empty($user)){
$data = [
'openid'=>$openid,
'nickname'=>isset($json_arr['nickName'])?$json_arr['nickName']:'',
'headimage'=>isset($json_arr['avatarUrl'])?$json_arr['avatarUrl']:'',
'user_type'=>'douyin',
'unionid'=>$res['data']['unionid'],
'clientid'=>$clientid,
'last_login_time'=>Tools::get_now_date(),
];
Db::table(TabConf::$fa_users)
->data($data)
->insert();
}else{
Db::table(TabConf::$fa_users)
->where('openid',$openid)
->data([
'clientid'=>$clientid,
'nickname'=>isset($json_arr['nickName'])?$json_arr['nickName']:Tools::rand_str(),
'headimage'=>isset($json_arr['avatarUrl'])?$json_arr['avatarUrl']:request()->domain().'/static/common/headimage.jpg',
'last_login_time'=>Tools::get_now_date(),
])//更新登录状态
->update();
}
//初始化用户消消乐游戏奖励
$usereliminate = Db::table(TabConf::$fa_usereliminate)
->where('openid',$openid)
->find();
if(empty($usereliminate)){
Db::table(TabConf::$fa_usereliminate)->insert([
'openid'=>$openid
]);
}
return json($res);
}catch (\Exception $e){
Tools::error_txt_log($e);
return json(Tools::set_fail());
}
}
/**
* desc创建二维码
* 接口说明
* 获取小程序/小游戏的二维码。该二维码可通过任意 app 扫码打开,
* 能跳转到开发者指定的对应字节系 app 内拉起小程序/小游戏,并传入开发者指定的参数。
* 通过该接口生成的二维码,永久有效,暂无数量限制。
*
* ⚠ Tip在使用该功能之前请记得先配置您的默认分享文案和图片配置方式可参考论坛。
* ⚠ Tip小程序的 path 要 encode 一次,如 pages%3fparam%3dtrue小游戏的 path 为 JSON 字符串,
* 如{"param":true},否则会导致取不到。
*
* 参数:
* code和anonymous_code二选一 必须
* appname 可选,目标打开应用名称 默认douyin
* background 可选背景色rgb格式英文逗号隔开默认透明色
* path 可选,小程序/小游戏启动参数,小程序则格式为 encode({path}?{query}),小游戏则格式为 JSON 字符串,默认为空
* width 宽度 可选,二维码宽度,单位 px最小 280px最大 1280px默认为 430px
* line_color 可选二维码线条颜色默认为黑色rgb格式英文逗号隔开默认黑色
* set_icon 可选,是否展示小程序/小游戏 icon默认不展示传yes展示no不展示默认no
*
* api/douyin/createQRCode
* 参数openid
*
* authorwh
*/
function createQRCode(){
try {
$openid = input('openid');
if(empty($openid)){
return json(Tools::set_fail('openid error'));
}
$logic = new DouYinMiniGame();
//tp5.1必须带app.
$logic->appid = config('app.douyin_config_mini_game.appid');
$logic->secret = config('app.douyin_config_mini_game.secret');
$path=input('path','');
$appname=input('appname','douyin');
$width=input('width');
$background=input('background');
$line_color=input('line_color');
$set_icon=input('set_icon','yes');
$res = $logic->createQRCode($path,$appname,$width,$background,$line_color,$set_icon);
if(is_array($res)){
return json(Tools::set_fail('错误.',$res));
}
$img_save_path = '/uploads/unlimited_douyin/';
$rand_str = Tools::rand_str();
$filename = $openid.'_'.$rand_str.'.png';
(new Image())->binaryToImage($res,$img_save_path,$filename);
return json(Tools::set_ok('ok',$img_save_path.$filename));
}catch (\Exception $e){
Tools::error_txt_log($e);
return json(Tools::set_fail());
}
}
}

View File

@@ -0,0 +1,41 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/6/18} {17:39}
*/
namespace app\api\controller;
use app\api\logic\EnemyLogic;
use app\common\model\TabConf;
use think\Db;
use wanghua\general_utility_tools_php\Mmodel;
use wanghua\general_utility_tools_php\tool\Tools;
/**
* 敌人
* Class Enemy
* @package app\api\controller
*/
class Enemy extends BaseHttpApi
{
/**
* desc累加击杀敌人数量
*
* api/enemy/addKillEnemyNum
*
* 参数enemy_num
*
* authorwh
*/
function addKillEnemyNum(){
return Mmodel::catchJson(function (){
return (new EnemyLogic())->addKillEnemyNum();
});
}
}

View File

@@ -0,0 +1,95 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/5/26} {22:58}
*/
namespace app\api\controller;
use app\common\model\TabConf;
use think\Db;
use wanghua\general_utility_tools_php\Mmodel;
use wanghua\general_utility_tools_php\tool\Tools;
class Friends extends BaseHttpApi
{
/**
* desc查询推荐好友
*
* api/friends/getPutFriends
*
* 要求:不是自己和自己的好友
* authorwh
*/
function getPutFriends(){
return Mmodel::catchJson(function (){
$openid_arr = [api_user_openid()];
//查询自己的好友
$fr = Db::table(TabConf::$fa_gamefriend)
->where('openid',api_user_openid())
->select();
$arr = array_column($fr,'friend_openid');
$arrmg = array_merge($openid_arr,$arr);
$lists = Db::table(TabConf::$fa_users)
->whereNotIn('openid',$arrmg)
->select();
return Tools::set_ok('ok',$lists);
});
}
/**
* desc添加好友
* api/friends/addFriend
* 参数friend_openid
*
* 要求:不是自己和自己的好友
* authorwh
*/
//function addFriend(){
// return Mmodel::catchJson(function () {
// $openid_arr = [api_user_openid()];
// //查询自己的好友
// $fr = Db::table(TabConf::$fa_gamefriend)
// ->where('openid',api_user_openid())
// ->select();
// $arr = array_column($fr,'friend_openid');
//
// $arrmg = array_merge($openid_arr,$arr);
//
// $friend_openid = input('friend_openid');
// if(empty($friend_openid)){
// return Tools::set_fail('请输入好友openid');
// }
// if(in_array($friend_openid,$arrmg)){
// return Tools::set_fail('不能添加自己和自己的好友');
// }
// //查询用户
// $users = Db::table(TabConf::$fa_users)
// ->where('openid',$friend_openid)
// ->find();
// if(empty($users)){
// return Tools::set_fail('用户不存在');
// }
//
// $data = [
// 'openid'=>api_user_openid(),
// 'nickname'=>api_user_info('nickname'),
// 'type'=>2,
// 'friend_openid'=>$users['openid'],
// 'friend_nickname'=>$users['nickname'],
// 'friend_image'=>$users['headimage'],
// ];
// Db::table(TabConf::$fa_gamefriend)
// ->insert($data);
// return Tools::set_ok('ok');
// });
//}
}

View File

@@ -0,0 +1,82 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/5/22} {22:56}
*/
namespace app\api\controller;
use app\common\model\TabConf;
use think\Db;
use wanghua\general_utility_tools_php\Mmodel;
use wanghua\general_utility_tools_php\tool\Tools;
class Gameemail extends BaseHttpApi
{
/**
* desc游戏邮件列表
* api/gameemail/getlists
*
* is_read 阅读状态
* is_deleted 删除标记
*/
function getlists(){
return Mmodel::catchJson(function (){
$lists = Db::table(TabConf::$fa_gameemail)->order('id desc')->select();
foreach ($lists as &$list){
$is_read = Db::table(TabConf::$fa_user_email_read_record)
->where('openid',api_user_openid())
->where('gameemail_id',$list['id'])
->find();
//阅读状态
$list['is_read'] = $is_read?1:0;
//删除标记
$list['is_deleted'] = $is_read?$is_read['is_deleted']:0;
}
return Tools::set_ok('ok',$lists);
});
}
/**
* 设置邮件为已读
* api/gameemail/read
* 参数:
* email_id 邮件id
*/
function read(){
return Mmodel::catchJson(function (){
$email_id = input('email_id');
if(empty($email_id)){
return Tools::set_fail('邮件id不能为空');
}
Db::table(TabConf::$fa_user_email_read_record)
->data([
'openid'=>api_user_openid(),
'gameemail_id'=>$email_id,
])
->insert();
return Tools::set_ok('ok');
});
}
/**
* 删除所有已读邮件
* api/gameemail/delete
* 参数:
*/
function delete(){
return Mmodel::catchJson(function (){
//记录存在表示已读
Db::table(TabConf::$fa_user_email_read_record)
->where('openid',api_user_openid())
->data([
'is_deleted'=>'1',
])
->update();
return Tools::set_ok('ok');
});
}
}

View File

@@ -0,0 +1,81 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/5/23} {0:06}
*/
namespace app\api\controller;
use app\common\model\TabConf;
use think\Db;
use wanghua\general_utility_tools_php\Mmodel;
use wanghua\general_utility_tools_php\tool\Tools;
/**
* 游戏道具
*
* Class Gameprop
* @package app\api\controller
*/
class Gameprop extends BaseHttpApi
{
/**
* desc游戏道具已解锁、未解锁接口
* api/gameprop/getprop
* 参数:
*
* 返回:
* have_arr 已解锁
* no_arr 未解锁
*
* authorwh
*/
function getprop(){
return Mmodel::catchJson(function (){
$openid = api_user_openid();
//查询所有未获取的道具列表
$gameprop_list = Db::table(TabConf::$fa_gameprop)->select();
$have_arr = [];//已拥有
$no_arr = [];//未拥有
foreach ($gameprop_list as $item){
$tmp_arr = [];
$usergameprop = Db::table(TabConf::$fa_usergameprop)
->where('openid',$openid)
->where('gameprop_id',$item['id'])
->find();
if($usergameprop){
$tmp_arr['num'] = $usergameprop['num'];
//已拥有
$have_arr[] = array_merge($tmp_arr, $item);
}else{
//未拥有
$no_arr[] = $item;
}
}
return Tools::set_ok('ok',[
'have_arr'=>$have_arr,
'no_arr'=>$no_arr,
]);
});
}
/**
* desc获取游戏道具列表肥料等各种道具
*
* api/gameprop/getGamePropList
*
* authorwh
*/
function getGamePropList(){
return Mmodel::catchJson(function (){
$gameprop_list = Db::table(TabConf::$fa_gameprop)->select();
return Tools::set_ok('ok',$gameprop_list);
});
}
}

View File

@@ -0,0 +1,33 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/5/22} {21:09}
*/
namespace app\api\controller;
use app\common\model\TabConf;
use think\Db;
use wanghua\general_utility_tools_php\Mmodel;
use wanghua\general_utility_tools_php\tool\Tools;
class Notice extends BaseHttpApi
{
/**
* desc游戏公告
* api/notice/getnotice
*
* authorwh
* @return \think\response\Json
*/
function getnotice(){
return Mmodel::catchJson(function (){
$res = Db::table(TabConf::$fa_notice)->find();
return Tools::set_ok('ok',$res);
});
}
}

View File

@@ -0,0 +1,120 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/5/25} {16:30}
*/
namespace app\api\controller;
use app\common\model\TabConf;
use think\Db;
use wanghua\general_utility_tools_php\Mmodel;
use wanghua\general_utility_tools_php\tool\Tools;
class Plant extends BaseHttpApi
{
/**
* desc查询系统植物列表
* api/plant/getlist
* authorwh
*/
function getlist(){
return Mmodel::catchJson(function (){
$lists = Db::table(TabConf::$fa_plant)
->select();
return Tools::set_ok('ok',$lists);
});
}
/**
* 添加系统植物(前端合成植物时调用并增加用户的植物)
* 如果用户植物存在则新增,否则增加植物数量
* api/plant/add
*
* 参数:
* name 系统植物名称 必须
* num 用户植物增加数量默认1可不传
* plant_sit 植物合成时的位置 必须
*/
//function add(){
// return Mmodel::catchTransJson(function (){
// if(empty(input('name'))){
// return Tools::set_fail('植物名称不能为空');
// }
// //重复
// $plant = Db::table(TabConf::$fa_plant)->where('name',input('name'))->find();
// if($plant){
// $this->addUserPlants($plant['id']);
// $this->userPlantConflateRecord($plant['id']);
// return Tools::set_fail('植物名称重复');
// }else{
// $id = Db::table(TabConf::$fa_plant)->insertGetId([
// 'name'=>input('name'),
// ]);
// $this->addUserPlants($id);
// $this->userPlantConflateRecord($id);
// }
//
// return Tools::set_ok('ok',['plant_id'=>$id]);
// });
//}
//
//
///**
// * desc合成后新增用户植物前端合成时调用新增
// * num 增加数量默认1可不传
// * authorwh
// */
//private function addUserPlants($id){
// return Mmodel::catchTrans(function () use ($id){
// $num = input('num',1);
// $userplant = Db::table(TabConf::$fa_userplant)
// ->where('openid', api_user_openid())
// ->where('plant_id', $id)
// ->find();
// if($userplant){
// Db::table(TabConf::$fa_userplant)
// ->where('id',$userplant['id'])
// ->setInc('num',$num);
// }else{
// $plant = Db::table(TabConf::$fa_plant)
// ->where('id',$id)
// ->find();
// Db::table(TabConf::$fa_userplant)
// ->insert([
// 'openid'=>api_user_openid(),
// 'plant_id'=>$id,
// 'num'=>$num,
// 'name'=>$plant['name'],
// 'image'=>$plant['image'],
// ]);
// }
// return Tools::set_ok('ok');
// });
//}
//
///**
// * desc用户植物合成记录
// * authorwh
// */
//private function userPlantConflateRecord($plant_id){
// $plant_sit = input('plant_sit');
// $data = [
// 'openid'=>api_user_openid(),
// 'plant_sit'=>$plant_sit,
// 'plant_id'=>$plant_id,
// ];
// Db::table(TabConf::$fa_userplantconflaterecord)
// ->data($data)
// ->insert();
//}
//
//function getUserPlantConflateRecord(){
// return Mmodel::catchJson(function (){
//
// });
//}
}

View File

@@ -0,0 +1,54 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/6/22} {15:02}
*/
namespace app\api\controller;
use app\common\model\TabConf;
use think\Db;
use wanghua\general_utility_tools_php\Mmodel;
use wanghua\general_utility_tools_php\SundryConfig;
use wanghua\general_utility_tools_php\tool\Tools;
class Power extends BaseHttpApi
{
/**
* desc当前用户消耗体力
*
* api/Power/cutPower
*
* 参数:
* num 消耗体力 默认1
*
* authorwh
*/
function cutPower()
{
return Mmodel::catchJson(function (){
$openid = api_user_openid();
$num = input('num',1);
Db::table(TabConf::$fa_users)
->where('openid',$openid)
->setDec('power',$num);
return Tools::set_ok('ok');
});
}
/**
* desc获取体力上限配置
* api/Power/getPowerLimitConfig
* authorwh
*/
function getPowerLimitConfig(){
return Mmodel::catchJson(function (){
$power_limit_config = SundryConfig::val('power_limit_config');
return Tools::set_ok('ok',$power_limit_config);
});
}
}

View File

@@ -0,0 +1,33 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/5/27} {13:06}
*/
namespace app\api\controller;
use app\common\model\TabConf;
use think\Db;
use wanghua\general_utility_tools_php\Mmodel;
use wanghua\general_utility_tools_php\tool\Tools;
class Rankinglist extends BaseHttpApi
{
/**
* desc查询排行榜
* /api/rankinglist/getrankinglist
* authorwh
*/
function getrankinglist(){
return Mmodel::catchJson(function (){
$lists = Db::table(TabConf::$fa_users)
->order('now_level desc')
->select();
return Tools::set_ok('ok',$lists);
});
}
}

View File

@@ -0,0 +1,128 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/6/12} {11:53}
*/
namespace app\api\controller;
use app\common\model\TabConf;
use think\Db;
use wanghua\general_utility_tools_php\Mmodel;
use wanghua\general_utility_tools_php\SundryConfig;
use wanghua\general_utility_tools_php\tool\Tools;
/**
* Class Redeemcode 兑换码
* @package app\api\controller
*/
class Redeemcode extends BaseHttpApi
{
/**
* desc新增一个兑换码
* 参数: num (默认1)
* authorwh
*/
function add(){
return Mmodel::catchJson(function (){
$num = input('num',1);//生成数量
for ($i=0;$i<$num;$i++){
Db::table(TabConf::$fa_redeem_code)
->insert(['create_time'=>Tools::get_now_date()]);
return Tools::set_ok();
}
});
}
/**
* 查询一个没使用的兑换码
*/
function getOne(){
return Mmodel::catchJson(function (){
$res = Db::table(TabConf::$fa_redeem_code)
->where('is_use',0)
//->order('id','asc')
->find();
if($res){
return Tools::set_ok($res);
}
return Tools::set_fail('没有更多了');
});
}
/**
* 兑换码使用
*
* 参数code
*
* 返回用户获得的道具列表(可能获得多个道具,根据系统配置定)
*/
function use()
{
return Mmodel::catchJson(function () {
$code = input('code');
if (!$code) {
return Tools::set_fail('参数错误');
}
$res = Db::table(TabConf::$fa_redeem_code)
->where('id', $code)
->where('is_use', 0)
->find();
if (empty($res)) {
return Tools::set_fail('兑换码不存在或已使用');
}
Db::table(TabConf::$fa_redeem_code)
->where('id', $code)
->data(['is_use' => 1])
->update();
//计算奖励
$redeem_code_prize_config = SundryConfig::val('redeem_code_prize_config');
$prize_arr = explode(',', $redeem_code_prize_config);
$prop_arr = [];
foreach ($prize_arr as $prize_str){
$prize_id = explode('-',$prize_str)[0];
$prize_num = explode('-',$prize_str)[1];
//查询道具
$prop = Db::table(TabConf::$fa_gameprop)
->where('id', $prize_id)
->find();
if (empty($prop)) {
continue;
}
//查询道具
$prop_user = Db::table(TabConf::$fa_usergameprop)
->where('openid', api_user_openid())
->where('gameprop_id', $prize_id)
->find();
if($prop_user){
//更新
Db::table(TabConf::$fa_usergameprop)
->where('openid', api_user_openid())
->where('gameprop_id', $prize_id)
->setInc('num', $prize_num);
$prop_user['num'] = $prop_user['num'] + $prize_num;
$prop_arr[] = $prop_user;
}else{
$data = [
'openid'=>api_user_openid(),
'gameproptype_id'=>$prop['gameproptype_id'],
'name'=>$prop['name'],
'gameprop_id'=>$prize_id,
'num'=>$prize_num,
'image'=>$prop['image'],
];
//新增
$data_id = Db::table(TabConf::$fa_usergameprop)
->insertGetId($data);
$data['id'] = $data_id;
$prop_arr[] = $data;
}
}
return Tools::set_ok('使用成功,返回用户获得的道具.',$prop_arr);
});
}
}

View File

@@ -0,0 +1,98 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/7/1} {20:49}
*/
namespace app\api\controller;
use app\common\model\TabConf;
use think\Db;
use wanghua\general_utility_tools_php\Mmodel;
use wanghua\general_utility_tools_php\tool\Tools;
class Usereliminate extends BaseHttpApi
{
/**
* 增加消消乐道具奖励数量
*
* @param string $openid 用户id
* @param string prop_n 修改哪一个道具
* @param string $num 数量 默认1
*
* api/usereliminate/add
* authorwh
*/
function add(){
return Mmodel::catchJson(function (){
$openid = input('openid');
$prop_n = input('prop_n');
$num = input('num',1);
if(empty($openid)){
return Tools::set_fail('缺少参数');
}
if(empty($prop_n)){
return Tools::set_fail('缺少参数.');
}
if(empty($num)){
return Tools::set_fail('缺少参数...');
}
$um = Db::table(TabConf::$fa_usereliminate)
->where('openid',$openid)
->find();
if($um){
Db::table(TabConf::$fa_usereliminate)
->where('openid',$openid)
->setInc($prop_n,$num);
}else{
Db::table(TabConf::$fa_usereliminate)
->data([
'openid'=>$openid,
"$prop_n"=>$num
])
->insert();
}
return Tools::set_ok();
});
}
/**
* 减少消消乐道具奖励数量
*
* @param string $openid 用户id
* @param string prop_n 修改哪一个道具
* @param string $num 数量 默认1
*
* api/usereliminate/cut
* authorwh
*/
function cut(){
return Mmodel::catchJson(function (){
$openid = input('openid');
$prop_n = input('prop_n');
$num = input('num');//减少的数量
if(empty($openid)){
return Tools::set_fail('缺少参数');
}
if(empty($prop_n)){
return Tools::set_fail('缺少参数.');
}
if(empty($num)){
return Tools::set_fail('缺少参数...');
}
Db::table(TabConf::$fa_usereliminate)
->where('openid',$openid)
->where($prop_n,'>',0)
->setDec($prop_n,$num);
return Tools::set_ok();
});
}
}

View File

@@ -0,0 +1,52 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/6/13} {11:33}
*/
namespace app\api\controller;
use app\common\model\TabConf;
use think\Db;
use wanghua\general_utility_tools_php\Mmodel;
use wanghua\general_utility_tools_php\tool\Tools;
class Useremail extends BaseHttpApi
{
/**
* 查询当前登陆人收到的邮件(好友触发了某个操作,同时向你发送了消息,并非真实邮件)
* 默认查询未读消息
* 参数:无
*/
function getMyEmailMessage(){
return Mmodel::catchJson(function (){
$info = Db::table(TabConf::$fa_user_email)
->where('addressee_openid',api_user_openid())
->where('status','0')//查询未读
->select();
return Tools::set_ok($info);
});
}
/**
* 用户邮件-设置已读
* 参数dataid 邮件的数据id
*/
function read(){
return Mmodel::catchJson(function (){
$id = input('dataid');
if(!$id){
return Tools::set_fail('参数错误');
}
Db::table(TabConf::$fa_user_email)
->where('id',$id)
->where('addressee_openid',api_user_openid())
->update(['status'=>'1']);
return Tools::set_ok();
});
}
}

View File

@@ -0,0 +1,140 @@
<?php
namespace app\api\controller;
use app\common\model\TabConf;
use think\Db;
use think\Exception;
use wanghua\general_utility_tools_php\Mmodel;
use wanghua\general_utility_tools_php\tool\Tools;
/**
* 用户游戏道具
* Class Usergameprop
* @package app\api\controller
*/
class Usergameprop extends BaseHttpApi
{
/**
* 用户获得游戏道具接口
* api /api/usergameprop/gainGameProp
*
* @param string $openid 用户openid
* @param int $gameprop_id 道具id
* @param int $num 道具数量
*
*/
public function gainGameProp()
{
Tools::log_to_write_txt(['获取道具 入参:' => input()]);
return Mmodel::catchJson(function (){
$openid = input('openid', '');
$gameprop_id = input('gameprop_id/d', 0);
$num = input('num/d', 1);
if (empty($openid) || empty($gameprop_id)) {
return Tools::set_fail('openid或gameprop_id不能为空');
}
// 检查gameprop_id的有效性
$gamepropExist = Db::table('fa_gameprop')->where('id', $gameprop_id)->find();
if (!$gamepropExist) {
return Tools::set_fail('无效的gameprop_id');
}
// 检查用户是否已拥有该道具
$propExist = Db::table('fa_usergameprop')
->where('openid', $openid)
->where('gameprop_id', $gameprop_id)
->find();
if ($propExist) {
// 更新道具数量
Db::table('fa_usergameprop')
->where('openid', $openid)
->where('gameprop_id', $gameprop_id)
->inc('num', $num)
->update();
} else {
// 新增道具记录
$gameproptype_id = $gamepropExist['gameproptype_id'];
$newData = [
'openid' => $openid,
'gameproptype_id' => $gameproptype_id,
'name' => $gamepropExist['name'],
'gameprop_id' => $gameprop_id,
'num' => $num,
'image' => $gamepropExist['image'],
];
Db::table('fa_usergameprop')->insert($newData);
}
Tools::log_to_write_txt(['获取道具 结果:' => '成功']);
return Tools::set_ok('道具处理成功');
});
}
/**
* 查询用户获得的游戏道具列表接口
* api/usergameprop/listUserGameProps
*
*/
public function listUserGameProps()
{
Tools::log_to_write_txt(['查询道具列表 入参:' => input()]);
try {
$openid = api_user_openid();
// 查询用户道具列表并格式化时间
$props = Db::table('fa_usergameprop')
->where('openid', $openid)
->order('gameprop_id asc')
->select();
Tools::log_to_write_txt(['查询道具列表 结果:' => count($props)]);
return json(Tools::set_ok('查询成功', $props));
} catch (Exception $e) {
Tools::error_txt_log($e);
return json(Tools::set_fail('错误', $e->getMessage()));
}
}
/**
* desc用户消耗游戏道具
*
* api/usergameprop/cutGameProp
* 参数:
* usergameprop_id 用户的游戏道具id
* num 消耗数量默认1
*
* authorwh
*/
function cutGameProp()
{
return Mmodel::catchJson(function (){
$num = input('num',1);
$openid = api_user_openid();
$usergameprop_id = input('usergameprop_id/d', 0);//用户的游戏道具
if (empty($openid) || empty($usergameprop_id)) {
return Tools::set_fail('参数错误');
}
$propExist = Db::table(TabConf::$fa_usergameprop)
->where('openid', $openid)
->where('id', $usergameprop_id)
->find();
if(empty($propExist)){
return Tools::set_fail('道具不存在');
}
if($propExist['num'] <= 0){
return Tools::set_fail('道具不足');
}
if($propExist['num'] - $num < 0){
return Tools::set_fail('道具不足.');
}
Db::table(TabConf::$fa_usergameprop)
->where('id', $usergameprop_id)
->setDec('num', $num);
return Tools::set_ok('消耗成功');
});
}
}

View File

@@ -0,0 +1,245 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/5/25} {16:37}
*/
namespace app\api\controller;
use app\common\model\TabConf;
use think\Db;
use wanghua\general_utility_tools_php\Mmodel;
use wanghua\general_utility_tools_php\tool\Tools;
class Userplant extends BaseHttpApi
{
/**
* desc查询用户拥有的植物列表
*
* api/userplant/listUserPlants
*
* authorwh
*/
function listUserPlants(){
return Mmodel::catchJson(function (){
$openid = api_user_openid();
if (empty($openid)) {
return Tools::set_fail('openid不能为空');
}
$plants = Db::table(TabConf::$fa_userplant)
->where('openid', $openid)
->select();
//foreach ($plants as $plant){
// Db::table(TabConf::$fa_userplantconflaterecord)
//
//}
return Tools::set_ok('查询成功', $plants);
});
}
/**
* desc植物合成
* api/userplant/plantConflate
*
*
* descoperate_type=add时新增植物
* plant_sit 新增植物位置
* sys_plant_id 新增植物id系统植物
*
*
* descoperate_type=drag时拖拽
* old_user_plant_data_id 原用户植物数据id
* new_plant_sit 新植物位置
*
*
* descoperate_type=conflate时合成植物
* target_plant_sit 目标植物位置
* target_sys_plant_id 目标系统植物id
* old_user_plant_data_id 旧用户植物数据id
* new_sys_plant_data_id 新植物数据id
*
*
* desc击杀植物
* operate_type=killPlant
* user_plant_data_id 用户植物数据id
*/
function plantConflate(){
return Mmodel::catchTransJson(function (){
$operate_type = input('operate_type');//操作类型add新增drag拖拽、3 conflate
if($operate_type == 'add'){
return $this->add();
}else if ($operate_type == 'drag'){
return $this->drag();
}else if ($operate_type == 'conflate'){
return $this->conflate();
}
else if ($operate_type == 'killPlant'){
return $this->killPlant();
}
else{
return Tools::set_fail('operate_type参数错误');
}
});
}
/**
* authorwh
*/
private function add(){
$plant_sit = input('plant_sit');
if(empty($plant_sit)){
return Tools::set_fail('plant_sit不能为空');
}
$sys_plant_id = input('sys_plant_id');
if(empty($sys_plant_id)){
return Tools::set_fail('新增植物id系统植物');
}
//有植物就返回该位置有植物
$userplant = Db::table(TabConf::$fa_userplant)
->where('openid', api_user_openid())
->where('plant_id', $sys_plant_id)
->where('plant_sit', $plant_sit)
->find();
if($userplant){
return Tools::set_fail('该位置有植物');
}
$plant = Db::table(TabConf::$fa_plant)
->where('id', $sys_plant_id)
->find();
if(empty($plant)){
return Tools::set_fail('植物不存在');
}
$data = [
'openid'=>api_user_openid(),
'plant_sit'=>$plant_sit,
'plant_id'=>$sys_plant_id,
'name'=>$plant['name'],
'image'=>$plant['image'],
];
//新增植物
$dataid = Db::table(TabConf::$fa_userplant)
->insertGetId($data);
$data['id'] = $dataid;
return Tools::set_ok('ok',$data);
}
/**
* authorwh
*/
private function drag(){
$new_plant_sit = input('new_plant_sit');
if(empty($new_plant_sit)){
return Tools::set_fail('新植物位置');
}
$old_user_plant_data_id = input('old_user_plant_data_id');
if(empty($old_user_plant_data_id)){
return Tools::set_fail('原用户植物数据id不能为空');
}
//原用户植物
$old_user_plant = Db::table(TabConf::$fa_userplant)
->where('id',$old_user_plant_data_id)
->where('openid',api_user_openid())
->find();
if(empty($old_user_plant)){
return Tools::set_fail('原用户植物数据不存在');
}
//有植物就返回该位置有植物
$userplant = Db::table(TabConf::$fa_userplant)
->where('openid', api_user_openid())
->where('plant_sit', $new_plant_sit)
->find();
if($userplant){
return Tools::set_fail('该位置有植物');
}
//更新该位置的植物
Db::table(TabConf::$fa_userplant)
->where('id', $old_user_plant['id'])
->update([
'plant_sit'=>$new_plant_sit,
]);
return Tools::set_ok('ok');
}
/**
* authorwh
*/
private function conflate(){
$target_plant_sit = input('target_plant_sit');
if(empty($target_plant_sit)){
return Tools::set_fail('target_plant_sit目标植物位置不能为空');
}
$target_sys_plant_id = input('target_sys_plant_id');//目标植物
if(empty($target_sys_plant_id)){
return Tools::set_fail('目标系统植物id不能为空');
}
//合成逻辑,该位置没有植物,给与提示
$userplant = Db::table(TabConf::$fa_userplant)
->where('openid', api_user_openid())
->where('plant_sit', $target_plant_sit)
->find();
if(empty($userplant)){
return Tools::set_fail('该位置没有植物');
}
//获取该位置植物信息,如果该位置的植物不相等,提示不能合成
if($userplant['plant_id'] != $target_sys_plant_id){
return Tools::set_fail('该位置植物不相同,不能合成');
}
//删除原位置的植物,更新当前位置的植物信息
$old_user_plant_data_id = input('old_user_plant_data_id');
if(empty($old_user_plant_data_id)){
return Tools::set_fail('原用户植物数据id不能为空');
}
Db::table(TabConf::$fa_userplant)
->where('id', $old_user_plant_data_id)
->where('openid', api_user_openid())
->delete();
$new_sys_plant_data_id = input('new_sys_plant_data_id');
if(empty($new_sys_plant_data_id)){
return Tools::set_fail('新系统植物id不能为空');
}
$new_plant = Db::table(TabConf::$fa_plant)
->where('id', $new_sys_plant_data_id)
->find();
if(empty($new_plant)){
return Tools::set_fail('新植物不存在');
}
//更新当前位置的植物信息
Db::table(TabConf::$fa_userplant)
->where('openid', api_user_openid())
->where('plant_sit', $target_plant_sit)
->update([
'plant_id'=>$new_plant['id'],
'name'=>$new_plant['name'],
'image'=>$new_plant['image'],
]);
return Tools::set_ok('ok');
}
/**
* authorwh
*/
private function killPlant(){
$user_plant_data_id = input('user_plant_data_id');
if(empty($user_plant_data_id)){
return Tools::set_fail('user_plant_data_id不能为空');
}
$userplant = Db::table(TabConf::$fa_userplant)
->where('id', $user_plant_data_id)
->where('openid', api_user_openid())
->find();
if(empty($userplant)){
return Tools::set_fail('该植物不存在');
}
//删除该植物
Db::table(TabConf::$fa_userplant)
->where('id', $user_plant_data_id)
->where('openid', api_user_openid())
->delete();
return Tools::set_ok('ok');
}
}

View File

@@ -0,0 +1,909 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/3/26} {20:55}
*/
namespace app\api\controller;
use app\api\logic\UserOfflinePrizeLogic;
use app\common\model\TabConf;
use GatewayWorker\Lib\Gateway;
use think\Db;
use think\Exception;
use wanghua\general_utility_tools_php\Mmodel;
use wanghua\general_utility_tools_php\SundryConfig;
use wanghua\general_utility_tools_php\tool\Tools;
use wanghua\general_utility_tools_php\wechat\UserAuth;
class Users extends BaseHttpApi
{
/**
* desc根据游戏id查询用户
* api/Users/getUserById
* 参数:
* gameid 用户id
* authorwh
*/
function getUserById(){
return Mmodel::catchJson(function (){
$gameid = input('gameid');
if(empty($gameid)){
return Tools::set_fail('参数错误');
}
$data = Db::table(TabConf::$fa_users)
->where('id',$gameid*1)
->find();
return Tools::set_res(200,'查询成功',$data);
});
}
/**
* desc根据openid查询用户
* api/Users/getUserInfo
* 参数:
* openid
*
* 返回:
* now_rank 当前排名
* all_coins: 累计获得金币
* enemy 累计击杀数
* eliminate 消消乐道具
*/
function getUserInfo(){
Tools::log_to_write_txt(['查询单个用户 入参:'=>input()]);
try {
$openid = input('openid');
if(empty($openid)){
return json(Tools::set_fail('参数错误'));
}
$model_obj = Db::table('fa_users');
if(input('openid')){
$model_obj->where('openid',input('openid'));
}
$data = $model_obj->find();
if(empty($data)){
return json(Tools::set_res(234,'用户不存在'));
}
//更新用户最后登录时间
Db::table('fa_users')
->data(['last_login_time'=>Tools::get_now_date()])
->where('id',$data['id'])
->update();
//写入登录记录
Mmodel::existsUpdateInsert('fa_login_record',['date'=>date('Y-m-d')],[
'openid'=>$openid,
'date'=>date('Y-m-d')
]);
//总计登录天数
$data['total_login_days'] = Db::table('fa_login_record')
->where('openid',$openid)
->count('id');
//当前排名
$data['now_rank'] = $this->countRank($openid);
//eliminate
$eliminate = Db::table('fa_usereliminate')
->where('openid',$data['openid'])
->select();
$data['eliminate'] = $eliminate;
return json(Tools::set_ok('ok',$data));
}catch(\Exception $e){
Tools::log_to_write_txt([
'error'=>'查询单个用户.异常.'.$e->getMessage(),
'参数'=>input(),
'error_info'=>$e->getTraceAsString()
]);
return json(Tools::set_res(500,'操作异常',[]));
}
}
/**
* desc计算排名
* authorwh
*/
private function countRank($openid){
if(cache('user_rank_'.$openid)){
return cache('user_rank_'.$openid);
}
$lists = Db::table(TabConf::$fa_users)
->order('now_level desc')
->field('openid,now_level')
->select();
if($lists){
foreach ($lists as $k=>$v){
if($v['openid'] == $openid){
cache('user_rank_'.$openid,$k+1,3600);
return $k+1;
}
}
}
return 0;//没有排名
}
/**
* desc微信授权登录
*
* /api/users/login
*
* 参数:code
*
* authorwh
*/
function login()
{
Db::startTrans();
try {
$clientid = input('clientid');
if(empty($clientid)){
return json(Tools::set_fail('clientid error'));
}
$code = input('code');
if(empty($code)){
return json(Tools::set_fail('CODE参数错误'));
}
$wxconfig = get_wechat_config();
Tools::log_to_write_txt(['微信授权start'=>input(),'$wxconfig'=>$wxconfig]);
$res = (new UserAuth($wxconfig))->usrAccessTokenApplet($code);
Tools::log_to_write_txt(['微信授权end'=>$res]);
$openid = $res['openid'];
$user = Db::table(TabConf::$fa_users)->where('openid',$openid)->find();
if(empty($user)){
$data = [
'openid'=>$openid,
'nickname'=>Tools::rand_str(),
'headimage'=>'',
'hint_num'=>3,
'clientid'=>$clientid,
'user_type'=>'wechat'
];
//新增一个用户
$id = Db::table(TabConf::$fa_users)
->insertGetId($data);
$data['id'] = $id;
}else{
Db::table(TabConf::$fa_users)
->where('openid',$openid)
->data(['clientid'=>$clientid])//更新登录状态
->update();
$data = $user;
}
session('api_user_info',$data);
Db::commit();
return json(Tools::set_ok('ok',$res));
}catch (\Exception $e){
Db::rollback();
Tools::log_to_write_text([
'error'=>'微信授权异常。'.$e->getMessage(),
'input'=>input(),
'error_info'=>$e->getTraceAsString()
]);
return json(Tools::set_fail('请求异常'));
}
}
/**
* desc修改用户昵称、头像
*
* /api/users/updateuser
*
* 参数:
* openid 必传
* nicknameheadimage
*/
function updateuser(){
return Mmodel::catchJson(function (){
$nickname = input('nickname','');
$headimage = input('headimage','');
$data = [];
if($nickname){
$data['nickname'] = $nickname;
}
if($headimage){
$data['headimage'] = $headimage;
}
$openid = input('openid');
if(empty($openid)){
return Tools::set_fail('OPENID MUST');
}
if(!empty($data)){
Db::table(TabConf::$fa_users)
->where('openid',$openid)
->data($data)
->update();
}
return Tools::set_ok();
});
}
/**
* desc更新最新关卡
* api/users/updatenowlevel
*
* 参数:
* now_level 最新关卡
* authorwh
*/
function updateNowLevel(){
return Mmodel::catchJson(function (){
$now_level = input('now_level');
if(empty($now_level)){
return Tools::set_fail('now_level 必须');
}
Db::table(TabConf::$fa_users)
->where('openid',api_user_openid())
->update([
'now_level'=>$now_level,
]);
return Tools::set_ok();
});
}
/**
* desc查询好友列表-计算离线奖励
* /api/users/getFriendsOfflinePrizeList
*
* 离线奖励:从用户下线时刻开始每3个小时奖励一瓶随机等级的肥料只取整数不四舍五入。离线时长除以3取整数。
* 比如:离线 0-2.9 个小时 不奖励
离线 3-5.9 个小时 奖励 1瓶
离线 6-8.9 个小时 奖励 2瓶
*
gameprop_id 道具奖品
prize_all_num 总奖励数量
self_got_num 自己保底所得数量(固定)
can_lose_num 可被偷取的数量(固定)
now_can_lose_num 已偷取(偷取后数值增加,数值大于可被偷取的总数量时,拒绝偷取)
* authorwh
*/
function getFriendsOfflinePrizeList(){
return Mmodel::catchJson(function (){
//查询我的离线好友
$friends = Db::table(TabConf::$fa_gamefriend)
->where('openid',api_user_openid())
->select();
if(empty($friends)){
return Tools::set_res(220,'没有好友');
}
//可偷取的奖励部分每次允许偷取比例配置
$lose_rate = SundryConfig::val('offline_prize_can_lose_per_times_lose_rate');
foreach ($friends as &$list){
$friend_openid = $list['friend_openid'];
$sql = "
select * from fa_user_offline_prize a left join
fa_user_offline_prize_got_record b
on a.id = b.user_offline_prizeid
where a.openid='{$friend_openid}' and b.user_offline_prizeid is null;
";
//查询好友的离线奖励
$friend_prize = Db::query($sql);
//统计我的已偷取数量
//$my_already_lose_num = Db::table(TabConf::$fa_user_offline_prize_got_record)
// ->where('openid',api_user_openid())
// ->whereIn('user_offline_prizeid',array_column($friend_prize,'id'))
// ->sum('num');
//统计我的已偷取数量=$can_lose_num*$lose_rate如果相等就设置偷取数量为0
$can_lose_num_arr = array_column($friend_prize,'can_lose_num');
//总的可偷取数量
$can_lose_num = array_sum($can_lose_num_arr);
$already_lose_num_arr = array_column($friend_prize,'already_lose_num');
//已偷取的总数量
$already_lose_num = array_sum($already_lose_num_arr);
$friend_prize['now_can_lose_num'] = floor(($can_lose_num-$already_lose_num)*$lose_rate);
$friend_prize['lose_rate'] = $lose_rate;
$tmp_arr = [];
//查询好友的奖励
$tmp_arr['friend_prize'] = $friend_prize;
$list = array_merge($list, $tmp_arr);
//$can_lose_num_arr = array_column($friend_prize,'can_lose_num');
//$can_lose_num = array_sum($can_lose_num_arr);//总的可偷取数量
//if($my_already_lose_num == $can_lose_num*$lose_rate){
// //默认为0
// $friend_prize['now_can_lose_num'] = 0;
// $friend_prize['lose_rate'] = 0;
// $tmp_arr = [];
// $tmp_arr['friend_prize'] = $friend_prize;
// $list = array_merge($list, $tmp_arr);
//}else{
// //过滤已偷过的记录
// //$already_lose_record = Db::table(TabConf::$fa_user_offline_prize_got_record)
// // ->where('openid',api_user_openid())
// // ->whereIn('user_offline_prizeid',array_column($friend_prize,'id'))
// // ->select();
// $friend_prize = Db::table(TabConf::$fa_user_offline_prize)
// ->where('openid',$list['friend_openid'])
// ->whereNotIn('id',array_column($already_lose_record,'id'))//剔除已偷过的记录
// ->select();
//
// $can_lose_num_arr = array_column($friend_prize,'can_lose_num');
// //总的可偷取数量
// $can_lose_num = array_sum($can_lose_num_arr);
// $already_lose_num_arr = array_column($friend_prize,'already_lose_num');
// //已偷取的总数量
// $already_lose_num = array_sum($already_lose_num_arr);
//
// $friend_prize['now_can_lose_num'] = floor(($can_lose_num-$already_lose_num)*$lose_rate);
// $friend_prize['lose_rate'] = $lose_rate;
//
// $tmp_arr = [];
// //查询好友的奖励
// $tmp_arr['friend_prize'] = $friend_prize;
// $list = array_merge($list, $tmp_arr);
//}
}
return Tools::set_ok('ok',$friends);
});
}
/**
* desc随机奖励
*/
private function random_prop($key=''){
$count = Db::table(TabConf::$fa_gameprop)
->count('id');
$id = mt_rand(1,$count);
$p = Db::table(TabConf::$fa_gameprop)->where('id',$id)->find();
if(empty($p)){
$id = mt_rand(1,$count);
$p = Db::table(TabConf::$fa_gameprop)->where('id',$id)->find();
}
if(empty($p)){
throw new Exception('道具获取失败');
}
return $key?$p[$key]:$p;
}
/**
* desc偷取领取好友离线奖励领取多少根据后台配置领取比例而定偷取后发邮件给用户
*
* api/users/offlineprizegot
* 参数:
* friend_openid 好友
*
* authorwh
*/
function offlinePrizeGot(){
return Mmodel::catchTransJson(function (){
$friend_openid = input('friend_openid');
if(empty($friend_openid)){
return Tools::set_fail('friend_openid 必须');
}
//可偷取的奖励部分每次允许偷取比例配置
$lose_rate = SundryConfig::val('offline_prize_can_lose_per_times_lose_rate');
$sql = "
select a.* from fa_user_offline_prize a left join
fa_user_offline_prize_got_record b
on a.id = b.user_offline_prizeid
where a.openid='{$friend_openid}' and b.user_offline_prizeid is null;
";
//查询好友的离线奖励
$prize_lists = Db::query($sql);
$got_prize_arr = [];
foreach ($prize_lists as $prize){
$gameprop_id = $prize['gameprop_id'];
//计算本次可领取奖励
$num = floor($prize['can_lose_num'] * $lose_rate);
if($num<=0){
//偷取数量为0
$got_prize_arr[]=[
'num'=>0,
'gameprop_id'=>0
];
continue;
}
//查询用户已有道具
$usergameprop = Db::table(TabConf::$fa_usergameprop)
->where('openid',api_user_openid())
->where('gameprop_id',$gameprop_id)
->find();
//偷取时更新奖励
if($usergameprop){
//更新用户道具数量
Db::table(TabConf::$fa_usergameprop)
->where('openid',api_user_openid())
->where('gameprop_id',$gameprop_id)
->setInc('num',$num);
}else{
//查询道具
$gameprop = Db::table(TabConf::$fa_gameprop)
->where('id',$prize['gameprop_id'])
->find();
//新增用户道具
Db::table(TabConf::$fa_usergameprop)
->data([
'gameproptype_id'=>$gameprop['gameproptype_id'],
'name'=>$gameprop['name'],
'image'=>$gameprop['image'],
'openid'=>api_user_openid(),
'num'=>$num,
'gameprop_id'=>$gameprop_id
])
->insert();
}
//偷取时,增加已偷取数量
Db::table(TabConf::$fa_user_offline_prize)
->where('id',$prize['id'])
->setInc('already_lose_num',$num);
//写入(偷取)领取记录
Db::table(TabConf::$fa_user_offline_prize_got_record)
->data([
'openid'=>api_user_openid(),
'friend_openid'=>$friend_openid,
'num'=>$num,
'gameprop_id'=>$gameprop_id,
'user_offline_prizeid'=>$prize['id'],//记录id
])
->insert();
$got_prize_arr[]=[
'num'=>$num,
'gameprop_id'=>$gameprop_id
];
}
//添加一封邮件(不是真实的邮件,可以理解为消息)
Db::table(TabConf::$fa_user_email)
->data([
'addresser_openid'=>api_user_openid(),
'addressee_openid'=>$friend_openid,//收件人
'title'=>'好友偷取奖励',
'content'=>'您的奖励已被好友偷取啦!',
])
->insert();
return Tools::set_ok('ok',$got_prize_arr);
});
}
/**
* 查询自己的离线奖励
*
* 离线奖励:从用户下线时刻开始每3个小时奖励一瓶随机等级的肥料只取整数不四舍五入。离线时长除以3取整数。
* 比如:离线 0-2.9 个小时 不奖励
离线 3-5.9 个小时 奖励 1瓶
离线 6-8.9 个小时 奖励 2瓶
*
* api/users/getselfofflineprize
*/
function getSelfOfflinePrize(){
return Mmodel::catchJson(function (){
$lists = Db::table(TabConf::$fa_user_offline_prize)
->where('openid',api_user_openid())
->order('id asc')//客户端要取最早的那个时间
->select();
if(empty($lists)){
return Tools::set_res(220,'没有离线奖励');
}
//可偷取的奖励部分每次允许偷取比例配置
$lose_rate = SundryConfig::val('offline_prize_can_lose_per_times_lose_rate');
$lists_data = [];
foreach ($lists as $list){
if($list['self_got_num']==0){
continue;//领取过的数据,不返回
}
$record = Db::table(TabConf::$fa_user_offline_prize_got_record)
->where('openid',api_user_openid())//当前登陆人
->where('user_offline_prizeid',$list['id'])
->find();
if(empty($record)){//为空说明未偷取
$lists_data[] = array_merge($list, ['now_can_lose_num'=>floor($list['can_lose_num']*$lose_rate),'lose_rate'=>$lose_rate]);
}else{
$lists_data[] = array_merge($list, ['now_can_lose_num'=>0]);
}
}
return Tools::set_ok('ok',$lists_data);
});
}
/**
* desc领取自己的离线奖励一次性领取所有离线奖励不能分批次领取没有部分领取一说
* api/users/receiveSelfOfflinePrize
* 参数:
* is_double 是否双倍奖励 1 一倍2 二倍
* authorwh
*/
function receiveSelfOfflinePrize(){
return Mmodel::catchTransJson(function (){
//查询我的离线奖励
$prize_lists = Db::table(TabConf::$fa_user_offline_prize)
->where('openid',api_user_openid())
->lock(true)//锁住
->select();
$got_prize_arr = [];
//是否双倍奖励 1 一倍2 二倍
$is_double = input('is_double',1);
foreach ($prize_lists as $item){
//查询领取记录
$offline_prize_got_record = Db::table(TabConf::$fa_user_offline_prize_got_record)
->where('openid',api_user_openid())
->where('user_offline_prizeid',$item['id'])
->find();
if($offline_prize_got_record){
continue;//领取过的数据,不能再次领取
}
//道具id
$gameprop_id = $item['gameprop_id'];
//自己保底所得数量+可被偷取的数量-已被偷取的数量
$prize_all_num = $item['self_got_num'] + $item['can_lose_num'] - $item['already_lose_num'];
//乘以倍数
$num = $prize_all_num * $is_double;
//查询道具
$gameprop = Db::table(TabConf::$fa_gameprop)
->where('id',$gameprop_id)
->find();
if(empty($gameprop)){
//道具不应该不存在
continue;
//return Tools::set_fail('道具不存在');
}
//写入领取记录
Db::table(TabConf::$fa_user_offline_prize_got_record)
->data([
'openid'=>api_user_openid(),
'num'=>$num,
'gameprop_id'=>$gameprop_id,
'is_double'=>$is_double,
'user_offline_prizeid'=>$item['id'],
])
->insert();
//查询用户已有道具
$usergameprop = Db::table(TabConf::$fa_usergameprop)
->where('openid',api_user_openid())
->where('gameprop_id',$gameprop_id)
->find();
if($usergameprop){
//更新道具数量
Db::table(TabConf::$fa_usergameprop)
->where('openid',api_user_openid())
->where('gameprop_id',$gameprop_id)
->setInc('num',$num);
}else{
//新增道具
Db::table(TabConf::$fa_usergameprop)
->data([
'gameproptype_id'=>$gameprop['gameproptype_id'],
'name'=>$gameprop['name'],
'image'=>$gameprop['image'],
'openid'=>api_user_openid(),
'num'=>$num,
'gameprop_id'=>$gameprop_id
])
->insert();
}
Db::table(TabConf::$fa_user_offline_prize)
->where('id',$item['id'])
->data([
'self_got_num'=>0,
'can_lose_num'=>0,
])
->update();
$got_prize_arr[]=[
'num'=>$num,
'gameprop_id'=>$gameprop_id
];
}
//领取之后删除离线奖励表
UserOfflinePrizeLogic::deletedPrize(api_user_openid());
return Tools::set_ok('领取成功',$got_prize_arr);
});
}
/**
* desc查询我的好友列表
*
* api/users/getMyFriends
*
* authorwh
*/
function getMyFriends(){
return Mmodel::catchJson(function (){
$lists = Db::table(TabConf::$fa_gamefriend)
->where('openid',api_user_openid())
->select();
return Tools::set_ok('ok',$lists);
});
}
/**
* desc添加好友
*
* api/users/addFriend
* 参数:
* friend_openid 好友openid
* 注意:如果好友在线,会向好友发送申请消息
* authorwh
*/
function addFriend(){
return Mmodel::catchJson(function (){
$friend_openid = input('friend_openid');
if(empty($friend_openid)){
return Tools::set_fail('请输入好友openid');
}
$user_friend = Db::table(TabConf::$fa_users)
->where('openid',$friend_openid)
->find();
if(empty($user_friend)){
return Tools::set_fail('好友不存在');
}
$uf = Db::table(TabConf::$fa_gamefriend)
->where('openid',api_user_openid())
->where('friend_openid',$friend_openid)
->find();
if($uf){
return Tools::set_fail('不能添加自己和自己的好友');
}
if($friend_openid == api_user_openid()){
return Tools::set_fail('不能添加自己');
}
$data = [
'openid'=>api_user_openid(),
'headimage'=>api_user_info('headimage'),
'nickname'=>api_user_info('nickname'),
'friend_openid'=>$friend_openid,
'friend_nickname'=>$user_friend['nickname']
];
//如果已经申请则不再申请
$apply_record = Db::table(TabConf::$fa_friend_apply_record)
->where('openid',api_user_openid())
->where('friend_openid',$friend_openid)
->find();
if($apply_record){
return Tools::set_fail('你已申请过该好友');
}
Db::table(TabConf::$fa_friend_apply_record)
->data($data)
->insert();
//如果好友在线,则发送添加好友申请
if($user_friend['clientid']){
$json = BaseWssApi::json_wss('new-friend-apply', '有新的好友申请');
Gateway::sendToClient($user_friend['clientid'], json_encode($json, JSON_UNESCAPED_UNICODE));
}
return Tools::set_ok('申请已发送');
});
}
/**
* desc查询我的好友申请列表
*
* api/users/getFriendApplyList
* authorwh
*/
function getFriendApplyList(){
return Mmodel::catchJson(function (){
$friend_apply_record = Db::table(TabConf::$fa_friend_apply_record)
->where('friend_openid',api_user_openid())
->select();
return Tools::set_ok('ok',$friend_apply_record);
});
}
/**
* 同意好友申请
* api/users/agreeFriendApply
* 参数:
* friend_openid 好友openid
*/
function agreeFriendApply(){
return Mmodel::catchTransJson(function (){
$friend_openid = input('friend_openid');
if(empty($friend_openid)){
return Tools::set_fail('请输入好友openid');
}
$user_friend = Db::table(TabConf::$fa_users)
->where('openid',$friend_openid)
->find();
if(empty($user_friend)){
return Tools::set_fail('好友不存在.');
}
//好友已存在
$uf = Db::table(TabConf::$fa_gamefriend)
->where('openid',api_user_openid())
->where('friend_openid',$friend_openid)
->find();
if($uf){
return Tools::set_fail('好友已存在');
}
//添加陌生人为好友
Db::table(TabConf::$fa_gamefriend)
->data([
'openid'=>api_user_openid(),
'nickname'=>api_user_info('nickname'),
'friend_openid'=>$friend_openid,
'friend_nickname'=>$user_friend['nickname'],
'friend_image'=>$user_friend['headimage'],
])
->insert();
//把自己添加为陌生人的好友
Db::table(TabConf::$fa_gamefriend)
->data([
'openid'=>$friend_openid,
'nickname'=>$user_friend['nickname'],
'friend_openid'=>api_user_openid(),
'friend_nickname'=>api_user_info('nickname'),
'friend_image'=>api_user_info('headimage'),
])
->insert();
//删除好友申请记录
Db::table(TabConf::$fa_friend_apply_record)
->where('openid',$friend_openid)
//->where('friend_openid',$friend_openid)
->delete();
return Tools::set_ok('ok');
});
}
/**
* 拒绝好友申请
*
* api/users/refuseFriendApply
* 参数:
* friend_openid 好友openid
*/
function refuseFriendApply(){
return Mmodel::catchTransJson(function (){
$friend_openid = input('friend_openid');
if(empty($friend_openid)){
return Tools::set_fail('请输入好友openid');
}
$users = Db::table(TabConf::$fa_users)
->where('openid',$friend_openid)
->find();
if(empty($users)){
return Tools::set_fail('用户不存在');
}
//删除好友申请记录
Db::table(TabConf::$fa_friend_apply_record)
->where('openid',$friend_openid)
//->where('friend_openid',$friend_openid)
->delete();
return Tools::set_ok('ok');
});
}
/**
* desc增加金币,直接存用户信息里
* authorwh
* 参数:
* coins 金币数量
*/
function addCoins(){
return Mmodel::catchTransJson(function (){
$coins = input('coins');
if(empty($coins)){
return Tools::set_fail('请输入金币');
}
Db::table(TabConf::$fa_users)
->where('openid',api_user_openid())
->setInc('coins',$coins);
Db::table(TabConf::$fa_users)
->where('openid',api_user_openid())
->setInc('all_coins',$coins);//累计金币
return Tools::set_ok('ok');
});
}
/**
* desc消耗金币
* authorwh
* 参数:
* coins 金币数量
*/
function cutCoins(){
return Mmodel::catchJson(function (){
$coins = input('coins');
if(empty($coins)){
return Tools::set_fail('请输入金币');
}
Db::table(TabConf::$fa_users)
->where('openid',api_user_openid())
->setDec('coins',$coins);
return Tools::set_ok('ok');
});
}
/**
* 消耗金币增加体力(消耗金币增加体力次数减一)
* 参数:无
* api/users/cutCoinsAddStrength
*/
function cutCoinsAddStrength(){
return Mmodel::catchTransJson(function (){
//消耗金币增加体力的金币数值配置
$cut_n_coins_add_power = SundryConfig::val('cut_n_coins_add_power');
$user = Db::table(TabConf::$fa_users)
->where('openid',api_user_openid())
->lock(true)
->find();
if($user['coin_power_times'] <= 0){
return Tools::set_fail('金币增加体力次数不足');
}
if($user['coins'] < $cut_n_coins_add_power){
return Tools::set_fail('金币不足');
}
//消耗金币
Db::table(TabConf::$fa_users)
->where('openid',api_user_openid())
->setDec('coins',$cut_n_coins_add_power);
//增加体力
Db::table(TabConf::$fa_users)
->where('openid',api_user_openid())
->setInc('power',1);
//减少金币增加体力次数
Db::table(TabConf::$fa_users)
->where('openid',api_user_openid())
->where('coin_power_times','>',0)
->setDec('coin_power_times',1);
return Tools::set_ok('ok');
});
}
/**
* 看广告增加体力 (看广告增加体力次数减一)
* 参数:无
* api/users/lookAdAddPower
*/
function lookAdAddPower(){
return Mmodel::catchTransJson(function (){
$user = Db::table(TabConf::$fa_users)
->where('openid',api_user_openid())
->lock(true)
->find();
if($user['ad_power_times'] <= 0){
return Tools::set_fail('看广告增加体力次数不足');
}
//增加体力
Db::table(TabConf::$fa_users)
->where('openid',api_user_openid())
->setInc('power',1);
//
Db::table(TabConf::$fa_users)
->where('openid',api_user_openid())
->where('ad_power_times','>',0)
->setDec('ad_power_times',1);
return Tools::set_ok('ok');
});
}
}

View File

@@ -0,0 +1,81 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/4/5} {19:51}
*/
namespace app\api\controller;
use app\api\logic\StatisticsLogic;
use app\common\model\TabConf;
use GatewayWorker\Lib\Gateway;
use think\Db;
use wanghua\general_utility_tools_php\Date;
use wanghua\general_utility_tools_php\tool\Tools;
/**
* socket 主动推送
*
* Class Wsspush
* @package app\api\controller
*/
class Wsspush extends BaseWssApi
{
public function index()
{
$socketTaskId = input('socketTaskId');
Gateway::sendToClient($socketTaskId,json_encode(Tools::set_ok('向指定客户端发送信息。',$socketTaskId),JSON_UNESCAPED_UNICODE));
}
public function hello($name = 'ThinkPHP5')
{
return 'hello,' . $name;
}
/**
* desc向客户端推送消息
*
* 接收一维数组表单
*
* /api/wsspush/pushMessageToClient
*
* authorwh
*/
function pushMessageToClient(){
$socketTaskId = input('clientid');
if(empty($socketTaskId)){
return json(Tools::set_fail('客户端id必须'));
}
$action = input('action');
if(empty($action)){
return json(Tools::set_fail('ACTION MUST'));
}
$msg = input('msg');
if(empty($msg)){
return json(Tools::set_fail('MSG MUST'));
}
$all_params = [];
foreach (input() as $key=>$item){
if(in_array($key, ['clientid','action','msg'])){
continue;
}
$all_params[$key] = $item;
}
//json_encode(Tools::set_ok('向指定客户端发送信息。',$socketTaskId),JSON_UNESCAPED_UNICODE);
$json = self::json_wss($action,$msg,$all_params);
Gateway::sendToClient($socketTaskId, $json);
return json(Tools::set_ok('向指定客户端发送信息成功。'));
}
}

View File

@@ -0,0 +1,103 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/5/23} {18:01}
*/
namespace app\api\logic;
use app\api\controller\BaseWssApi;
use GatewayWorker\Lib\Gateway;
use think\Db;
use wanghua\general_utility_tools_php\tool\Tools;
class BaseLogic
{
function domsg($client_id, $data){
try {
$res = @json_decode($data, true);
Tools::log_to_write_txt(['json_decode:', $res]);
if (!$res) {
$json = BaseWssApi::json_wss('error', '消息格式错误');
Gateway::sendToClient($client_id, json_encode($json, JSON_UNESCAPED_UNICODE));
return;
}
if (empty($res['action'])) {
$json = BaseWssApi::json_wss('error', '消息格式错误action必须');
Gateway::sendToClient($client_id, json_encode($json, JSON_UNESCAPED_UNICODE));
return;
}
$act_arr = explode('/', $res['action']);
if (empty($act_arr[0])) {
$json = BaseWssApi::json_wss('error', '错误的action格式');
Gateway::sendToClient($client_id, json_encode($json, JSON_UNESCAPED_UNICODE));
return;
}
if (empty($act_arr[1])) {
$json = BaseWssApi::json_wss('error', '错误的action格式');
Gateway::sendToClient($client_id, json_encode($json, JSON_UNESCAPED_UNICODE));
return;
}
//根据action执行业务逻辑
$controller = ucfirst($act_arr[0]);
$function = $act_arr[1];
$object = '\\app\\api\\logic\\' . $controller . 'Logic';
$obj = $this->getinstance($object);
$obj->$function($client_id, $res);
} catch (\Exception $e) {
Tools::error_txt_log($e);
$json = BaseWssApi::json_wss('error', '服务繁忙');
Gateway::sendToClient($client_id, json_encode($json, JSON_UNESCAPED_UNICODE));
}
}
function getinstance($className)
{
// 类名字符串
// 参数数组
// 确保类存在
if (!class_exists($className)) {
throw new \InvalidArgumentException("Class {$className} does not exist.");
}
// 创建反射类实例
$reflection = new \ReflectionClass($className);
// 检查构造函数是否存在
//if (!$reflection->hasMethod('__construct')) {
// throw new \LogicException("Class {$className} has no constructor.");
//}
//$constructor = $reflection->getConstructor();
// 如果构造函数有参数,我们需要匹配参数
//if ($constructor !== null) {
// $constructorParams = $constructor->getParameters();
//
// // 确保参数数量匹配
// if (count($constructorParams) !== count($params)) {
// throw new \InvalidArgumentException("Number of constructor parameters does not match provided arguments.");
//
// }
// // 创建参数数组,将参数类型与值匹配
// $matchedParams = [];
// foreach ($constructorParams as $index => $param) {
// // 如果参数允许null或者参数类型与传递的值兼容添加到匹配参数数组
// if ($param->allowsNull() || $param->getClass() === null || $param->getClass()->isInstance($params[$index])) {
// $matchedParams[] = $params[$index];
// } else {
// throw new \InvalidArgumentException("Provided argument does not match constructor parameter type at position {$index}.");
// }
// }
// // 使用反射类创建并初始化类实例
// $instance = $reflection->newInstanceArgs($matchedParams);
//} else {
//
//}
// 构造函数无参数,直接创建实例
$instance = $reflection->newInstanceWithoutConstructor();
return $instance;
}
}

View File

@@ -0,0 +1,36 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/6/18} {18:05}
*/
namespace app\api\logic;
use app\common\model\TabConf;
use think\Db;
use wanghua\general_utility_tools_php\Mmodel;
use wanghua\general_utility_tools_php\tool\Tools;
class EnemyLogic extends BaseLogic
{
/**
* desc累加击杀敌人数量
*
* 参数enemy_num
*
* authorwh
*/
function addKillEnemyNum(){
return Mmodel::catchJson(function (){
$enemy_num = input('enemy_num',1);
Db::table(TabConf::$fa_users)
->where('openid',api_user_openid())
->setInc('enemy',$enemy_num);//累加击杀敌人数量
return Tools::set_ok();
});
}
}

View File

@@ -0,0 +1,70 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/5/23} {18:01}
*/
namespace app\api\logic;
use app\api\controller\BaseWssApi;
use app\common\model\TabConf;
use GatewayWorker\Lib\Gateway;
use think\Db;
use wanghua\general_utility_tools_php\Mmodel;
use wanghua\general_utility_tools_php\tool\Tools;
class UserLogic extends BaseLogic
{
/**
* desc客户端离线
* authorwh
*/
function offline($client_id){
Mmodel::catchTrans(function () use ($client_id){
Tools::log_to_write_txt(['服务端收到客户端离线消息client_id:' . $client_id]);
$user = Db::table(TabConf::$fa_users)
->where('clientid', $client_id)
->find();
if(empty($user)){
Tools::log_to_write_txt(['error:客户端离线用户不存在client_id:' . $client_id]);
return ;
}
Tools::log_to_write_txt(['写入离线记录openid:' . $user['openid']]);
//写入离线记录
Db::table(TabConf::$fa_user_offline_record)
->insert([
'openid'=>$user['openid'],
]);
Tools::log_to_write_txt(['设置离线时间clientid:' . $client_id]);
Db::table(TabConf::$fa_users)
->where('clientid', $client_id)
->data([
'clientid'=>'',
'offline_time'=>Tools::get_now_date(),//离线时间
])
->update();
Tools::log_to_write_txt(['好友列表设置为离线openid:' . $user['openid']]);
//好友列表设置为离线
Db::table(TabConf::$fa_gamefriend)
->data([
'offline_time'=>Tools::get_now_date(),//离线时间
])
->where('friend_openid',$user['openid'])
->update();
Tools::log_to_write_txt(['返回离线消息']);
//在$client_id无效的情况下可能会抛出异常
//$json = BaseWssApi::json_wss('ok', '用户已离线');
//Gateway::sendToClient($client_id, json_encode($json, JSON_UNESCAPED_UNICODE));
});
}
}

View File

@@ -0,0 +1,69 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/6/2} {10:51}
*/
namespace app\api\logic;
use app\common\model\TabConf;
use think\Db;
use wanghua\general_utility_tools_php\Mmodel;
/**
* 用户离线奖品表(用户上线时写入,领取后删除)
* Class UserOfflinePrizeLogic
* @package app\api\logic
*/
class UserOfflinePrizeLogic
{
/**
* desc查询最早的一条奖品数据
* authorwh
* @param $openid
*/
static function getFirstPrizeRecord($openid){
return Db::table(TabConf::$fa_user_offline_prize)
->where('openid',$openid)
->order('id asc')
->find();
}
/**
* desc用户上线时写入奖品(存在则num加1)
* authorwh
*/
static function insertPrize($openid,$gameprop_id,$num){
//
$prize = Db::table(TabConf::$fa_user_offline_prize)
->where('openid',$openid)
->where('gameprop_id',$gameprop_id)
->find();
if($prize){
Db::table(TabConf::$fa_user_offline_prize)
->where('id',$prize['id'])
->setInc('num',$num);
}else{
Db::table(TabConf::$fa_user_offline_prize)
->insert([
'openid'=>$openid,
'gameprop_id'=>$gameprop_id,
'num'=>$num
]);
}
}
/**
* desc领取后删除
* authorwh
* @param $openid
*/
static function deletedPrize($openid){
Db::table(TabConf::$fa_user_offline_prize)
->where('openid',$openid)
->delete();
}
}

View File

@@ -0,0 +1,19 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/5/23} {17:34}
*/
namespace app\api\logic;
use app\api\controller\BaseWssApi;
use GatewayWorker\Lib\Gateway;
use wanghua\general_utility_tools_php\tool\Tools;
class WssMessageLogic extends BaseLogic
{
}

View File

@@ -0,0 +1,12 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
return [];

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,63 @@
<?php
/*
* description
* authorwh
* email
* createTime{2023/12/5} {15:45}
*/
namespace app\common\behavior;
use app\api\logic\LoginLogic;
use wanghua\general_utility_tools_php\api\BaseUserLogic;
use wanghua\general_utility_tools_php\tool\Tools;
class LoginBehavior
{
//public function run(&$params)
//{
// // 行为逻辑
//}
public function actionBegin(){
return true;
//白名单
$white_arr = [
//【全小写】
'api/login/login',
'api/reg/reg',
'api/email/sendemail',
'api/email/check',
'api/users/forgot',
//public
'api/twitter/search',
];
$module = request()->module();
$controller = request()->controller();
$action = request()->action();
if($module != 'api'){
return false;
}
$url = strtolower($module.'/'.$controller.'/'.$action);
//dump($url);
if(in_array($url, $white_arr)){
//dump('不校验');
return true;//不校验
}
Tools::log_to_write_txt(['action log'=>input()]);
$r = session('api_user_info');
//dump($r);die;
if(empty($r)){
Tools::log_to_write_txt(['api_user_info'=>$r]);
echo json_encode(Tools::set_fail('登录失效'),JSON_UNESCAPED_UNICODE);die;
}
}
}

View File

@@ -0,0 +1,42 @@
<?php
/*
* description
* authorwh
* email
* createTime{2022/03/08} {14:17}
*/
namespace app\common\exception;
use think\exception\Handle;
use think\Request;
use wanghua\general_utility_tools_php\tool\Tools;
class SystemException extends Handle
{
public function render(\Exception $e)
{
// 参数验证错误
//if ($e instanceof ValidateException) {
// return json($e->getError(), 422);
//}
// 请求异常
//if ($e instanceof HttpException && request()->isAjax()) {
// return response($e->getMessage(), $e->getStatusCode());
//}
Tools::log_to_write_txt([
'error'=>'系统错误.'.$e->getMessage(),
'input'=>\think\facade\Request::input(),
'error_info'=>$e->getTraceAsString()
]);
//request()->LogObj->flush();
//可以在此交由系统处理
return parent::render($e);
}
}

View File

@@ -0,0 +1,31 @@
<?php
/*
* description
* authorwh
* email
* createTime{2021/6/21} {15:02}
*/
namespace app\common\model;
use think\Db;
use think\Model;
class BaseModel extends Model
{
protected static $log_file = '';//日志文件名
/**
* desc
* authorwh
* @param $self_table
* @return \think\db\Query
*/
protected static function tab($self_table){
return Db::table($self_table);
}
}

View File

@@ -0,0 +1,147 @@
<?php
namespace app\common\model;
class TabConf
{
/**
* 用户植物合成记录
*/
static $__fa_userplantconflaterecord = '__fa_userplantconflaterecord';
static $fa_usereliminate = 'fa_usereliminate';
/**
* 好友申请记录
*/
static $fa_friend_apply_record = 'fa_friend_apply_record';
/**
* 好友离线奖品领取记录
*/
static $fa_friend_offline_prize_got_record = 'fa_friend_offline_prize_got_record';
/**
* 游戏邮件
*/
static $fa_gameemail = 'fa_gameemail';
/**
* 游戏好友
*/
static $fa_gamefriend = 'fa_gamefriend';
/**
* 游戏关卡
*/
static $fa_gamelevel = 'fa_gamelevel';
/**
* 游戏系统道具表(上线后不允许删道具,会导致已领取的离线奖励不存在,给用户造成损失)
*/
static $fa_gameprop = 'fa_gameprop';
/**
* 游戏道具类型表
*/
static $fa_gameproptype = 'fa_gameproptype';
/**
* 登录记录
*/
static $fa_login_record = 'fa_login_record';
/**
* 游戏公告
*/
static $fa_notice = 'fa_notice';
/**
* 系统植物表
*/
static $fa_plant = 'fa_plant';
/**
* 兑换码(只能增加不能删数据)
*/
static $fa_redeem_code = 'fa_redeem_code';
/**
* 系统维护配置,支持模块、控制器、方法。全等匹配。
*/
static $fa_sys_maintain_config = 'fa_sys_maintain_config';
/**
* 用户邮件
*/
static $fa_user_email = 'fa_user_email';
/**
* 用户邮件阅读记录(存在数据表示已读)
*/
static $fa_user_email_read_record = 'fa_user_email_read_record';
/**
* 用户离线奖品表定时任务写入领取后删除用户也可以一直不领取最多也只有n小时以内的奖励
*/
static $fa_user_offline_prize = 'fa_user_offline_prize';
/**
* 用户离线奖品领取记录
*/
static $fa_user_offline_prize_got_record = 'fa_user_offline_prize_got_record';
/**
* 用户离线记录
*/
static $fa_user_offline_record = 'fa_user_offline_record';
/**
* 用户拥有的游戏道具表
*/
static $fa_usergameprop = 'fa_usergameprop';
/**
* 用户拥有的植物表
*/
static $fa_userplant = 'fa_userplant';
/**
* 用户植物合成记录
*/
static $fa_userplantconflaterecord = 'fa_userplantconflaterecord';
/**
* 用户表
*/
static $fa_users = 'fa_users';
/**
* 系统杂项配置
*/
static $fa_zc_sundry_config = 'fa_zc_sundry_config';
}

View File

@@ -0,0 +1,100 @@
<?php
/*
* description
* authorwh
* email
* createTime{2022/5/4} {9:12}
*/
namespace app\index\controller;
use app\apidata\Config;
use app\common\consts\LogDir;
use app\common\model\TabConf;
use app\index\model\WechatUserModel;
use think\Controller;
use think\Db;
use think\Request;
use wanghua\general_utility_tools_php\framework\base\OuterController;
use wanghua\general_utility_tools_php\tool\Tools;
class BaseAuthController extends BaseCommonController
{
public function __construct(Request $request = null)
{
parent::__construct($request);
//首页提示语
$this->assign('index_msg',cache('index_msg_alert_cache_time'));
//线上环境加载微信授权
if(config('sys_env') == 'PROD'){
$wx_user_info = session('wx_user_info');
if(empty($wx_user_info['openid'])) {
//重定向之前保存当前url, 在获取授权信息之后,回跳到授权之前的网页地址
session('redirect_before_url_session',request()->url(true));
//没有则重定向去授权
return $this->redirect(url('Wexinauth/usrAuth','',301,true));
}
$this->saveWechatUser($wx_user_info);
}
//校验系统维护状态 start
$chm = $this->checkMaintain();
if($chm['is_maintain']){
if($chm['openid']){
//解析openid
if(!in_array(index_user_openid(), explode(',',$chm['openid']))){
//白名单之外维护中
//Tools::log_to_write_txt([
// '维护测试'=>$chm['openid'],
// 'my'=>index_user_openid()
//]);
return $this->error($chm['msg']);
}
}else{
//不存在,直接维护中
return $this->error($chm['msg'].'');
}
}
//校验系统维护状态 end
}
/**
* desc
* authorwh
* @param $wx_user_info
*/
private function saveWechatUser($wx_user_info){
try {
$wechat_user = WechatUserModel::getWxUserByOpenid($wx_user_info['openid']);
if(empty($wechat_user)){
return WechatUserModel::insertInfo($wx_user_info);
}
//扩展,按周期更新,而不是不更新
if(empty($wechat_user['update_time']) || time()-strtotime($wechat_user['update_time'])>5*3600){
return WechatUserModel::updateUser($wx_user_info);
}
}catch (\Exception $e){
Tools::log_to_write_txt([
'error'=>'存储异常.'.$e->getMessage(),
'wx_user_info'=>$wx_user_info,
'error_info'=>$e->getTraceAsString()
],LogDir::WECHAT_USER_INFO_LOG);
}
}
}

View File

@@ -0,0 +1,73 @@
<?php
/*
* description
* authorwh
* email
* createTime{2023/1/21} {16:22}
*/
namespace app\index\controller;
use app\apidata\Config;
use app\common\model\TabConf;
use think\Controller;
use think\Db;
use think\Request;
use wanghua\general_utility_tools_php\framework\BaseController;
use wanghua\general_utility_tools_php\tool\Tools;
class BaseCommonController extends BaseController
{
function __construct(Request $request = null)
{
parent::__construct($request);
}
/**
* desc检查路径维护状态
*
* “===”完全匹配不能使用like
*
* authorwh
*/
protected function checkMaintain(){
$configs = Db::table(TabConf::$fa_sys_maintain_config)
->where('status','1')
->cache()
->select();
//模块
$strmodule = request()->module();
foreach ($configs as $config){
if($strmodule == $config['url']){
//模块维护中
return ['is_maintain'=>true,'msg'=>$config['msg'],'openid'=>$config['openid']];
}
}
//模块/控制器
$strcontroller = strtolower(request()->module().'/'.request()->controller());
foreach ($configs as $config){
if($strcontroller == $config['url']){
//模块维护中
return ['is_maintain'=>true,'msg'=>$config['msg'],'openid'=>$config['openid']];
}
}
//模块/控制器/方法
$straction = strtolower(request()->module().'/'.request()->controller().'/'.request()->action());
foreach ($configs as $config){
if($straction == $config['url']){
//模块维护中
return ['is_maintain'=>true,'msg'=>$config['msg'],'openid'=>$config['openid']];
}
}
//未维护
return ['is_maintain'=>false,'msg'=>'服务运行中'];
}
}

View File

@@ -0,0 +1,47 @@
<?php
/*
* description
* authorwh
* email
* createTime{2022/5/4} {9:39}
*/
namespace app\index\controller;
use think\Request;
use wanghua\general_utility_tools_php\framework\base\PublicController;
use wanghua\general_utility_tools_php\tool\Tools;
class BasePublicController extends BaseCommonController
{
public function __construct(Request $request = null)
{
parent::__construct($request);
//校验系统维护状态 start
$chm = $this->checkMaintain();
if($chm['is_maintain']){
if($chm['openid']){
//解析openid
if(!in_array(index_user_openid(), explode(',',$chm['openid']))){
//白名单之外维护中
//Tools::log_to_write_txt([
// '维护测试'=>$chm['openid'],
// 'my'=>index_user_openid()
//]);
return $this->error($chm['msg']);
}
}else{
//不存在,直接维护中
return $this->error($chm['msg'].'');
}
}
//校验系统维护状态 end
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace app\index\controller;
use GatewayWorker\Lib\Gateway;
use think\Db;
use wanghua\general_utility_tools_php\tool\Tools;
use Workerman\Worker;
class Index extends BasePublicController
{
function index()
{
}
}

View File

@@ -0,0 +1,63 @@
<?php
/*
* description
* authorwh
* email
* createTime{2023/11/19} {22:32}
*/
namespace app\index\controller;
use think\Controller;
use wanghua\general_utility_tools_php\tool\Tools;
use wanghua\general_utility_tools_php\wechat\TmpWexinauth;
use wanghua\general_utility_tools_php\wechat\UserAuth;
use wanghua\general_utility_tools_php\wechat\WechatLogic;
/**
*
*/
class Login extends Controller
{
function login()
{
$username = input('username');
$password = input('password');
return json(Tools::set_res(200,'ok',['username'=>$username]));
}
/**
* desc微信授权
* authorwh
*/
function wxauth()
{
try {
$code = input('code');
if(empty($code)){
return Tools::set_fail('CODE参数错误');
}
$wxconfig = get_boom_union_wechat_config();
$res = (new UserAuth($wxconfig,$wxconfig['access_token_path']))->usrAccessTokenApplet($code);
//绑定客户端ID和用户openid
return json(Tools::set_ok('ok',$res));
}catch (\Exception $e){
Tools::log_to_write_text([
'error'=>'微信授权异常。'.$e->getMessage(),
'input'=>input(),
'error_info'=>$e->getTraceAsString()
]);
return json(Tools::set_fail('请求异常'));
}
}
}

View File

@@ -0,0 +1,205 @@
<?php
/*
* description
* authorwh
* email
* createTime{2024/6/3} {15:56}
*/
namespace app\index\controller;
use app\common\model\TabConf;
use think\Db;
use think\Exception;
use wanghua\general_utility_tools_php\Mmodel;
use wanghua\general_utility_tools_php\SundryConfig;
use wanghua\general_utility_tools_php\tool\Tools;
/**
* 离线奖励计算任务
*
* Class Offlineprizetimer
* @package app\index\controller
*/
class Offlineprizetimer
{
/**
* desc定时计算任务每小时执行一次
* authorwh
*/
function count()
{
$this->countOfflinePrize();
$this->recoveryPower();
$this->recoveryPowerTimes();
}
/**
* desc计算离线奖励并写入离线奖励表
*
* 每1小时执行一次
*
* index/Offlineprizetimer/count
*
* authorwh
*/
private function countOfflinePrize(){
Tools::log_to_write_txt(['开始计算离线奖励']);
return Mmodel::catchJson(function (){
//一定时间内可领取的离线奖励次数
$time_inner_get_prize_times = SundryConfig::val('time_inner_get_prize_times');
$exp_arr = explode('-',$time_inner_get_prize_times);
$max_hours = $exp_arr[0];
$limit_time = time()-$max_hours * 3600;//n小时以内的离线用户
//$can_get_times = $exp_arr[1];//可领取次数
//所有离线时间大于 $max_hours 的用户
$all_users = Db::table(TabConf::$fa_users)
->where('offline_time','egt',date('Y-m-d H:i:s',$limit_time))//规定离线时间内
->where('clientid','')//已离线
->select();
//每离线N小时可获得奖励
$offline_n_hour_gift_can_prize = SundryConfig::val('offline_n_hour_gift_can_prize');
//计算奖励
foreach ($all_users as &$user){
if(empty($user['offline_time'])){
//刚注册,未离线
continue;
}
if($user['clientid']){
//在线
continue;
}
/** 下方是已离线用户↓ **/
//查询最近计算奖励的时间
$last_prize_time = Db::table(TabConf::$fa_user_offline_prize)
->where('openid',$user['openid'])
->order('id desc')
->find();
$offline_time = '';
if($last_prize_time){
//如果最近领取了奖励则以最近领取时间为准
$offline_time = $last_prize_time['create_time'];
}else{
//取离线时间
$offline_time = $user['offline_time'];
}
//离线时间超过3小时才能计算奖励
if(time() - strtotime($offline_time) < 3*3600 ){
//上次计算奖励的时间到现在还没到3小时
continue;
}
if(time()-$max_hours*3600 < strtotime($offline_time)){//在72小时以内
//减去领奖时间
$offline_time_hours = (time() - strtotime($offline_time)) / 3600;//得到小时数
$prize_num = floor($offline_time_hours / $offline_n_hour_gift_can_prize);//得到本次可领取的奖品数量
}else{//在72小时以外按72小时计算
$prize_num = floor($max_hours / $offline_n_hour_gift_can_prize);//得到本次可领取的奖品数量
}
if($prize_num<=0){
//离线时间不足,不计算奖励
continue;
}
//离线奖励获得数值
$offline_prize_got_num_value = SundryConfig::val('offline_prize_got_num_value');
//随机一个奖品
$prop_id = $this->random_prop('id');
//离线奖励可被偷取的百分比
$lose_percent = SundryConfig::val('offline_prize_can_lose_percent');
$prize_all_num = $prize_num * $offline_prize_got_num_value;
$can_lose_num = floor($prize_all_num * $lose_percent);
$self_got_num = $prize_all_num - $can_lose_num;
//计算奖品数值
$gameprop_arr = [
'openid'=>$user['openid'],
//奖品
'gameprop_id'=>$prop_id,
//奖品总数量
'prize_all_num'=>$prize_all_num,
//可被偷取的数量
'can_lose_num'=>$can_lose_num,//被偷取时,该值减少
//自己保底所得数量
'self_got_num'=>$self_got_num?:0,
];
Db::table(TabConf::$fa_user_offline_prize)
->insert($gameprop_arr);
}
Tools::log_to_write_txt(['结束计算离线奖励']);
return Tools::set_ok('ok');
});
}
private function random_prop($key=''){
$count = Db::table(TabConf::$fa_gameprop)
->count('id');
$id = mt_rand(1,$count);
$p = Db::table(TabConf::$fa_gameprop)->where('id',$id)->find();
if(empty($p)){
$id = mt_rand(1,$count);
$p = Db::table(TabConf::$fa_gameprop)->where('id',$id)->find();
}
if(empty($p)){
throw new Exception('道具获取失败');
}
return $key?$p[$key]:$p;
}
/**
* desc每小时恢复一点体力上限5点
* authorwh
*/
private function recoveryPower(){
return Mmodel::catchJson(function (){
$users = Db::table(TabConf::$fa_users)
->where('power','<',5)
->select();
foreach ($users as $user){
try {
Db::table(TabConf::$fa_users)
->where('id',$user['id'])
->setInc('power',1);
}catch (\Exception $e){
continue;
}
}
});
}
/**
* 每日凌晨恢复看广告增加体力次数和消耗金币增加体力次数
*/
private function recoveryPowerTimes(){
return Mmodel::catchJson(function (){
//判断当前时间是否是零点
$now_time = date('H');
if($now_time !== '00'){
return '';
}
$per_day_coin_add_power_times = SundryConfig::val('per_day_coin_add_power_times');
$per_day_look_ad_add_power_times = SundryConfig::val('per_day_look_ad_add_power_times');
$users = Db::table(TabConf::$fa_users)->select();
foreach ($users as $user){
try {
Db::table(TabConf::$fa_users)
->where('id',$user['id'])
->data([
'coin_power_times'=>$per_day_coin_add_power_times,
'ad_power_times'=>$per_day_look_ad_add_power_times,
]);
}catch (\Exception $e){
continue;
}
}
});
}
}

View File

@@ -0,0 +1,68 @@
<?php
/*
* description
* authorwh
* email
* createTime{2023/11/20} {10:28}
*/
namespace app\index\controller;
use app\api\controller\BaseCommonController;
use app\api\logic\UserLogic;
use think\Controller;
use think\Db;
use think\facade\Request;
use wanghua\general_utility_tools_php\api\ApiDocument;
use wanghua\general_utility_tools_php\http\Curl;
use wanghua\general_utility_tools_php\tool\Bank;
use wanghua\general_utility_tools_php\tool\Tools;
/**
*
*/
class Test extends BasePublicController
{
function test()
{
// 使用mt_rand()生成随机数
//$randomNumber = mt_rand(0, 2);
//
//echo $randomNumber;
(new UserLogic())->offline(input('client_id','asdsssssssssss'));
//$res = Db::table('fa_users')->find();
//dump($res);
//$res = Db::connect('mysql://cup_defense:z8PMXE3PGsy7WiFP@127.0.0.1:3306/cup_defense#utf8')->table('fa_users')->find();
//dump($res);
//$res = Curl::curl_get('https://qifu.baidu.com/ip/geo/v1/district?ip=183.227.88.8');
//dump($res);die;
//$res = (new Bank())->getBankSimpleInfoByBankNo('6217003760019611401');
//
//dump($res);
//dump(Request::host());
}
function testwss(){
return view();
}
function buildApiDoc()
{
parent::buildApiDoc();
}
public function buildTablesConf()
{
parent::buildTablesConf(); // TODO: Change the autogenerated stub
}
public function clearCache()
{
parent::clearCache(); // TODO: Change the autogenerated stub
}
}

View File

@@ -0,0 +1,223 @@
<?php
namespace app\index\logic\events;
use app\api\controller\BaseWssApi;
use app\api\logic\PartnerOfflineLogic;
use app\api\logic\UserLogic;
use app\api\logic\WssMessageLogic;
use app\index\logic\Baselogic;
use GatewayWorker\Lib\Gateway;
use think\Db;
use think\worker\Application;
use wanghua\general_utility_tools_php\http\Curl;
use wanghua\general_utility_tools_php\tool\Tools;
use Workerman\Worker;
/**
* 本事件监控逻辑
*
* 1、安装长连接框架composer require workerman/gateway-worker
* 2、配置基本参数
* 配置为文件为 config/gateway_worker.php必须使用对应命令才能启动
* 配置端口startPortpingDataeventHandler其它默认就好
* eventHandler配置为app\index\logic\events\Events.php类用于处理监听后的业务逻辑
* 3、启动服务
* 启动命令为php think worker:gateway
* 4、 nginx服务配置以支持/wss方式访问
* 参考配置:
* location /wss
{
proxy_pass http://127.0.0.1:2000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-Real-IP $remote_addr;
}
* 5、JavaScript客户端建立连接并访问
* ws = new WebSocket("wss://boomim.playone.cn/wss");//这种访问方式需要nginx配置
ws.onopen = function() {
alert("连接成功");
ws.send('hello,thinkphp');
alert("给服务端发送一个字符串hello,thinkphp");
};
*/
class Events extends \think\worker\Events
{
/**
* onWorkerStart 事件回调
* 当businessWorker进程启动时触发。每个进程生命周期内都只会触发一次
*
* @access public
* @param \Workerman\Worker $businessWorker
* @return void
*/
public static function onWorkerStart(Worker $businessWorker)
{
$app = new Application;
//config([
// 'database' => [
// // 数据库类型
// 'type' => 'mysql',
// // 服务器地址
// 'hostname' => '127.0.0.1',//,
// // 数据库名
// 'database' => 'cup_defense',
// // 数据库用户名
// 'username' => 'cup_defense',
// // 数据库密码
// 'password' => 'z8PMXE3PGsy7WiFP',
// // 数据库连接端口
// 'hostport' => 3306,
// // 数据库编码默认采用utf8
// 'charset' => 'utf8',
// // 连接dsn
// 'dsn' => '',
// // 数据库连接参数
// 'params' => [],
// // 数据库表前缀
// 'prefix' => '',
// ],
//]);
$app->initialize();
// 输出数据库配置
//Tools::log_to_write_txt(['onWorkerStart_database'=>config('database.')]);
//// 加载数据库配置
// 输出数据库配置
//Tools::log_to_write_txt(['onWorkerStart_database'=>config('database.')]);
// 初始化数据库连接
//Db::init();
//Db::connect();
// 在工作进程开始时,可以在这里执行一次数据库查询
//Db::table('fa_users')->find();
}
/**
* onConnect 事件回调
* 当客户端连接上gateway进程时(TCP三次握手完毕时)触发
*
* @access public
* @param int $client_id
* @return void
*/
public static function onConnect($client_id)
{
//一个连接只触发一次
Tools::log_to_write_txt(['客户端完成TCP握手'=>"[{$client_id}]"]);
$json = BaseWssApi::json_wss('onConnect','连接成功',['client_id'=>$client_id]);
Gateway::sendToCurrentClient($json);
}
/**
* onWebSocketConnect 事件回调
* 当客户端连接上gateway完成websocket握手时触发
*
* @param integer $client_id 断开连接的客户端client_id
* @param mixed $data {
"get":[
],
"server":{
"REQUEST_METHOD":"GET",
"REQUEST_URI":"/wss",
"SERVER_PROTOCOL":"HTTP/1.1",
"HTTP_UPGRADE":"websocket",
"HTTP_CONNECTION":"Upgrade",
"HTTP_X_REAL_IP":"183.227.89.107",
"HTTP_HOST":"127.0.0.1:2000",
"SERVER_NAME":"127.0.0.1",
"SERVER_PORT":"2000",
"HTTP_PRAGMA":"no-cache",
"HTTP_CACHE_CONTROL":"no-cache",
"HTTP_USER_AGENT":"wechatdevtools desktopapp appservice port/62717 token/589065e467011760c777411fca2cd0aa runtime/2 MicroMessenger",
"HTTP_ORIGIN":"https://boomim.playone.cn",
"HTTP_SEC_WEBSOCKET_VERSION":"13",
"HTTP_ACCEPT_ENCODING":"gzip, deflate, br",
"HTTP_ACCEPT_LANGUAGE":"zh-CN,zh;q=0.9",
"HTTP_CONTENT_TYPE":"application/json",
"HTTP_REFERER":"https://servicewechat.com/wx55e10fb2834803d5/devtools/page-frame.html",
"HTTP_SEC_WEBSOCKET_KEY":"uWOWC1AZahJOpS18hN3ZHA==",
"HTTP_SEC_WEBSOCKET_EXTENSIONS":"permessage-deflate; client_max_window_bits",
"QUERY_STRING":""
},
"cookie":[
]
}
* @return void
*/
public static function onWebSocketConnect($client_id, $data)
{
// var_export($data);
//对应客户端打开连接, 一个连接只触发一次
Tools::log_to_write_txt(['客户端打开了websocket连接',$client_id,$data]);
//$res = Tools::set_ok('ok',['client_id'=>$client_id,'msg'=>'客户端打开连接时,发送到服务端的消息:','data'=>$data]);
//
//Gateway::sendToCurrentClient(json_encode($res,JSON_UNESCAPED_UNICODE));
//$json = BaseWssApi::json_wss('openConnect','打开连接成功',['client_id'=>$client_id,'data'=>$data]);
//Gateway::sendToCurrentClient($json);
}
/**
* onMessage 事件回调
* 当客户端发来数据(Gateway进程收到数据)后触发
*
* 解析消息,根据action处理业务逻辑
*
* @access public
* @param int $client_id
* @param mixed $data
* @return void
*/
public static function onMessage($client_id, $data)
{
Tools::log_to_write_txt(['客户端发来数据(Gateway进程收到数据).client_id:'.$client_id,$data]);
//$res = Tools::set_ok('ok',['client_id'=>$client_id,'msg'=>'你发来的消息我接收到了:',$client_id=>$data]);
//Gateway::sendToClient($client_id,json_encode($res,JSON_UNESCAPED_UNICODE));
//解析消息
//解析action
//调用业务逻辑&响应处理结果
(new WssMessageLogic())->domsg($client_id,$data);
}
/**
* onClose 事件回调 当用户断开连接时触发的方法
*
* @param integer $client_id 断开连接的客户端client_id
* @return void
*/
public static function onClose($client_id)
{
//GateWay::sendToAll("client[$client_id] logout\n");
Tools::log_to_write_txt(['断开连接.client_id:'.$client_id]);
//$url = 'https://boomim.playone.cn/api/Partnermerchants/offline';
//Curl::curl_post($url,['clientid'=>$client_id]);
(new UserLogic())->offline($client_id);
}
/**
* onWorkerStop 事件回调
* 当businessWorker进程退出时触发。每个进程生命周期内都只会触发一次。
*
* @param \Workerman\Worker $businessWorker
* @return void
*/
public static function onWorkerStop(Worker $businessWorker)
{
//echo "WorkerStop\n";
Tools::log_to_write_txt(['businessWorker进程退出时触发。每个进程生命周期内都只会触发一次.',$businessWorker]);
//所有人离线,不需要修改所有用户离线状态,
//因为离线后再上线clint_id会重新生成
}
}

View File

@@ -0,0 +1,18 @@
<?php
/*
* description
* authorwh
* email
* createTime{2021/1/14} {14:37}
*/
namespace app\index\model;
use think\Db;
class BaseModel extends \app\common\model\BaseModel
{
}

View File

@@ -0,0 +1,320 @@
<?php
/*
* description
* authorwh
* email
* createTime{2022/01/18} {16:24}
*/
namespace app\index\model;
use app\apidata\Config;
use app\common\model\TabConf;
use think\Db;
class WechatUserModel extends \app\index\model\BaseModel
{
/**
* desc
* authorwh
* @param $wx_user_info \app\index\model\微信用户
*
* {
* "openid":"or9D2vs863Ky5Py2ovkAiu9XFLO4",
* "nickname":"起源果蔬副食大华",
* "sex":0,
* "language":"",
* "city":"",
* "province":"",
* "country":"",
* "headimgurl":"https://thirdwx.qlogo.cn/mmopen/vi_32/joiaA475nx3fJiaqx0ibdnWo4A7Q3uCgu2hsribI0ATLItORjuUgCSP8mCaBkqL61ibGojib4pQYX1djUhZpF5zoqpSg/132",
* "privilege":[]
* }
*/
static function insertInfo(array $wx_user_info)
{
if (isset($wx_user_info['privilege'])) {
$wx_user_info['privilege'] = json_encode($wx_user_info['privilege']);
}
$data = [
'nickname' => $wx_user_info['nickname'],
'country' => $wx_user_info['country'],
'province' => $wx_user_info['province'],
'city' => $wx_user_info['city'],
'headimage' => $wx_user_info['headimgurl'],
'language' => $wx_user_info['language'],
'openid' => $wx_user_info['openid'],
'unionid' => isset($wx_user_info['unionid']) ? $wx_user_info['unionid'] : '',
'privilege' => $wx_user_info['privilege'],
'sex' => $wx_user_info['sex'],
'arm_group' => '',
'score' => 0,//积分
'group_buy_earnings' => 0,//拼团收益
'water_drop_balance' => 0,//水滴
];
self::tab(TabConf::$fa_wechatuser)
->data($data)
->insert();
}
/**
* desc更新用户信息
*
* authorwh
* @throws \think\Exception
* @throws \think\exception\PDOException
*/
static function updateUser($wx_user_info)
{
$data = [
'nickname' => $wx_user_info['nickname'],
'headimage' => $wx_user_info['headimgurl'],
'unionid' => isset($wx_user_info['unionid']) ? $wx_user_info['unionid'] : '',
];
self::tab(TabConf::$fa_wechatuser)
->data($data)
->where('openid', index_user_openid())
->update();
}
/**
* desc
* authorwh
* @param string $unionid
* @return array|bool|\PDOStatement|string|\think\Model|null
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
static function getWxUserByUnionid(string $unionid)
{
return Db::table(TabConf::$fa_wechatuser)
->field('id')
->where('unionid', $unionid)
->find();
}
/**
* desc
* authorwh
* @param string $openid
* @return array|bool|\PDOStatement|string|\think\Model|null
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
static function getWxUserByOpenid(string $openid)
{
return Db::table(TabConf::$fa_wechatuser)
//->field('id')
->where('openid', $openid)
->find();
}
/**
* desc
* authorwh
* @param string $openid
* @return array|bool|\PDOStatement|string|\think\Model|null
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
static function getNicknameByOpenid(string $openid)
{
return Db::table(TabConf::$fa_wechatuser)
->where('openid', $openid)
->value('nickname');
}
/**
* desc增加店铺会员积分
*
* authorwh
*/
static function addShopMemberScore(string $openid, $shop_member_score)
{
Db::table(TabConf::$fa_wechatuser)
->where('openid', $openid)
->setInc('shop_member_score', $shop_member_score);
}
/**
* desc增加积分、积分变动记录
* authorwh
*/
static function addScore(string $openid, $order_real_amount)
{
$score = $order_real_amount * 100;
//用户
$user = Db::table(TabConf::$fa_wechatuser)
->where('openid', $openid)
->find();
//增加积分变动记录
Db::table(TabConf::$fa_score_change_record)
->data([
'nickname' => $user['nickname'],
'openid' => $user['openid'],
'score' => $score,
'score_before' => $user['score'],
'score_after' => $user['score'] + $score,
'from' => 'main_store_goods_buy_order',
])
->insert();
//增加积分
return self::tab(TabConf::$fa_wechatuser)
->where('openid', $openid)
->setInc('score', $score);//分为单位
}
/**
* desc减去积分 扣除积分、积分变动记录
* authorwh
*/
static function deductScore(string $openid, $order_real_amount, $remark = '')
{
$score = $order_real_amount * 100;
//用户
$user = Db::table(TabConf::$fa_wechatuser)
->where('openid', $openid)
->find();
//增加积分变动记录
Db::table(TabConf::$fa_score_change_record)
->data([
'nickname' => $user['nickname'],
'openid' => $user['openid'],
'score' => -$score,
'score_before' => $user['score'],
'score_after' => $user['score'] - $score,
'from' => 'system_deduct_score',//系统冲扣积分
'remark' => $remark,
])
->insert();
//增加积分
return self::tab(TabConf::$fa_wechatuser)
->where('openid', $openid)
->setDec('score', $score);//分为单位
}
/**
* desc积分冲补
*
* authorwh
* @param string $openid
* @param $order_real_amount
* @param string $remark
* @return bool|int|string|true
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
static function repairScore(string $openid, $order_real_amount, $remark = '')
{
$score = $order_real_amount * 100;
//用户
$user = Db::table(TabConf::$fa_wechatuser)
->where('openid', $openid)
->find();
//增加积分变动记录
Db::table(TabConf::$fa_score_change_record)
->data([
'nickname' => $user['nickname'],
'openid' => $user['openid'],
'score' => $score,
'score_before' => $user['score'],
'score_after' => $user['score'] + $score,
'from' => 'system_repair_score',//系统冲补积分
'remark' => $remark,
])
->insert();
//增加积分
return self::tab(TabConf::$fa_wechatuser)
->where('openid', $openid)
->setInc('score', $score);//分为单位
}
/**
* desc每笔订单成功之后增加水滴
*
* authorwh
* @param string $openid
* @param $order_real_amount
* @return bool|int|string|true
* @throws \think\Exception
*/
static function addWaterDropBalance(string $openid, $order_real_amount)
{
$water_drop_basic_num = (int)Config::sundryConfigVal('water_drop_basic_num');
$water = 0;
if ($order_real_amount < 1) {
$water = 1;//小于1积累1滴水滴
} else if ($order_real_amount >= 1 && $order_real_amount < 10) {
$water = 2;
} else if ($order_real_amount >= 10 && $order_real_amount < 50) {
$water = 3;
} else if ($order_real_amount >= 50 && $order_real_amount < 100) {
$water = 4;
} else if ($order_real_amount >= 100 && $order_real_amount < 500) {
$water = 5;
} else if ($order_real_amount >= 500 && $order_real_amount < 2000) {
$water = 6;
} else if ($order_real_amount >= 2000) {
$water = 7;
}
return self::tab(TabConf::$fa_wechatuser)
->where('openid', $openid)
->setInc('water_drop_balance', $water * $water_drop_basic_num);
}
/**
* desc实时获取用户身上的微信拼团收益
* authorwh
*/
static function getUserEarnings()
{
$val = self::tab(TabConf::$fa_wechatuser)
->where('openid', index_user_openid())
->value('group_buy_earnings');
return 1 * $val;
}
static function getUserTypeByOpenid(string $openid)
{
return self::tab(TabConf::$fa_wechatuser)
->where('openid', $openid)
->value('user_type');
}
/**
* desc实时获取用户身上的积分
* authorwh
*/
static function getUserScore()
{
return self::tab(TabConf::$fa_wechatuser)
->where('openid', index_user_openid())
->value('score');
}
/**
* desc实时获取用户身上的水滴
* authorwh
*/
static function getUserWater()
{
return self::tab(TabConf::$fa_wechatuser)
->where('openid', index_user_openid())
->value('water_drop_balance');
}
}

View File

@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="text" id="msg" value='{"action":"user/offline","method":"response","msg":"22222","items":[]}'> <button onclick="sendmsg()">发送消息</button>
</body>
<script>
let ws = new WebSocket("wss://cupdefense.playone.cn/wss");//这种访问方式需要nginx配置
ws.onopen = function() {
console.log("连接成功");
ws.send('hello,thinkphp');
console.log("给服务端发送一个字符串hello,thinkphp");
};
ws.onmessage = function(e){
// console.log(e);
//e.data 的数据格式也是字符串,手动解析这些数据才能得到其他格式的数据。
const _data = JSON.parse(e.data);
console.log(e.data,_data);
}
//当客户端收到服务端发送的关闭连接请求时触发onclose事件
ws.onclose = function(e){
console.log("close");
}
//如果出现连接、处理、接收、发送数据失败的时候触发onerror事件
ws.onerror = function(error){
console.log(error);
}
function sendmsg(){
let msg = document.getElementById("msg").value;
console.log('发送:'+msg);
ws.send(msg);
}
</script>
</html>

View File

@@ -0,0 +1,14 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 应用容器绑定定义
return [
];

View File

@@ -0,0 +1,45 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 动态绑定属性
//框架生命周期日志(只支持tp5.0)
//\think\facade\Request::instance()->bind('LogObj',new \wanghua\general_utility_tools_php\log\Driver('mysql'));
//业务日志对象
//\think\Request::instance()->bind('ServeLogObj',new \wanghua\general_utility_tools_php\log\Driver('file'));
// 注册 app\index\behavior\CheckLang行为类到app_init标签位
//\think\Hook::add('app_init', '\\wanghua\\general_utility_tools_php\\log\\example\\LoggerBehavior');
//注册 app\admin\behavior\CronRun行为类到app_init标签位
//\think\Hook::add('app_end', '\\wanghua\\general_utility_tools_php\\log\\example\\LoggerBehavior');
// 应用行为扩展定义文件
return [
// 应用初始化
'app_init' => [],
// 应用开始
'app_begin' => [],
// 模块初始化
'module_init' => [],
// 操作开始执行
'action_begin' => [
'app\\common\\behavior\\LoginBehavior',
],
// 视图内容过滤
'view_filter' => [],
// 日志写入
'log_write' => [],
// 应用结束
'app_end' => [],
];

View File

@@ -0,0 +1,26 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
return [
// 生成应用公共文件
'__file__' => ['common.php'],
// 定义demo模块的自动生成 (按照实际定义的文件名生成)
'demo' => [
'__file__' => ['common.php'],
'__dir__' => ['behavior', 'controller', 'model', 'view'],
'controller' => ['Index', 'Test', 'UserType'],
'model' => ['User', 'UserType'],
'view' => ['index/index'],
],
// 其他更多的模块定义
];

View File

@@ -0,0 +1,48 @@
{
"name": "topthink/think",
"description": "the new thinkphp framework",
"type": "project",
"keywords": [
"framework",
"thinkphp",
"ORM"
],
"homepage": "http://thinkphp.cn/",
"license": "Apache-2.0",
"authors": [
{
"name": "liu21st",
"email": "liu21st@gmail.com"
}
],
"require": {
"php": ">=7.4",
"topthink/framework": "5.1.*",
"topthink/think-worker": "^2.0",
"workerman/gateway-worker": "^3.0",
"wanghua/general-utility-tools-php": "dev-master",
"ext-json": "*",
"ext-mbstring": "*",
"doing/phpqrcode": "dev-master"
},
"autoload": {
"psr-4": {
"app\\": "application"
}
},
"extra": {
"think-path": "thinkphp"
},
"config": {
"preferred-install": "dist",
"allow-plugins": {
"topthink/think-installer": true
}
},
"repositories": {
"packagist": {
"type": "composer",
"url": "https://packagist.org"
}
}
}

404
digital_doctor_admin/composer.lock generated Normal file
View File

@@ -0,0 +1,404 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "8fe761fafeaf165fbc5ba11e2717293e",
"packages": [
{
"name": "doing/phpqrcode",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/Doing0/phpqrcode.git",
"reference": "600baab04cd4dfe2b307a321775ec5a66e330560"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Doing0/phpqrcode/zipball/600baab04cd4dfe2b307a321775ec5a66e330560",
"reference": "600baab04cd4dfe2b307a321775ec5a66e330560",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=5.3"
},
"default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
"PHPQRCode\\": "src/lib"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Doing",
"email": "vip.dulin@gmial.com"
}
],
"description": "基于phpqrcode修改的二维码生成工具:可自定义二维码颜色和头像",
"keywords": [
"phpqrcode",
"二维码"
],
"support": {
"issues": "https://github.com/Doing0/phpqrcode/issues",
"source": "https://github.com/Doing0/phpqrcode/tree/master"
},
"time": "2018-03-28T09:05:08+00:00"
},
{
"name": "topthink/framework",
"version": "v5.1.42",
"source": {
"type": "git",
"url": "https://github.com/top-think/framework.git",
"reference": "ecf1a90d397d821ce2df58f7d47e798c17eba3ad"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/framework/zipball/ecf1a90d397d821ce2df58f7d47e798c17eba3ad",
"reference": "ecf1a90d397d821ce2df58f7d47e798c17eba3ad",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=5.6.0",
"topthink/think-installer": "2.*"
},
"require-dev": {
"johnkary/phpunit-speedtrap": "^1.0",
"mikey179/vfsstream": "~1.6",
"phpdocumentor/reflection-docblock": "^2.0",
"phploc/phploc": "2.*",
"phpunit/phpunit": "^5.0|^6.0",
"sebastian/phpcpd": "2.*",
"squizlabs/php_codesniffer": "2.*"
},
"type": "think-framework",
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "liu21st",
"email": "liu21st@gmail.com"
},
{
"name": "yunwuxin",
"email": "448901948@qq.com"
}
],
"description": "the new thinkphp framework",
"homepage": "http://thinkphp.cn/",
"keywords": [
"framework",
"orm",
"thinkphp"
],
"support": {
"issues": "https://github.com/top-think/framework/issues",
"source": "https://github.com/top-think/framework/tree/v5.1.42"
},
"time": "2022-10-25T15:04:49+00:00"
},
{
"name": "topthink/think-installer",
"version": "v2.0.5",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-installer.git",
"reference": "38ba647706e35d6704b5d370c06f8a160b635f88"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-installer/zipball/38ba647706e35d6704b5d370c06f8a160b635f88",
"reference": "38ba647706e35d6704b5d370c06f8a160b635f88",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"composer-plugin-api": "^1.0||^2.0"
},
"require-dev": {
"composer/composer": "^1.0||^2.0"
},
"type": "composer-plugin",
"extra": {
"class": "think\\composer\\Plugin"
},
"autoload": {
"psr-4": {
"think\\composer\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "yunwuxin",
"email": "448901948@qq.com"
}
],
"support": {
"issues": "https://github.com/top-think/think-installer/issues",
"source": "https://github.com/top-think/think-installer/tree/v2.0.5"
},
"time": "2021-01-14T12:12:14+00:00"
},
{
"name": "topthink/think-worker",
"version": "v2.0.12",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-worker.git",
"reference": "922d8c95e2f095e0da66d18b9e3fbbfd8de70a3f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-worker/zipball/922d8c95e2f095e0da66d18b9e3fbbfd8de70a3f",
"reference": "922d8c95e2f095e0da66d18b9e3fbbfd8de70a3f",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"ext-fileinfo": "*",
"topthink/framework": "^5.1.18",
"topthink/think-installer": "^2.0",
"workerman/gateway-worker": "^3.0.0",
"workerman/workerman": "^3.5.0"
},
"type": "think-extend",
"extra": {
"think-config": {
"worker": "src/config/worker.php",
"worker_server": "src/config/server.php",
"gateway_worker": "src/config/gateway.php"
}
},
"autoload": {
"files": [
"src/command.php"
],
"psr-4": {
"think\\worker\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "liu21st",
"email": "liu21st@gmail.com"
}
],
"description": "workerman extend for thinkphp5.1",
"support": {
"issues": "https://github.com/top-think/think-worker/issues",
"source": "https://github.com/top-think/think-worker/tree/v2.0.12"
},
"time": "2019-03-08T11:22:34+00:00"
},
{
"name": "wanghua/general-utility-tools-php",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://gitee.com/drop_drop/general_utility_tools_php.git",
"reference": "b7f7ec6a9bf19b15e4940838d787e4c08e29f7a6"
},
"require": {
"ext-json": "*"
},
"default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
"wanghua\\general_utility_tools_php\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "wanghua",
"email": "wanghua@qq.com",
"homepage": "https://blog.csdn.net/qq_15941409"
}
],
"description": "general utility tools for thinkPHP",
"homepage": "https://gitee.com/drop_drop/general_utility_tools_php.git",
"keywords": [
"common tool",
"general-utility-tools",
"php tool"
],
"time": "2024-06-06T07:47:22+00:00"
},
{
"name": "workerman/gateway-worker",
"version": "v3.0.22",
"source": {
"type": "git",
"url": "https://github.com/walkor/GatewayWorker.git",
"reference": "a615036c482d11f68b693998575e804752ef9068"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/walkor/GatewayWorker/zipball/a615036c482d11f68b693998575e804752ef9068",
"reference": "a615036c482d11f68b693998575e804752ef9068",
"shasum": ""
},
"require": {
"workerman/workerman": ">=3.5.0"
},
"type": "library",
"autoload": {
"psr-4": {
"GatewayWorker\\": "./src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"homepage": "http://www.workerman.net",
"keywords": [
"communication",
"distributed"
],
"support": {
"issues": "https://github.com/walkor/GatewayWorker/issues",
"source": "https://github.com/walkor/GatewayWorker/tree/v3.0.22"
},
"funding": [
{
"url": "https://opencollective.com/walkor",
"type": "open_collective"
},
{
"url": "https://www.patreon.com/walkor",
"type": "patreon"
}
],
"time": "2021-12-23T13:13:09+00:00"
},
{
"name": "workerman/workerman",
"version": "v3.5.35",
"source": {
"type": "git",
"url": "https://github.com/walkor/workerman.git",
"reference": "3cc0adae51ba36db38b11e7996c64250d356dbe7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/walkor/workerman/zipball/3cc0adae51ba36db38b11e7996c64250d356dbe7",
"reference": "3cc0adae51ba36db38b11e7996c64250d356dbe7",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": "^5.3||^7.0"
},
"suggest": {
"ext-event": "For better performance. "
},
"type": "library",
"autoload": {
"psr-4": {
"Workerman\\": "./"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "walkor",
"email": "walkor@workerman.net",
"homepage": "http://www.workerman.net",
"role": "Developer"
}
],
"description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.",
"homepage": "http://www.workerman.net",
"keywords": [
"asynchronous",
"event-loop"
],
"support": {
"email": "walkor@workerman.net",
"forum": "http://wenda.workerman.net/",
"issues": "https://github.com/walkor/workerman/issues",
"source": "https://github.com/walkor/workerman",
"wiki": "http://doc.workerman.net/"
},
"funding": [
{
"url": "https://opencollective.com/workerman",
"type": "open_collective"
},
{
"url": "https://www.patreon.com/walkor",
"type": "patreon"
}
],
"time": "2023-09-13T14:30:13+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"wanghua/general-utility-tools-php": 20,
"doing/phpqrcode": 20
},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=7.4",
"ext-json": "*",
"ext-mbstring": "*"
},
"platform-dev": [],
"plugin-api-version": "2.6.0"
}

View File

@@ -0,0 +1,214 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
use \think\facade\Env;
use think\facade\Request;
// +----------------------------------------------------------------------
// | 应用设置
// +----------------------------------------------------------------------
//定位到项目根目录 E:\wh\projects\boom_im
$root_path = str_replace('config','',__DIR__);
list($debug,$trace,$sys_env) = [false,false,'DEV'];
if (!function_exists('is_main_domain')) {
function is_main_domain($domain, $main_domain)
{
$exp_arr = explode('.', $domain);
$str = $exp_arr[count($exp_arr) - 2] . '.' . $exp_arr[count($exp_arr) - 1];
return in_array($str, $main_domain);//$str == $main_domain;
}
}
if (!function_exists('auto_choose_app_conf')) {
function auto_choose_app_conf(&$debug,&$trace,&$sys_env){
$domain = Request::host(); //获取当前域名
if(in_array($domain, ['boomim.playone.cn'])){
//正式 - 全域名
$debug = true;
$trace = false;
$sys_env = 'PROD';
}
//测试
else if(in_array($domain, ['cupdefense.playone.cn','xxx.com'])) {
$debug = true;
$trace = false;
$sys_env = 'DEV';
}
else {
//本地
$debug = true;
$trace = false;
$sys_env = 'LOCAL';
}
}
}
auto_choose_app_conf($debug,$trace,$sys_env);
return [
// 应用名称
'app_name' => '',
// 应用地址
'app_host' => '47.108.163.84',
// 应用调试模式
'app_debug' => $debug,
// 应用Trace
'app_trace' => $trace,
// 是否支持多模块
'app_multi_module' => true,
// 入口自动绑定模块
'auto_bind_module' => false,
// 注册的根命名空间
'root_namespace' => [],
// 默认输出类型
'default_return_type' => 'html',
// 默认AJAX 数据返回格式,可选json xml ...
'default_ajax_return' => 'json',
// 默认JSONP格式返回的处理方法
'default_jsonp_handler' => 'jsonpReturn',
// 默认JSONP处理方法
'var_jsonp_handler' => 'callback',
// 默认时区
'default_timezone' => 'Asia/Shanghai',
// 是否开启多语言
'lang_switch_on' => false,
// 默认全局过滤方法 用逗号分隔多个
'default_filter' => '',
// 默认语言
'default_lang' => 'zh-cn',
// 应用类库后缀
'class_suffix' => false,
// 控制器类后缀
'controller_suffix' => false,
// +----------------------------------------------------------------------
// | 模块设置
// +----------------------------------------------------------------------
// 默认模块名
'default_module' => 'index',
// 禁止访问模块
'deny_module_list' => ['common'],
// 默认控制器名
'default_controller' => 'Index',
// 默认操作名
'default_action' => 'index',
// 默认验证器
'default_validate' => '',
// 默认的空模块名
'empty_module' => '',
// 默认的空控制器名
'empty_controller' => 'Error',
// 操作方法前缀
'use_action_prefix' => false,
// 操作方法后缀
'action_suffix' => '',
// 自动搜索控制器
'controller_auto_search' => false,
// +----------------------------------------------------------------------
// | URL设置
// +----------------------------------------------------------------------
// PATHINFO变量名 用于兼容模式
'var_pathinfo' => 's',
// 兼容PATH_INFO获取
'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
// pathinfo分隔符
'pathinfo_depr' => '/',
// HTTPS代理标识
'https_agent_name' => '',
// IP代理获取标识
'http_agent_ip' => 'X-REAL-IP',
// URL伪静态后缀
'url_html_suffix' => 'html',
// URL普通方式参数 用于自动生成
'url_common_param' => false,
// URL参数方式 0 按名称成对解析 1 按顺序解析
'url_param_type' => 0,
// 是否开启路由延迟解析
'url_lazy_route' => false,
// 是否强制使用路由
'url_route_must' => false,
// 合并路由规则
'route_rule_merge' => false,
// 路由是否完全匹配
'route_complete_match' => false,
// 使用注解路由
'route_annotation' => false,
// 域名根如thinkphp.cn
'url_domain_root' => '',
// 是否自动转换URL中的控制器和操作名
'url_convert' => true,
// 默认的访问控制器层
'url_controller_layer' => 'controller',
// 表单请求类型伪装变量
'var_method' => '_method',
// 表单ajax伪装变量
'var_ajax' => '_ajax',
// 表单pjax伪装变量
'var_pjax' => '_pjax',
// 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
'request_cache' => false,
// 请求缓存有效期
'request_cache_expire' => null,
// 全局请求缓存排除规则
'request_cache_except' => [],
// 是否开启路由缓存
'route_check_cache' => false,
// 路由缓存的Key自定义设置闭包默认为当前URL和请求类型的md5
'route_check_cache_key' => '',
// 路由缓存类型及参数
'route_cache_option' => [],
// 默认跳转页面对应的模板文件
'dispatch_success_tmpl' => Env::get('think_path') . 'tpl/dispatch_jump.tpl',
'dispatch_error_tmpl' => Env::get('think_path') . 'tpl/dispatch_jump.tpl',
// 异常页面的模板文件
'exception_tmpl' => Env::get('think_path') . 'tpl/think_exception.tpl',
// 错误显示信息,非调试模式有效
'error_message' => '页面错误!请稍后再试~',
// 显示错误信息
'show_error_msg' => false,
// 异常处理handle类 留空使用 \think\exception\Handle
'exception_handle' => '\\app\\common\\exception\\SystemException',
'pay_config'=>[
'wechat' => [
//小白菜商城
],
],
//业务基础架构配置
'service_framework_config'=>[
//内网访问架构中放行的端口
'inner_allow_ports'=>[8080],
//错误重定向URL
'auth_err_redirect_url'=>'/index/err/checkfailed',
'sign_token'=>'ASbn56&1^%_qsdcvb',
//业务架构调试模式 false 关闭, true开启
'debug'=>false,
],
//抖音应用配置
'douyin_config_mini_game'=>[
'appid'=>'tte7c6917b78f05c0c02',
'secret'=>'c68998a9f37774258aa071556088f55e4bd6956f',
],
//当前系统环境类型
'sys_env'=>$sys_env,
//系统日志驱动
'sys_log_type'=>'file',//file mysql email
];

View File

@@ -0,0 +1,25 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | 缓存设置
// +----------------------------------------------------------------------
return [
// 驱动方式
'type' => 'File',
// 缓存保存目录
'path' => '',
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 0,
];

View File

@@ -0,0 +1,20 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | 控制台配置
// +----------------------------------------------------------------------
return [
'name' => 'Think Console',
'version' => '0.1',
'user' => null,
'auto_path' => env('app_path') . 'command' . DIRECTORY_SEPARATOR,
];

View File

@@ -0,0 +1,30 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | Cookie设置
// +----------------------------------------------------------------------
return [
// cookie 名称前缀
'prefix' => '',
// cookie 保存时间
'expire' => 0,
// cookie 保存路径
'path' => '/',
// cookie 有效域名
'domain' => '',
// cookie 启用安全传输
'secure' => false,
// httponly设置
'httponly' => '',
// 是否使用 setcookie
'setcookie' => true,
];

View File

@@ -0,0 +1,110 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
use \think\facade\Env;
use think\facade\Request;
list($hostname,$database,$username,$password,$hostport) = ['','','','',''];
if (!function_exists('is_main_domain')) {
function is_main_domain($domain, $main_domain)
{
$exp_arr = explode('.', $domain);
$str = $exp_arr[count($exp_arr) - 2] . '.' . $exp_arr[count($exp_arr) - 1];
return in_array($str, $main_domain);//$str == $main_domain;
}
}
if (!function_exists('auto_choose_db_conf')) {
function auto_choose_db_conf(&$hostname,&$database,&$username,&$password,&$hostport){
$domain = Request::host(); //获取当前域名
//正式
if(in_array($domain, [
'sdsdsd.playone.cn'
])){
$hostname = 'localhost';
$database = 'cup_defense';
$username = 'cup_defense';
$password = 'cup_defense';
$hostport = '3306';
}
//测试 socket请求这里$domain=null【上线正式环境之后把null移动到正式环境配置】
else if(in_array($domain, [null,'cupdefense.playone.cn','testzckj.zcc10.com'])) {
$hostname = 'localhost';
$database = 'cup_defense';
$username = 'cup_defense';
$password = 'z8PMXE3PGsy7WiFP';
$hostport = '3306';
}
//本地
else{
$hostname = '127.0.0.1';
$database = 'cup_defense';
$username = 'root';
$password = 'root';//root or 123456
$hostport = '3306';
}
}
}
auto_choose_db_conf($hostname,$database,$username,$password,$hostport);
return [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => $hostname,
// 数据库名
'database' => $database,
// 用户名
'username' => $username,//正式:root,测试zc_game_admin本地root
// 密码.
'password' => $password,//正式:hbDB8SRa3Ix3poVi,测试KZK4cGd4XYsbNG5w本地root
// 端口
'hostport' => $hostport,
// 连接dsn
'dsn' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => '',
// 数据库调试模式
'debug' => true,
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 自动读取主库数据
'read_master' => false,
// 是否严格检查字段是否存在
'fields_strict' => true,
// 数据集返回类型
'resultset_type' => 'array',
// 自动写入时间戳字段
'auto_timestamp' => false,
// 时间字段取出后的默认时间格式
'datetime_format' => 'Y-m-d H:i:s',
// 是否需要进行SQL性能分析
'sql_explain' => false,
// Builder类
'builder' => '',
// Query类
'query' => '\\think\\db\\Query',
// 是否需要断线重连
'break_reconnect' => true,
// 断线标识字符串
'break_match_str' => [],
];

View File

@@ -0,0 +1,52 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | Workerman设置 仅对 php think worker:gateway 指令有效
// +----------------------------------------------------------------------
return [
/**
* https://blog.csdn.net/qq_15941409/article/details/135760559?spm=1001.2014.3001.5502
* 【长连接使用此配置,启动命令: php think worker:gateway 】
*/
// 扩展自身需要的配置
'protocol' => 'websocket', // 协议 支持 tcp udp unix http websocket text
'host' => '0.0.0.0', // 监听地址
'port' => 3000, // 监听端口
'socket' => '', // 完整监听地址
'context' => [], // socket 上下文选项
'register_deploy' => true, // 是否需要部署register
'businessWorker_deploy' => true, // 是否需要部署businessWorker
'gateway_deploy' => true, // 是否需要部署gateway
// Register配置
'registerAddress' => '127.0.0.1:1256',
// Gateway配置
'name' => 'thinkphp',
'count' => 1,
'lanIp' => '127.0.0.1',
'startPort' => 1370,
'daemonize' => false,
'pingInterval' => 30,
'pingNotResponseLimit' => 0,
'pingData' => '{"action":"ping"}',
// BusinsessWorker配置
'businessWorker' => [
'name' => 'BusinessWorker',
'count' => 1,
// 'eventHandler' => '\think\worker\Events',
'eventHandler' => 'app\index\logic\events\Events',
],
];

View File

@@ -0,0 +1,30 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | 日志设置
// +----------------------------------------------------------------------
return [
// 日志记录方式,内置 file socket 支持扩展
'type' => 'File',
// 日志保存目录
'path' => '',
// 日志记录级别
'level' => [],
// 单文件日志写入
'single' => false,
// 独立日志级别
'apart_level' => [],
// 最大日志文件数量
'max_files' => 0,
// 是否关闭日志写入
'close' => false,
];

View File

@@ -0,0 +1,18 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | 中间件配置
// +----------------------------------------------------------------------
return [
// 默认中间件命名空间
'default_namespace' => 'app\\http\\middleware\\',
];

View File

@@ -0,0 +1,26 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | 会话设置
// +----------------------------------------------------------------------
return [
'id' => '',
// SESSION_ID的提交变量,解决flash上传跨域
'var_session_id' => '',
// SESSION 前缀
'prefix' => 'think',
// 驱动方式 支持redis memcache memcached
'type' => '',
// 是否自动开启 SESSION
'auto_start' => true,
];

View File

@@ -0,0 +1,35 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | 模板设置
// +----------------------------------------------------------------------
return [
// 模板引擎类型 支持 php think 支持扩展
'type' => 'Think',
// 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 3 保持操作方法
'auto_rule' => 1,
// 模板路径
'view_path' => '',
// 模板后缀
'view_suffix' => 'html',
// 模板文件名分隔符
'view_depr' => DIRECTORY_SEPARATOR,
// 模板引擎普通标签开始标记
'tpl_begin' => '{',
// 模板引擎普通标签结束标记
'tpl_end' => '}',
// 标签库标签开始标记
'taglib_begin' => '{',
// 标签库标签结束标记
'taglib_end' => '}',
];

View File

@@ -0,0 +1,18 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | Trace设置 开启 app_trace 后 有效
// +----------------------------------------------------------------------
return [
// 内置Html Console 支持扩展
'type' => 'Html',
];

View File

@@ -0,0 +1,34 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
use think\facade\Env;
// +----------------------------------------------------------------------
// | Workerman设置 仅对 php think worker 指令有效
// +----------------------------------------------------------------------
$app_path = explode('config',__FILE__)[0];
//dump($app_path);die;
return [
/** 【php think worker 命令默认启动的此文件 】 */
// 扩展自身需要的配置
'host' => '0.0.0.0', // 监听地址
'port' => 2006, // 监听端口
'root' => Env::get('root_path') . 'public', // WEB 根目录 默认会定位public目录
'app_path' => $app_path.'application', // 应用目录 守护进程模式必须设置(绝对路径)
'file_monitor' => false, // 是否开启PHP文件更改监控调试模式下自动开启
'file_monitor_interval' => 2, // 文件监控检测时间间隔(秒)
'file_monitor_path' => [], // 文件监控目录 默认监控application和config目录
// 支持workerman的所有配置参数
'name' => 'thinkphp',
'count' => 4,
'daemonize' => false,
'pidFile' => Env::get('runtime_path') . 'worker.pid',
];

View File

@@ -0,0 +1,85 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
use think\facade\Env;
// +----------------------------------------------------------------------
// | Workerman设置 仅对 php think worker:server 指令有效
// +----------------------------------------------------------------------
return [
/**
* 2024-1-21日测试通过可以发信息
* php think worker:server
* 【php think worker:server start命令对应的是此文件】
*/
// 扩展自身需要的配置
'protocol' => 'websocket', // 协议 支持 tcp udp unix http websocket text
'host' => '0.0.0.0', // 监听地址
'port' => 2001, // 监听端口
'socket' => '', // 完整监听地址
'context' => [], // socket 上下文选项
'worker_class' => '', // 自定义Workerman服务类名 支持数组定义多个服务
// 支持workerman的所有配置参数
'name' => 'thinkphp',
'count' => 4,
'daemonize' => false,
'pidFile' => Env::get('runtime_path') . 'worker.pid',
// 支持事件回调
// onWorkerStart
'onWorkerStart' => function ($worker) {
\wanghua\general_utility_tools_php\tool\Tools::log_to_write_txt([
'onWorkerStart'=>$worker
]);
},
// onWorkerReload
'onWorkerReload' => function ($worker) {
\wanghua\general_utility_tools_php\tool\Tools::log_to_write_txt([
'onWorkerReload'=>$worker
]);
},
// onConnect
'onConnect' => function ($connection) {
\wanghua\general_utility_tools_php\tool\Tools::log_to_write_txt([
'onConnect'=>'onConnect'
]);
$connection->send(json_encode(['msg_type'=>'onConnect']));
//$connection->send(json_encode(['test'=>'test','conn'=>$connection],JSON_UNESCAPED_UNICODE));
},
// onMessage
'onMessage' => function ($connection, $data) {
\wanghua\general_utility_tools_php\tool\Tools::log_to_write_txt([
'onMessage'=>$data
]);
$connection->send(json_encode(['msg_type'=>'onMessage']));
//$connection->send($connection.' === receive ,,,success');
},
// onClose
'onClose' => function ($connection) {
\wanghua\general_utility_tools_php\tool\Tools::log_to_write_txt([
'onClose'=>'onClose'
]);
$connection->send(json_encode(['msg_type'=>'onClose']));
},
// onError
'onError' => function ($connection, $code, $msg) {
\wanghua\general_utility_tools_php\tool\Tools::log_to_write_txt([
'onError'=>[$code=>$msg]
]);
$connection->send(json_encode(['msg_type'=>'onError']));
//echo "error [ $code ] $msg\n";
},
];

View File

@@ -0,0 +1,2 @@
*
!.gitignore

View File

@@ -0,0 +1,8 @@
<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L]
</IfModule>

View File

@@ -0,0 +1,26 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>404</title>
<style>
body{
background-color:#444;
font-size:14px;
}
h3{
font-size:60px;
color:#eee;
text-align:center;
padding-top:30px;
font-weight:normal;
}
</style>
</head>
<body>
<h3>404您请求的文件不存在!</h3>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,526 @@
# API 文档
## 接口列表
###### ctrl+f 搜索)(如果更改了路由,请根据路由规则定位)
##### 请求域名http://127.0.0.1:8080/
##### 请求方式POST默认
***
```
/**
* desc
*
* api/Douyin/getaccesstoken
*
* authorwh
* api/douyin/getaccesstoken
*/
```
***
```
/**
* desctt.login触发调用
* 参数code或anonymous_code
*
* api/Douyin/jscode2session
*
* "{\"anonymous_openid\":\"\",\"error\":0,\"openid\":\"_0007vGUSinv-twIOjY9MzYvzlj6U_xHa3Or\",\"session_key\":\"495rArUkMUXa4JoeT7wEVg==\",\"unionid\":\"7e1b9701-a346-5b44-9925-0acc40873cff\"}
*
* authorwh
* api/douyin/jscode2session
*/
```
***
```
/**
* desc创建二维码
* 接口说明
* 获取小程序/小游戏的二维码。该二维码可通过任意 app 扫码打开,
* 能跳转到开发者指定的对应字节系 app 内拉起小程序/小游戏,并传入开发者指定的参数。
* 通过该接口生成的二维码,永久有效,暂无数量限制。
*
* ⚠ Tip在使用该功能之前请记得先配置您的默认分享文案和图片配置方式可参考论坛。
* ⚠ Tip小程序的 path 要 encode 一次,如 pages%3fparam%3dtrue小游戏的 path 为 JSON 字符串,
* 如{"param":true},否则会导致取不到。
*
* 参数:
* code和anonymous_code二选一 必须
* appname 可选,目标打开应用名称 默认douyin
* background 可选背景色rgb格式英文逗号隔开默认透明色
* path 可选,小程序/小游戏启动参数,小程序则格式为 encode({path}?{query}),小游戏则格式为 JSON 字符串,默认为空
* width 宽度 可选,二维码宽度,单位 px最小 280px最大 1280px默认为 430px
* line_color 可选二维码线条颜色默认为黑色rgb格式英文逗号隔开默认黑色
* set_icon 可选,是否展示小程序/小游戏 icon默认不展示传yes展示no不展示默认no
*
* api/douyin/createQRCode
* 参数openid
*
* authorwh
* api/douyin/createQRCode
*/
```
***
```
/**
* desc累加击杀敌人数量
*
* api/enemy/addKillEnemyNum
*
* 参数enemy_num
*
* authorwh
* api/enemy/addKillEnemyNum
*/
```
***
```
/**
* desc查询推荐好友
*
* api/friends/getPutFriends
*
* 要求:不是自己和自己的好友
* authorwh
* api/friends/getPutFriends
*/
```
***
```
/**
* desc游戏邮件列表
* api/gameemail/getlists
*
* is_read 阅读状态
* is_deleted 删除标记
* api/gameemail/getlists
*/
```
***
```
/**
* 设置邮件为已读
* api/gameemail/read
* 参数:
* email_id 邮件id
* api/gameemail/read
*/
```
***
```
/**
* 删除所有已读邮件
* api/gameemail/delete
* 参数:
* api/gameemail/delete
*/
```
***
```
/**
* desc游戏道具已解锁、未解锁接口
* api/gameprop/getprop
* 参数:
*
* 返回:
* have_arr 已解锁
* no_arr 未解锁
*
* authorwh
* api/gameprop/getprop
*/
```
***
```
/**
* desc获取游戏道具列表肥料等各种道具
*
* api/gameprop/getGamePropList
*
* authorwh
* api/gameprop/getGamePropList
*/
```
***
```
/**
* desc游戏公告
* api/notice/getnotice
*
* authorwh
* @return \think\response\Json
* api/notice/getnotice
*/
```
***
```
/**
* desc查询系统植物列表
* api/plant/getlist
* authorwh
* api/plant/getlist
*/
```
***
```
/**
* desc查询排行榜
* /api/rankinglist/getrankinglist
* authorwh
* api/rankinglist/getrankinglist
*/
```
***
```
/**
* desc新增一个兑换码
* 参数: num (默认1)
* authorwh
* api/redeemcode/add
*/
```
***
```
/**
* 查询一个没使用的兑换码
* api/redeemcode/getOne
*/
```
***
```
/**
* 兑换码使用
*
* 参数code
*
* 返回用户获得的道具列表(可能获得多个道具,根据系统配置定)
* api/redeemcode/use
*/
```
***
```
/**
* 查询当前登陆人收到的邮件(好友触发了某个操作,同时向你发送了消息,并非真实邮件)
* 默认查询未读消息
* 参数:无
* api/useremail/getMyEmailMessage
*/
```
***
```
/**
* 用户邮件-设置已读
* 参数dataid 邮件的数据id
* api/useremail/read
*/
```
***
```
/**
* 用户获得游戏道具接口
* api /api/usergameprop/gainGameProp
*
* @param string $openid 用户openid
* @param int $gameprop_id 道具id
* @param int $num 道具数量
*
* api/usergameprop/gainGameProp
*/
```
***
```
/**
* 查询用户获得的游戏道具列表接口
* api/usergameprop/listUserGameProps
*
* api/usergameprop/listUserGameProps
*/
```
***
```
/**
* desc用户消耗游戏道具
*
* api/usergameprop/cutGameProp
* 参数:
* usergameprop_id 用户的游戏道具id
* num 消耗数量默认1
*
* authorwh
* api/usergameprop/cutGameProp
*/
```
***
```
/**
* desc查询用户拥有的植物列表
*
* api/userplant/listUserPlants
*
* authorwh
* api/userplant/listUserPlants
*/
```
***
```
/**
* desc植物合成
* api/userplant/plantConflate
*
*
* descoperate_type=add时新增植物
* plant_sit 新增植物位置
* sys_plant_id 新增植物id系统植物
*
*
* descoperate_type=drag时拖拽
* old_user_plant_data_id 原用户植物数据id
* new_plant_sit 新植物位置
*
*
* descoperate_type=conflate时合成植物
* target_plant_sit 目标植物位置
* target_sys_plant_id 目标系统植物id
* old_user_plant_data_id 旧用户植物数据id
* new_sys_plant_data_id 新植物数据id
*
*
* desc击杀植物
* operate_type=killPlant
* user_plant_data_id 用户植物数据id
* api/userplant/plantConflate
*/
```
***
```
/**
* desc根据游戏id查询用户
* api/Users/getUserById
* 参数:
* gameid 用户id
* authorwh
* api/users/getUserById
*/
```
***
```
/**
* desc根据openid查询用户
* api/Users/getUserInfo
* 参数:
* openid
*
* 返回:
* now_rank 当前排名
* all_coins: 累计获得金币
* enemy 累计击杀数
* api/users/getUserInfo
*/
```
***
```
/**
* desc微信授权登录
*
* /api/users/login
*
* 参数:code
*
* authorwh
* api/users/login
*/
```
***
```
/**
* desc修改用户昵称、头像
*
* /api/users/updateuser
*
* 参数:
* openid 必传
* nicknameheadimage
* api/users/updateuser
*/
```
***
```
/**
* desc更新最新关卡
* api/users/updatenowlevel
*
* 参数:
* now_level 最新关卡
* authorwh
* api/users/updateNowLevel
*/
```
***
```
/**
* desc查询好友列表-计算离线奖励
* /api/users/getFriendsOfflinePrizeList
*
* 离线奖励:从用户下线时刻开始每3个小时奖励一瓶随机等级的肥料只取整数不四舍五入。离线时长除以3取整数。
* 比如:离线 0-2.9 个小时 不奖励
离线 3-5.9 个小时 奖励 1瓶
离线 6-8.9 个小时 奖励 2瓶
*
gameprop_id 道具奖品
prize_all_num 总奖励数量
self_got_num 自己保底所得数量(固定)
can_lose_num 可被偷取的数量(固定)
now_can_lose_num 已偷取(偷取后数值增加,数值大于可被偷取的总数量时,拒绝偷取)
* authorwh
* api/users/getFriendsOfflinePrizeList
*/
```
***
```
/**
* desc偷取领取好友离线奖励领取多少根据后台配置领取比例而定偷取后发邮件给用户
*
* api/users/offlineprizegot
* 参数:
* friend_openid 好友
*
* authorwh
* api/users/offlinePrizeGot
*/
```
***
```
/**
* 查询自己的离线奖励
*
* 离线奖励:从用户下线时刻开始每3个小时奖励一瓶随机等级的肥料只取整数不四舍五入。离线时长除以3取整数。
* 比如:离线 0-2.9 个小时 不奖励
离线 3-5.9 个小时 奖励 1瓶
离线 6-8.9 个小时 奖励 2瓶
*
* api/users/getselfofflineprize
* api/users/getSelfOfflinePrize
*/
```
***
```
/**
* desc领取自己的离线奖励一次性领取所有离线奖励不能分批次领取没有部分领取一说
* api/users/receiveSelfOfflinePrize
* 参数:
* is_double 是否双倍奖励 1 一倍2 二倍
* authorwh
* api/users/receiveSelfOfflinePrize
*/
```
***
```
/**
* desc查询我的好友列表
*
* api/users/getMyFriends
*
* authorwh
* api/users/getMyFriends
*/
```
***
```
/**
* desc添加好友
*
* api/users/addFriend
* 参数:
* friend_openid 好友openid
* 注意:如果好友在线,会向好友发送申请消息
* authorwh
* api/users/addFriend
*/
```
***
```
/**
* desc查询我的好友申请列表
*
* api/users/getFriendApplyList
* authorwh
* api/users/getFriendApplyList
*/
```
***
```
/**
* 同意好友申请
* api/users/agreeFriendApply
* 参数:
* friend_openid 好友openid
* api/users/agreeFriendApply
*/
```
***
```
/**
* 拒绝好友申请
*
* api/users/refuseFriendApply
* 参数:
* friend_openid 好友openid
* api/users/refuseFriendApply
*/
```
***
```
/**
* desc增加金币,直接存用户信息里
* authorwh
* 参数:
* coins 金币数量
* api/users/addCoins
*/
```
***
```
/**
* desc消耗金币
* authorwh
* 参数:
* coins 金币数量
* api/users/cutCoins
*/
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -0,0 +1,39 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>恭喜,站点创建成功!</title>
<style>
.container {
width: 60%;
margin: 10% auto 0;
background-color: #f0f0f0;
padding: 2% 5%;
border-radius: 10px
}
ul {
padding-left: 20px;
}
ul li {
line-height: 2.3
}
a {
color: #20a53a
}
</style>
</head>
<body>
<div class="container">
<h1>恭喜, 站点创建成功!</h1>
<h3>这是默认index.html本页面由系统自动生成</h3>
<ul>
<li>本页面在FTP根目录下的index.html</li>
<li>您可以修改、删除或覆盖本页面</li>
<li>FTP相关信息请到“面板系统后台 > FTP” 查看</li>
</ul>
</div>
</body>
</html>

View File

@@ -0,0 +1,22 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// [ 应用入口文件 ]
namespace think;
// 加载基础文件
require __DIR__ . '/../thinkphp/base.php';
// 支持事先使用静态方法设置Request对象和Config对象
// 执行应用并响应
Container::get('app')->run()->send();

View File

@@ -0,0 +1,2 @@
User-agent: *
Disallow:

View File

@@ -0,0 +1,17 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// $Id$
if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"])) {
return false;
} else {
require __DIR__ . "/index.php";
}

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,20 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
Route::get('think', function () {
return 'hello,ThinkPHP5!';
});
Route::get('hello/:name', 'index/hello');
return [
];

View File

@@ -0,0 +1,2 @@
*
!.gitignore

View File

@@ -0,0 +1,22 @@
#!/usr/bin/env php
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think;
// 加载基础文件
require __DIR__ . '/thinkphp/base.php';
// 应用初始化
Container::get('app')->path(__DIR__ . '/application/')->initialize();
// 控制台初始化
Console::init();

View File

@@ -0,0 +1,8 @@
/vendor
composer.phar
composer.lock
.DS_Store
Thumbs.db
/phpunit.xml
/.idea
/.vscode

View File

@@ -0,0 +1 @@
deny from all

View File

@@ -0,0 +1,119 @@
如何贡献我的源代码
===
此文档介绍了 ThinkPHP 团队的组成以及运转机制,您提交的代码将给 ThinkPHP 项目带来什么好处,以及如何才能加入我们的行列。
## 通过 Github 贡献代码
ThinkPHP 目前使用 Git 来控制程序版本,如果你想为 ThinkPHP 贡献源代码,请先大致了解 Git 的使用方法。我们目前把项目托管在 GitHub 上,任何 GitHub 用户都可以向我们贡献代码。
参与的方式很简单,`fork`一份 ThinkPHP 的代码到你的仓库中,修改后提交,并向我们发起`pull request`申请,我们会及时对代码进行审查并处理你的申请并。审查通过后,你的代码将被`merge`进我们的仓库中,这样你就会自动出现在贡献者名单里了,非常方便。
我们希望你贡献的代码符合:
* ThinkPHP 的编码规范
* 适当的注释,能让其他人读懂
* 遵循 Apache2 开源协议
**如果想要了解更多细节或有任何疑问,请继续阅读下面的内容**
### 注意事项
* 本项目代码格式化标准选用 [**PSR-2**](http://www.kancloud.cn/thinkphp/php-fig-psr/3141)
* 类名和类文件名遵循 [**PSR-4**](http://www.kancloud.cn/thinkphp/php-fig-psr/3144)
* 对于 Issues 的处理,请使用诸如 `fix #xxx(Issue ID)` 的 commit title 直接关闭 issue。
* 系统会自动在 PHP 5.4 5.5 5.6 7.0 和 HHVM 上测试修改,其中 HHVM 下的测试容许报错,请确保你的修改符合 PHP 5.4 ~ 5.6 和 PHP 7.0 的语法规范;
* 管理员不会合并造成 CI faild 的修改,若出现 CI faild 请检查自己的源代码或修改相应的[单元测试文件](tests)
## GitHub Issue
GitHub 提供了 Issue 功能,该功能可以用于:
* 提出 bug
* 提出功能改进
* 反馈使用体验
该功能不应该用于:
* 提出修改意见(涉及代码署名和修订追溯问题)
* 不友善的言论
## 快速修改
**GitHub 提供了快速编辑文件的功能**
1. 登录 GitHub 帐号;
2. 浏览项目文件,找到要进行修改的文件;
3. 点击右上角铅笔图标进行修改;
4. 填写 `Commit changes` 相关内容Title 必填);
5. 提交修改,等待 CI 验证和管理员合并。
**若您需要一次提交大量修改,请继续阅读下面的内容**
## 完整流程
1. `fork`本项目;
2. 克隆(`clone`)你 `fork` 的项目到本地;
3. 新建分支(`branch`)并检出(`checkout`)新分支;
4. 添加本项目到你的本地 git 仓库作为上游(`upstream`)
5. 进行修改,若你的修改包含方法或函数的增减,请记得修改[单元测试文件](tests)
6. 变基(衍合 `rebase`)你的分支到上游 master 分支;
7. `push` 你的本地仓库到 GitHub
8. 提交 `pull request`
9. 等待 CI 验证(若不通过则重复 5~7GitHub 会自动更新你的 `pull request`
10. 等待管理员处理,并及时 `rebase` 你的分支到上游 master 分支(若上游 master 分支有修改)。
*若有必要,可以 `git push -f` 强行推送 rebase 后的分支到自己的 `fork`*
*绝对不可以使用 `git push -f` 强行推送修改到上游*
### 注意事项
* 若对上述流程有任何不清楚的地方,请查阅 GIT 教程,如 [这个](http://backlogtool.com/git-guide/cn/)
* 对于代码**不同方面**的修改,请在自己 `fork` 的项目中**创建不同的分支**(原因参见`完整流程`第9条备注部分
* 变基及交互式变基操作参见 [Git 交互式变基](http://pakchoi.me/2015/03/17/git-interactive-rebase/)
## 推荐资源
### 开发环境
* XAMPP for Windows 5.5.x
* WampServer (for Windows)
* upupw Apache PHP5.4 ( for Windows)
或自行安装
- Apache / Nginx
- PHP 5.4 ~ 5.6
- MySQL / MariaDB
*Windows 用户推荐添加 PHP bin 目录到 PATH方便使用 composer*
*Linux 用户自行配置环境, Mac 用户推荐使用内置 Apache 配合 Homebrew 安装 PHP 和 MariaDB*
### 编辑器
Sublime Text 3 + phpfmt 插件
phpfmt 插件参数
```json
{
"autocomplete": true,
"enable_auto_align": true,
"format_on_save": true,
"indent_with_space": true,
"psr1_naming": false,
"psr2": true,
"version": 4
}
```
或其他 编辑器 / IDE 配合 PSR2 自动格式化工具
### Git GUI
* SourceTree
* GitHub Desktop
或其他 Git 图形界面客户端

View File

@@ -0,0 +1,32 @@
ThinkPHP遵循Apache2开源协议发布并提供免费使用。
版权所有Copyright © 2006-2018 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
Apache Licence是著名的非盈利开源组织Apache采用的协议。
该协议和BSD类似鼓励代码共享和尊重原作者的著作权
允许代码修改,再作为开源或商业软件发布。需要满足
的条件:
1 需要给代码的用户一份Apache Licence
2 如果你修改了代码,需要在被修改的文件中说明;
3 在延伸的代码中(修改和有源代码衍生的代码中)需要
带有原来代码中的协议,商标,专利声明和其他原来作者规
定需要包含的说明;
4 如果再发布的产品中包含一个Notice文件则在Notice文
件中需要带有本协议内容。你可以在Notice中增加自己的
许可但不可以表现为对Apache Licence构成更改。
具体的协议参考http://www.apache.org/licenses/LICENSE-2.0
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,99 @@
![](https://box.kancloud.cn/5a0aaa69a5ff42657b5c4715f3d49221)
ThinkPHP 5.1LTS —— 12载初心你值得信赖的PHP框架
===============
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/top-think/framework/badges/quality-score.png?b=5.1)](https://scrutinizer-ci.com/g/top-think/framework/?branch=5.1)
[![Build Status](https://travis-ci.org/top-think/framework.svg?branch=master)](https://travis-ci.org/top-think/framework)
[![Total Downloads](https://poser.pugx.org/topthink/framework/downloads)](https://packagist.org/packages/topthink/framework)
[![Latest Stable Version](https://poser.pugx.org/topthink/framework/v/stable)](https://packagist.org/packages/topthink/framework)
[![PHP Version](https://img.shields.io/badge/php-%3E%3D5.6-8892BF.svg)](http://www.php.net/)
[![License](https://poser.pugx.org/topthink/framework/license)](https://packagist.org/packages/topthink/framework)
ThinkPHP5.1对底层架构做了进一步的改进,减少依赖,其主要特性包括:
+ 采用容器统一管理对象
+ 支持Facade
+ 更易用的路由
+ 注解路由支持
+ 路由跨域请求支持
+ 验证类增强
+ 配置和路由目录独立
+ 取消系统常量
+ 类库别名机制
+ 模型和数据库增强
+ 依赖注入完善
+ 支持PSR-3日志规范
+ 中间件支持(`V5.1.6+`
+ 支持`Swoole`/`Workerman`运行(`V5.1.18+`
官方已经正式宣布`5.1.27`版本为LTS版本。
### 废除的功能:
+ 聚合模型
+ 内置控制器扩展类
+ 模型自动验证
> ThinkPHP5.1的运行环境要求PHP5.6+ 兼容PHP8.0。
## 安装
使用composer安装
~~~
composer create-project topthink/think tp
~~~
启动服务
~~~
cd tp
php think run
~~~
然后就可以在浏览器中访问
~~~
http://localhost:8000
~~~
更新框架
~~~
composer update topthink/framework
~~~
## 在线手册
+ [完全开发手册](https://www.kancloud.cn/manual/thinkphp5_1/content)
+ [升级指导](https://www.kancloud.cn/manual/thinkphp5_1/354155)
## 官方服务
+ [应用服务市场](https://market.topthink.com/)
+ [ThinkAPI——统一API服务](https://docs.topthink.com/think-api)
## 命名规范
`ThinkPHP5.1`遵循PSR-2命名规范和PSR-4自动加载规范。
## 参与开发
请参阅 [ThinkPHP5 核心框架包](https://github.com/top-think/framework)。
## 版权信息
ThinkPHP遵循Apache2开源协议发布并提供免费使用。
本项目包含的第三方源码和二进制文件之版权信息另行标注。
版权所有Copyright © 2006-2018 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
更多细节参阅 [LICENSE.txt](LICENSE.txt)

View File

@@ -0,0 +1,52 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
// 载入Loader类
require __DIR__ . '/library/think/Loader.php';
// 注册自动加载
Loader::register();
// 注册错误和异常处理机制
Error::register();
// 实现日志接口
if (interface_exists('Psr\Log\LoggerInterface')) {
interface LoggerInterface extends \Psr\Log\LoggerInterface
{}
} else {
interface LoggerInterface
{}
}
// 注册类库别名
Loader::addClassAlias([
'App' => facade\App::class,
'Build' => facade\Build::class,
'Cache' => facade\Cache::class,
'Config' => facade\Config::class,
'Cookie' => facade\Cookie::class,
'Db' => Db::class,
'Debug' => facade\Debug::class,
'Env' => facade\Env::class,
'Facade' => Facade::class,
'Hook' => facade\Hook::class,
'Lang' => facade\Lang::class,
'Log' => facade\Log::class,
'Request' => facade\Request::class,
'Response' => facade\Response::class,
'Route' => facade\Route::class,
'Session' => facade\Session::class,
'Url' => facade\Url::class,
'Validate' => facade\Validate::class,
'View' => facade\View::class,
]);

View File

@@ -0,0 +1,35 @@
{
"name": "topthink/framework",
"description": "the new thinkphp framework",
"type": "think-framework",
"keywords": [
"framework",
"thinkphp",
"ORM"
],
"homepage": "http://thinkphp.cn/",
"license": "Apache-2.0",
"authors": [
{
"name": "liu21st",
"email": "liu21st@gmail.com"
},
{
"name": "yunwuxin",
"email": "448901948@qq.com"
}
],
"require": {
"php": ">=5.6.0",
"topthink/think-installer": "2.*"
},
"require-dev": {
"phpunit/phpunit": "^5.0|^6.0",
"johnkary/phpunit-speedtrap": "^1.0",
"mikey179/vfsstream": "~1.6",
"phploc/phploc": "2.*",
"sebastian/phpcpd": "2.*",
"squizlabs/php_codesniffer": "2.*",
"phpdocumentor/reflection-docblock": "^2.0"
}
}

View File

@@ -0,0 +1,327 @@
<?php
return [
// +----------------------------------------------------------------------
// | 应用设置
// +----------------------------------------------------------------------
'app' => [
// 应用名称
'app_name' => '',
// 应用地址
'app_host' => '',
// 应用调试模式
'app_debug' => false,
// 应用Trace
'app_trace' => false,
// 应用模式状态
'app_status' => '',
// 是否HTTPS
'is_https' => false,
// 入口自动绑定模块
'auto_bind_module' => false,
// 注册的根命名空间
'root_namespace' => [],
// 默认输出类型
'default_return_type' => 'html',
// 默认AJAX 数据返回格式,可选json xml ...
'default_ajax_return' => 'json',
// 默认JSONP格式返回的处理方法
'default_jsonp_handler' => 'jsonpReturn',
// 默认JSONP处理方法
'var_jsonp_handler' => 'callback',
// 默认时区
'default_timezone' => 'Asia/Shanghai',
// 是否开启多语言
'lang_switch_on' => false,
// 默认验证器
'default_validate' => '',
// 默认语言
'default_lang' => 'zh-cn',
// +----------------------------------------------------------------------
// | 模块设置
// +----------------------------------------------------------------------
// 自动搜索控制器
'controller_auto_search' => false,
// 操作方法前缀
'use_action_prefix' => false,
// 操作方法后缀
'action_suffix' => '',
// 默认的空控制器名
'empty_controller' => 'Error',
// 默认的空模块名
'empty_module' => '',
// 默认模块名
'default_module' => 'index',
// 是否支持多模块
'app_multi_module' => true,
// 禁止访问模块
'deny_module_list' => ['common'],
// 默认控制器名
'default_controller' => 'Index',
// 默认操作名
'default_action' => 'index',
// 是否自动转换URL中的控制器和操作名
'url_convert' => true,
// 默认的访问控制器层
'url_controller_layer' => 'controller',
// 应用类库后缀
'class_suffix' => false,
// 控制器类后缀
'controller_suffix' => false,
// +----------------------------------------------------------------------
// | URL请求设置
// +----------------------------------------------------------------------
// 默认全局过滤方法 用逗号分隔多个
'default_filter' => '',
// PATHINFO变量名 用于兼容模式
'var_pathinfo' => 's',
// 兼容PATH_INFO获取
'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
// HTTPS代理标识
'https_agent_name' => '',
// IP代理获取标识
'http_agent_ip' => 'HTTP_X_REAL_IP',
// URL伪静态后缀
'url_html_suffix' => 'html',
// 域名根如thinkphp.cn
'url_domain_root' => '',
// 表单请求类型伪装变量
'var_method' => '_method',
// 表单ajax伪装变量
'var_ajax' => '_ajax',
// 表单pjax伪装变量
'var_pjax' => '_pjax',
// 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
'request_cache' => false,
// 请求缓存有效期
'request_cache_expire' => null,
// 全局请求缓存排除规则
'request_cache_except' => [],
// +----------------------------------------------------------------------
// | 路由设置
// +----------------------------------------------------------------------
// pathinfo分隔符
'pathinfo_depr' => '/',
// URL普通方式参数 用于自动生成
'url_common_param' => false,
// URL参数方式 0 按名称成对解析 1 按顺序解析
'url_param_type' => 0,
// 是否开启路由延迟解析
'url_lazy_route' => false,
// 是否强制使用路由
'url_route_must' => false,
// 合并路由规则
'route_rule_merge' => false,
// 路由是否完全匹配
'route_complete_match' => false,
// 使用注解路由
'route_annotation' => false,
// 默认的路由变量规则
'default_route_pattern' => '\w+',
// 是否开启路由缓存
'route_check_cache' => false,
// 路由缓存的Key自定义设置闭包默认为当前URL和请求类型的md5
'route_check_cache_key' => '',
// 路由缓存的设置
'route_cache_option' => [],
// +----------------------------------------------------------------------
// | 异常及错误设置
// +----------------------------------------------------------------------
// 默认跳转页面对应的模板文件
'dispatch_success_tmpl' => __DIR__ . '/tpl/dispatch_jump.tpl',
'dispatch_error_tmpl' => __DIR__ . '/tpl/dispatch_jump.tpl',
// 异常页面的模板文件
'exception_tmpl' => __DIR__ . '/tpl/think_exception.tpl',
// 错误显示信息,非调试模式有效
'error_message' => '页面错误!请稍后再试~',
// 显示错误信息
'show_error_msg' => false,
// 异常处理handle类 留空使用 \think\exception\Handle
'exception_handle' => '',
],
// +----------------------------------------------------------------------
// | 模板设置
// +----------------------------------------------------------------------
'template' => [
// 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写
'auto_rule' => 1,
// 模板引擎类型 支持 php think 支持扩展
'type' => 'Think',
// 视图基础目录,配置目录为所有模块的视图起始目录
'view_base' => '',
// 当前模板的视图目录 留空为自动获取
'view_path' => '',
// 模板后缀
'view_suffix' => 'html',
// 模板文件名分隔符
'view_depr' => DIRECTORY_SEPARATOR,
// 模板引擎普通标签开始标记
'tpl_begin' => '{',
// 模板引擎普通标签结束标记
'tpl_end' => '}',
// 标签库标签开始标记
'taglib_begin' => '{',
// 标签库标签结束标记
'taglib_end' => '}',
],
// +----------------------------------------------------------------------
// | 日志设置
// +----------------------------------------------------------------------
'log' => [
// 日志记录方式,内置 file socket 支持扩展
'type' => 'File',
// 日志保存目录
//'path' => LOG_PATH,
// 日志记录级别
'level' => [],
// 是否记录trace信息到日志
'record_trace' => false,
// 是否JSON格式记录
'json' => false,
],
// +----------------------------------------------------------------------
// | Trace设置 开启 app_trace 后 有效
// +----------------------------------------------------------------------
'trace' => [
// 内置Html Console 支持扩展
'type' => 'Html',
'file' => __DIR__ . '/tpl/page_trace.tpl',
],
// +----------------------------------------------------------------------
// | 缓存设置
// +----------------------------------------------------------------------
'cache' => [
// 驱动方式
'type' => 'File',
// 缓存保存目录
//'path' => CACHE_PATH,
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 0,
],
// +----------------------------------------------------------------------
// | 会话设置
// +----------------------------------------------------------------------
'session' => [
'id' => '',
// SESSION_ID的提交变量,解决flash上传跨域
'var_session_id' => '',
// SESSION 前缀
'prefix' => 'think',
// 驱动方式 支持redis memcache memcached
'type' => '',
// 是否自动开启 SESSION
'auto_start' => true,
'httponly' => true,
'secure' => false,
],
// +----------------------------------------------------------------------
// | Cookie设置
// +----------------------------------------------------------------------
'cookie' => [
// cookie 名称前缀
'prefix' => '',
// cookie 保存时间
'expire' => 0,
// cookie 保存路径
'path' => '/',
// cookie 有效域名
'domain' => '',
// cookie 启用安全传输
'secure' => false,
// httponly设置
'httponly' => '',
// 是否使用 setcookie
'setcookie' => true,
],
// +----------------------------------------------------------------------
// | 数据库设置
// +----------------------------------------------------------------------
'database' => [
// 数据库类型
'type' => 'mysql',
// 数据库连接DSN配置
'dsn' => '',
// 服务器地址
'hostname' => '127.0.0.1',
// 数据库名
'database' => '',
// 数据库用户名
'username' => 'root',
// 数据库密码
'password' => '',
// 数据库连接端口
'hostport' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => '',
// 数据库调试模式
'debug' => false,
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 数据集返回类型
'resultset_type' => 'array',
// 自动写入时间戳字段
'auto_timestamp' => false,
// 时间字段取出后的默认时间格式
'datetime_format' => 'Y-m-d H:i:s',
// 是否需要进行SQL性能分析
'sql_explain' => false,
// 查询对象
'query' => '\\think\\db\\Query',
],
//分页配置
'paginate' => [
'type' => 'bootstrap',
'var_page' => 'page',
'list_rows' => 15,
],
//控制台配置
'console' => [
'name' => 'Think Console',
'version' => '0.1',
'user' => null,
'auto_path' => '',
],
// 中间件配置
'middleware' => [
'default_namespace' => 'app\\http\\middleware\\',
],
];

View File

@@ -0,0 +1,726 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
//------------------------
// ThinkPHP 助手函数
//-------------------------
use think\Container;
use think\Db;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\facade\Cache;
use think\facade\Config;
use think\facade\Cookie;
use think\facade\Debug;
use think\facade\Env;
use think\facade\Hook;
use think\facade\Lang;
use think\facade\Log;
use think\facade\Request;
use think\facade\Route;
use think\facade\Session;
use think\facade\Url;
use think\Response;
use think\route\RuleItem;
if (!function_exists('abort')) {
/**
* 抛出HTTP异常
* @param integer|Response $code 状态码 或者 Response对象实例
* @param string $message 错误信息
* @param array $header 参数
*/
function abort($code, $message = null, $header = [])
{
if ($code instanceof Response) {
throw new HttpResponseException($code);
} else {
throw new HttpException($code, $message, null, $header);
}
}
}
if (!function_exists('action')) {
/**
* 调用模块的操作方法 参数格式 [模块/控制器/]操作
* @param string $url 调用地址
* @param string|array $vars 调用参数 支持字符串和数组
* @param string $layer 要调用的控制层名称
* @param bool $appendSuffix 是否添加类名后缀
* @return mixed
*/
function action($url, $vars = [], $layer = 'controller', $appendSuffix = false)
{
return app()->action($url, $vars, $layer, $appendSuffix);
}
}
if (!function_exists('app')) {
/**
* 快速获取容器中的实例 支持依赖注入
* @param string $name 类名或标识 默认获取当前应用实例
* @param array $args 参数
* @param bool $newInstance 是否每次创建新的实例
* @return mixed|\think\App
*/
function app($name = 'think\App', $args = [], $newInstance = false)
{
return Container::get($name, $args, $newInstance);
}
}
if (!function_exists('behavior')) {
/**
* 执行某个行为run方法 支持依赖注入
* @param mixed $behavior 行为类名或者别名
* @param mixed $args 参数
* @return mixed
*/
function behavior($behavior, $args = null)
{
return Hook::exec($behavior, $args);
}
}
if (!function_exists('bind')) {
/**
* 绑定一个类到容器
* @access public
* @param string $abstract 类标识、接口
* @param mixed $concrete 要绑定的类、闭包或者实例
* @return Container
*/
function bind($abstract, $concrete = null)
{
return Container::getInstance()->bindTo($abstract, $concrete);
}
}
if (!function_exists('cache')) {
/**
* 缓存管理
* @param mixed $name 缓存名称,如果为数组表示进行缓存设置
* @param mixed $value 缓存值
* @param mixed $options 缓存参数
* @param string $tag 缓存标签
* @return mixed
*/
function cache($name, $value = '', $options = null, $tag = null)
{
if (is_array($options)) {
// 缓存操作的同时初始化
Cache::connect($options);
} elseif (is_array($name)) {
// 缓存初始化
return Cache::connect($name);
}
if ('' === $value) {
// 获取缓存
return 0 === strpos($name, '?') ? Cache::has(substr($name, 1)) : Cache::get($name);
} elseif (is_null($value)) {
// 删除缓存
return Cache::rm($name);
}
// 缓存数据
if (is_array($options)) {
$expire = isset($options['expire']) ? $options['expire'] : null; //修复查询缓存无法设置过期时间
} else {
$expire = is_numeric($options) ? $options : null; //默认快捷缓存设置过期时间
}
if (is_null($tag)) {
return Cache::set($name, $value, $expire);
} else {
return Cache::tag($tag)->set($name, $value, $expire);
}
}
}
if (!function_exists('call')) {
/**
* 调用反射执行callable 支持依赖注入
* @param mixed $callable 支持闭包等callable写法
* @param array $args 参数
* @return mixed
*/
function call($callable, $args = [])
{
return Container::getInstance()->invoke($callable, $args);
}
}
if (!function_exists('class_basename')) {
/**
* 获取类名(不包含命名空间)
*
* @param string|object $class
* @return string
*/
function class_basename($class)
{
$class = is_object($class) ? get_class($class) : $class;
return basename(str_replace('\\', '/', $class));
}
}
if (!function_exists('class_uses_recursive')) {
/**
*获取一个类里所有用到的trait包括父类的
*
* @param $class
* @return array
*/
function class_uses_recursive($class)
{
if (is_object($class)) {
$class = get_class($class);
}
$results = [];
$classes = array_merge([$class => $class], class_parents($class));
foreach ($classes as $class) {
$results += trait_uses_recursive($class);
}
return array_unique($results);
}
}
if (!function_exists('config')) {
/**
* 获取和设置配置参数
* @param string|array $name 参数名
* @param mixed $value 参数值
* @return mixed
*/
function config($name = '', $value = null)
{
if (is_null($value) && is_string($name)) {
if ('.' == substr($name, -1)) {
return Config::pull(substr($name, 0, -1));
}
return 0 === strpos($name, '?') ? Config::has(substr($name, 1)) : Config::get($name);
} else {
return Config::set($name, $value);
}
}
}
if (!function_exists('container')) {
/**
* 获取容器对象实例
* @return Container
*/
function container()
{
return Container::getInstance();
}
}
if (!function_exists('controller')) {
/**
* 实例化控制器 格式:[模块/]控制器
* @param string $name 资源地址
* @param string $layer 控制层名称
* @param bool $appendSuffix 是否添加类名后缀
* @return \think\Controller
*/
function controller($name, $layer = 'controller', $appendSuffix = false)
{
return app()->controller($name, $layer, $appendSuffix);
}
}
if (!function_exists('cookie')) {
/**
* Cookie管理
* @param string|array $name cookie名称如果为数组表示进行cookie设置
* @param mixed $value cookie值
* @param mixed $option 参数
* @return mixed
*/
function cookie($name, $value = '', $option = null)
{
if (is_array($name)) {
// 初始化
Cookie::init($name);
} elseif (is_null($name)) {
// 清除
Cookie::clear($value);
} elseif ('' === $value) {
// 获取
return 0 === strpos($name, '?') ? Cookie::has(substr($name, 1), $option) : Cookie::get($name);
} elseif (is_null($value)) {
// 删除
return Cookie::delete($name);
} else {
// 设置
return Cookie::set($name, $value, $option);
}
}
}
if (!function_exists('db')) {
/**
* 实例化数据库类
* @param string $name 操作的数据表名称(不含前缀)
* @param array|string $config 数据库配置参数
* @param bool $force 是否强制重新连接
* @return \think\db\Query
*/
function db($name = '', $config = [], $force = true)
{
return Db::connect($config, $force)->name($name);
}
}
if (!function_exists('debug')) {
/**
* 记录时间(微秒)和内存使用情况
* @param string $start 开始标签
* @param string $end 结束标签
* @param integer|string $dec 小数位 如果是m 表示统计内存占用
* @return mixed
*/
function debug($start, $end = '', $dec = 6)
{
if ('' == $end) {
Debug::remark($start);
} else {
return 'm' == $dec ? Debug::getRangeMem($start, $end) : Debug::getRangeTime($start, $end, $dec);
}
}
}
if (!function_exists('download')) {
/**
* 获取\think\response\Download对象实例
* @param string $filename 要下载的文件
* @param string $name 显示文件名
* @param bool $content 是否为内容
* @param integer $expire 有效期(秒)
* @return \think\response\Download
*/
function download($filename, $name = '', $content = false, $expire = 360, $openinBrowser = false)
{
return Response::create($filename, 'download')->name($name)->isContent($content)->expire($expire)->openinBrowser($openinBrowser);
}
}
if (!function_exists('dump')) {
/**
* 浏览器友好的变量输出
* @param mixed $var 变量
* @param boolean $echo 是否输出 默认为true 如果为false 则返回输出字符串
* @param string $label 标签 默认为空
* @return void|string
*/
function dump($var, $echo = true, $label = null)
{
return Debug::dump($var, $echo, $label);
}
}
if (!function_exists('env')) {
/**
* 获取环境变量值
* @access public
* @param string $name 环境变量名(支持二级 .号分割)
* @param string $default 默认值
* @return mixed
*/
function env($name = null, $default = null)
{
return Env::get($name, $default);
}
}
if (!function_exists('exception')) {
/**
* 抛出异常处理
*
* @param string $msg 异常消息
* @param integer $code 异常代码 默认为0
* @param string $exception 异常类
*
* @throws Exception
*/
function exception($msg, $code = 0, $exception = '')
{
$e = $exception ?: '\think\Exception';
throw new $e($msg, $code);
}
}
if (!function_exists('halt')) {
/**
* 调试变量并且中断输出
* @param mixed $var 调试变量或者信息
*/
function halt($var)
{
// dump($var);
throw new HttpResponseException(new Response);
}
}
if (!function_exists('input')) {
/**
* 获取输入数据 支持默认值和过滤
* @param string $key 获取的变量名
* @param mixed $default 默认值
* @param string $filter 过滤方法
* @return mixed
*/
function input($key = '', $default = null, $filter = '')
{
if (0 === strpos($key, '?')) {
$key = substr($key, 1);
$has = true;
}
if ($pos = strpos($key, '.')) {
// 指定参数来源
$method = substr($key, 0, $pos);
if (in_array($method, ['get', 'post', 'put', 'patch', 'delete', 'route', 'param', 'request', 'session', 'cookie', 'server', 'env', 'path', 'file'])) {
$key = substr($key, $pos + 1);
} else {
$method = 'param';
}
} else {
// 默认为自动判断
$method = 'param';
}
if (isset($has)) {
return request()->has($key, $method, $default);
} else {
return request()->$method($key, $default, $filter);
}
}
}
if (!function_exists('json')) {
/**
* 获取\think\response\Json对象实例
* @param mixed $data 返回的数据
* @param integer $code 状态码
* @param array $header 头部
* @param array $options 参数
* @return \think\response\Json
*/
function json($data = [], $code = 200, $header = [], $options = [])
{
return Response::create($data, 'json', $code, $header, $options);
}
}
if (!function_exists('jsonp')) {
/**
* 获取\think\response\Jsonp对象实例
* @param mixed $data 返回的数据
* @param integer $code 状态码
* @param array $header 头部
* @param array $options 参数
* @return \think\response\Jsonp
*/
function jsonp($data = [], $code = 200, $header = [], $options = [])
{
return Response::create($data, 'jsonp', $code, $header, $options);
}
}
if (!function_exists('lang')) {
/**
* 获取语言变量值
* @param string $name 语言变量名
* @param array $vars 动态变量值
* @param string $lang 语言
* @return mixed
*/
function lang($name, $vars = [], $lang = '')
{
return Lang::get($name, $vars, $lang);
}
}
if (!function_exists('model')) {
/**
* 实例化Model
* @param string $name Model名称
* @param string $layer 业务层名称
* @param bool $appendSuffix 是否添加类名后缀
* @return \think\Model
*/
function model($name = '', $layer = 'model', $appendSuffix = false)
{
return app()->model($name, $layer, $appendSuffix);
}
}
if (!function_exists('parse_name')) {
/**
* 字符串命名风格转换
* type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
* @param string $name 字符串
* @param integer $type 转换类型
* @param bool $ucfirst 首字母是否大写(驼峰规则)
* @return string
*/
function parse_name($name, $type = 0, $ucfirst = true)
{
if ($type) {
$name = preg_replace_callback('/_([a-zA-Z])/', function ($match) {
return strtoupper($match[1]);
}, $name);
return $ucfirst ? ucfirst($name) : lcfirst($name);
} else {
return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
}
}
}
if (!function_exists('redirect')) {
/**
* 获取\think\response\Redirect对象实例
* @param mixed $url 重定向地址 支持Url::build方法的地址
* @param array|integer $params 额外参数
* @param integer $code 状态码
* @return \think\response\Redirect
*/
function redirect($url = [], $params = [], $code = 302)
{
if (is_integer($params)) {
$code = $params;
$params = [];
}
return Response::create($url, 'redirect', $code)->params($params);
}
}
if (!function_exists('request')) {
/**
* 获取当前Request对象实例
* @return Request
*/
function request()
{
return app('request');
}
}
if (!function_exists('response')) {
/**
* 创建普通 Response 对象实例
* @param mixed $data 输出数据
* @param int|string $code 状态码
* @param array $header 头信息
* @param string $type
* @return Response
*/
function response($data = '', $code = 200, $header = [], $type = 'html')
{
return Response::create($data, $type, $code, $header);
}
}
if (!function_exists('route')) {
/**
* 路由注册
* @param string $rule 路由规则
* @param mixed $route 路由地址
* @param array $option 路由参数
* @param array $pattern 变量规则
* @return RuleItem
*/
function route($rule, $route, $option = [], $pattern = [])
{
return Route::rule($rule, $route, '*', $option, $pattern);
}
}
if (!function_exists('session')) {
/**
* Session管理
* @param string|array $name session名称如果为数组表示进行session设置
* @param mixed $value session值
* @param string $prefix 前缀
* @return mixed
*/
function session($name, $value = '', $prefix = null)
{
if (is_array($name)) {
// 初始化
Session::init($name);
} elseif (is_null($name)) {
// 清除
Session::clear($value);
} elseif ('' === $value) {
// 判断或获取
return 0 === strpos($name, '?') ? Session::has(substr($name, 1), $prefix) : Session::get($name, $prefix);
} elseif (is_null($value)) {
// 删除
return Session::delete($name, $prefix);
} else {
// 设置
return Session::set($name, $value, $prefix);
}
}
}
if (!function_exists('token')) {
/**
* 生成表单令牌
* @param string $name 令牌名称
* @param mixed $type 令牌生成方法
* @return string
*/
function token($name = '__token__', $type = 'md5')
{
$token = Request::token($name, $type);
return '<input type="hidden" name="' . $name . '" value="' . $token . '" />';
}
}
if (!function_exists('trace')) {
/**
* 记录日志信息
* @param mixed $log log信息 支持字符串和数组
* @param string $level 日志级别
* @return array|void
*/
function trace($log = '[think]', $level = 'log')
{
if ('[think]' === $log) {
return Log::getLog();
} else {
Log::record($log, $level);
}
}
}
if (!function_exists('trait_uses_recursive')) {
/**
* 获取一个trait里所有引用到的trait
*
* @param string $trait
* @return array
*/
function trait_uses_recursive($trait)
{
$traits = class_uses($trait);
foreach ($traits as $trait) {
$traits += trait_uses_recursive($trait);
}
return $traits;
}
}
if (!function_exists('url')) {
/**
* Url生成
* @param string $url 路由地址
* @param string|array $vars 变量
* @param bool|string $suffix 生成的URL后缀
* @param bool|string $domain 域名
* @return string
*/
function url($url = '', $vars = '', $suffix = true, $domain = false)
{
return Url::build($url, $vars, $suffix, $domain);
}
}
if (!function_exists('validate')) {
/**
* 实例化验证器
* @param string $name 验证器名称
* @param string $layer 业务层名称
* @param bool $appendSuffix 是否添加类名后缀
* @return \think\Validate
*/
function validate($name = '', $layer = 'validate', $appendSuffix = false)
{
return app()->validate($name, $layer, $appendSuffix);
}
}
if (!function_exists('view')) {
/**
* 渲染模板输出
* @param string $template 模板文件
* @param array $vars 模板变量
* @param integer $code 状态码
* @param callable $filter 内容过滤
* @return \think\response\View
*/
function view($template = '', $vars = [], $code = 200, $filter = null)
{
return Response::create($template, 'view', $code)->assign($vars)->filter($filter);
}
}
if (!function_exists('widget')) {
/**
* 渲染输出Widget
* @param string $name Widget名称
* @param array $data 传入的参数
* @return mixed
*/
function widget($name, $data = [])
{
$result = app()->action($name, $data, 'widget');
if (is_object($result)) {
$result = $result->getContent();
}
return $result;
}
}
if (!function_exists('xml')) {
/**
* 获取\think\response\Xml对象实例
* @param mixed $data 返回的数据
* @param integer $code 状态码
* @param array $header 头部
* @param array $options 参数
* @return \think\response\Xml
*/
function xml($data = [], $code = 200, $header = [], $options = [])
{
return Response::create($data, 'xml', $code, $header, $options);
}
}
if (!function_exists('yaconf')) {
/**
* 获取yaconf配置
*
* @param string $name 配置参数名
* @param mixed $default 默认值
* @return mixed
*/
function yaconf($name, $default = null)
{
return Config::yaconf($name, $default);
}
}

View File

@@ -0,0 +1,144 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 核心中文语言包
return [
// 系统错误提示
'Undefined variable' => '未定义变量',
'Undefined index' => '未定义数组索引',
'Undefined offset' => '未定义数组下标',
'Parse error' => '语法解析错误',
'Type error' => '类型错误',
'Fatal error' => '致命错误',
'syntax error' => '语法错误',
// 框架核心错误提示
'dispatch type not support' => '不支持的调度类型',
'method param miss' => '方法参数错误',
'method not exists' => '方法不存在',
'function not exists' => '函数不存在',
'file not exists' => '文件不存在',
'module not exists' => '模块不存在',
'controller not exists' => '控制器不存在',
'class not exists' => '类不存在',
'property not exists' => '类的属性不存在',
'template not exists' => '模板文件不存在',
'illegal controller name' => '非法的控制器名称',
'illegal action name' => '非法的操作名称',
'url suffix deny' => '禁止的URL后缀访问',
'Route Not Found' => '当前访问路由未定义或不匹配',
'Undefined db type' => '未定义数据库类型',
'variable type error' => '变量类型错误',
'PSR-4 error' => 'PSR-4 规范错误',
'not support total' => '简洁模式下不能获取数据总数',
'not support last' => '简洁模式下不能获取最后一页',
'error session handler' => '错误的SESSION处理器类',
'not allow php tag' => '模板不允许使用PHP语法',
'not support' => '不支持',
'redisd master' => 'Redisd 主服务器错误',
'redisd slave' => 'Redisd 从服务器错误',
'must run at sae' => '必须在SAE运行',
'memcache init error' => '未开通Memcache服务请在SAE管理平台初始化Memcache服务',
'KVDB init error' => '没有初始化KVDB请在SAE管理平台初始化KVDB服务',
'fields not exists' => '数据表字段不存在',
'where express error' => '查询表达式错误',
'order express error' => '排序表达式错误',
'no data to update' => '没有任何数据需要更新',
'miss data to insert' => '缺少需要写入的数据',
'not support data' => '不支持的数据表达式',
'miss complex primary data' => '缺少复合主键数据',
'miss update condition' => '缺少更新条件',
'model data Not Found' => '模型数据不存在',
'table data not Found' => '表数据不存在',
'delete without condition' => '没有条件不会执行删除操作',
'miss relation data' => '缺少关联表数据',
'tag attr must' => '模板标签属性必须',
'tag error' => '模板标签错误',
'cache write error' => '缓存写入失败',
'sae mc write error' => 'SAE mc 写入错误',
'route name not exists' => '路由标识不存在(或参数不够)',
'invalid request' => '非法请求',
'bind attr has exists' => '模型的属性已经存在',
'relation data not exists' => '关联数据不存在',
'relation not support' => '关联不支持',
'chunk not support order' => 'Chunk不支持调用order方法',
'route pattern error' => '路由变量规则定义错误',
'route behavior will not support' => '路由行为废弃(使用中间件替代)',
'closure not support cache(true)' => '使用闭包查询不支持cache(true)请指定缓存Key',
// 上传错误信息
'unknown upload error' => '未知上传错误!',
'file write error' => '文件写入失败!',
'upload temp dir not found' => '找不到临时文件夹!',
'no file to uploaded' => '没有文件被上传!',
'only the portion of file is uploaded' => '文件只有部分被上传!',
'upload File size exceeds the maximum value' => '上传文件大小超过了最大值!',
'upload write error' => '文件上传保存错误!',
'has the same filename: {:filename}' => '存在同名文件:{:filename}',
'upload illegal files' => '非法上传文件',
'illegal image files' => '非法图片文件',
'extensions to upload is not allowed' => '上传文件后缀不允许',
'mimetype to upload is not allowed' => '上传文件MIME类型不允许',
'filesize not match' => '上传文件大小不符!',
'directory {:path} creation failed' => '目录 {:path} 创建失败!',
'The middleware must return Response instance' => '中间件方法必须返回Response对象实例',
'The queue was exhausted, with no response returned' => '中间件队列为空',
// Validate Error Message
':attribute require' => ':attribute不能为空',
':attribute must' => ':attribute必须',
':attribute must be numeric' => ':attribute必须是数字',
':attribute must be integer' => ':attribute必须是整数',
':attribute must be float' => ':attribute必须是浮点数',
':attribute must be bool' => ':attribute必须是布尔值',
':attribute not a valid email address' => ':attribute格式不符',
':attribute not a valid mobile' => ':attribute格式不符',
':attribute must be a array' => ':attribute必须是数组',
':attribute must be yes,on or 1' => ':attribute必须是yes、on或者1',
':attribute not a valid datetime' => ':attribute不是一个有效的日期或时间格式',
':attribute not a valid file' => ':attribute不是有效的上传文件',
':attribute not a valid image' => ':attribute不是有效的图像文件',
':attribute must be alpha' => ':attribute只能是字母',
':attribute must be alpha-numeric' => ':attribute只能是字母和数字',
':attribute must be alpha-numeric, dash, underscore' => ':attribute只能是字母、数字和下划线_及破折号-',
':attribute not a valid domain or ip' => ':attribute不是有效的域名或者IP',
':attribute must be chinese' => ':attribute只能是汉字',
':attribute must be chinese or alpha' => ':attribute只能是汉字、字母',
':attribute must be chinese,alpha-numeric' => ':attribute只能是汉字、字母和数字',
':attribute must be chinese,alpha-numeric,underscore, dash' => ':attribute只能是汉字、字母、数字和下划线_及破折号-',
':attribute not a valid url' => ':attribute不是有效的URL地址',
':attribute not a valid ip' => ':attribute不是有效的IP地址',
':attribute must be dateFormat of :rule' => ':attribute必须使用日期格式 :rule',
':attribute must be in :rule' => ':attribute必须在 :rule 范围内',
':attribute be notin :rule' => ':attribute不能在 :rule 范围内',
':attribute must between :1 - :2' => ':attribute只能在 :1 - :2 之间',
':attribute not between :1 - :2' => ':attribute不能在 :1 - :2 之间',
'size of :attribute must be :rule' => ':attribute长度不符合要求 :rule',
'max size of :attribute must be :rule' => ':attribute长度不能超过 :rule',
'min size of :attribute must be :rule' => ':attribute长度不能小于 :rule',
':attribute cannot be less than :rule' => ':attribute日期不能小于 :rule',
':attribute cannot exceed :rule' => ':attribute日期不能超过 :rule',
':attribute not within :rule' => '不在有效期内 :rule',
'access IP is not allowed' => '不允许的IP访问',
'access IP denied' => '禁止的IP访问',
':attribute out of accord with :2' => ':attribute和确认字段:2不一致',
':attribute cannot be same with :2' => ':attribute和比较字段:2不能相同',
':attribute must greater than or equal :rule' => ':attribute必须大于等于 :rule',
':attribute must greater than :rule' => ':attribute必须大于 :rule',
':attribute must less than or equal :rule' => ':attribute必须小于等于 :rule',
':attribute must less than :rule' => ':attribute必须小于 :rule',
':attribute must equal :rule' => ':attribute必须等于 :rule',
':attribute has exists' => ':attribute已存在',
':attribute not conform to the rules' => ':attribute不符合指定规则',
'invalid Request method' => '无效的请求类型',
'invalid token' => '令牌数据无效',
'not conform to the rules' => '规则错误',
];

View File

@@ -0,0 +1,979 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
use think\exception\ClassNotFoundException;
use think\exception\HttpResponseException;
use think\route\Dispatch;
/**
* App 应用管理
*/
class App extends Container
{
const VERSION = '5.1.41 LTS';
/**
* 当前模块路径
* @var string
*/
protected $modulePath;
/**
* 应用调试模式
* @var bool
*/
protected $appDebug = true;
/**
* 应用开始时间
* @var float
*/
protected $beginTime;
/**
* 应用内存初始占用
* @var integer
*/
protected $beginMem;
/**
* 应用类库命名空间
* @var string
*/
protected $namespace = 'app';
/**
* 应用类库后缀
* @var bool
*/
protected $suffix = false;
/**
* 严格路由检测
* @var bool
*/
protected $routeMust;
/**
* 应用类库目录
* @var string
*/
protected $appPath;
/**
* 框架目录
* @var string
*/
protected $thinkPath;
/**
* 应用根目录
* @var string
*/
protected $rootPath;
/**
* 运行时目录
* @var string
*/
protected $runtimePath;
/**
* 配置目录
* @var string
*/
protected $configPath;
/**
* 路由目录
* @var string
*/
protected $routePath;
/**
* 配置后缀
* @var string
*/
protected $configExt;
/**
* 应用调度实例
* @var Dispatch
*/
protected $dispatch;
/**
* 绑定模块(控制器)
* @var string
*/
protected $bindModule;
/**
* 初始化
* @var bool
*/
protected $initialized = false;
public function __construct($appPath = '')
{
$this->thinkPath = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR;
$this->path($appPath);
}
/**
* 绑定模块或者控制器
* @access public
* @param string $bind
* @return $this
*/
public function bind($bind)
{
$this->bindModule = $bind;
return $this;
}
/**
* 设置应用类库目录
* @access public
* @param string $path 路径
* @return $this
*/
public function path($path)
{
$this->appPath = $path ? realpath($path) . DIRECTORY_SEPARATOR : $this->getAppPath();
return $this;
}
/**
* 初始化应用
* @access public
* @return void
*/
public function initialize()
{
if ($this->initialized) {
return;
}
$this->initialized = true;
$this->beginTime = microtime(true);
$this->beginMem = memory_get_usage();
$this->rootPath = dirname($this->appPath) . DIRECTORY_SEPARATOR;
$this->runtimePath = $this->rootPath . 'runtime' . DIRECTORY_SEPARATOR;
$this->routePath = $this->rootPath . 'route' . DIRECTORY_SEPARATOR;
$this->configPath = $this->rootPath . 'config' . DIRECTORY_SEPARATOR;
static::setInstance($this);
$this->instance('app', $this);
// 加载环境变量配置文件
if (is_file($this->rootPath . '.env')) {
$this->env->load($this->rootPath . '.env');
}
$this->configExt = $this->env->get('config_ext', '.php');
// 加载惯例配置文件
$this->config->set(include $this->thinkPath . 'convention.php');
// 设置路径环境变量
$this->env->set([
'think_path' => $this->thinkPath,
'root_path' => $this->rootPath,
'app_path' => $this->appPath,
'config_path' => $this->configPath,
'route_path' => $this->routePath,
'runtime_path' => $this->runtimePath,
'extend_path' => $this->rootPath . 'extend' . DIRECTORY_SEPARATOR,
'vendor_path' => $this->rootPath . 'vendor' . DIRECTORY_SEPARATOR,
]);
$this->namespace = $this->env->get('app_namespace', $this->namespace);
$this->env->set('app_namespace', $this->namespace);
// 注册应用命名空间
Loader::addNamespace($this->namespace, $this->appPath);
// 初始化应用
$this->init();
// 开启类名后缀
$this->suffix = $this->config('app.class_suffix');
// 应用调试模式
$this->appDebug = $this->env->get('app_debug', $this->config('app.app_debug'));
$this->env->set('app_debug', $this->appDebug);
if (!$this->appDebug) {
ini_set('display_errors', 'Off');
} elseif (PHP_SAPI != 'cli') {
//重新申请一块比较大的buffer
if (ob_get_level() > 0) {
$output = ob_get_clean();
}
ob_start();
if (!empty($output)) {
echo $output;
}
}
// 注册异常处理类
if ($this->config('app.exception_handle')) {
Error::setExceptionHandler($this->config('app.exception_handle'));
}
// 注册根命名空间
if (!empty($this->config('app.root_namespace'))) {
Loader::addNamespace($this->config('app.root_namespace'));
}
// 加载composer autofile文件
Loader::loadComposerAutoloadFiles();
// 注册类库别名
Loader::addClassAlias($this->config->pull('alias'));
// 数据库配置初始化
Db::init($this->config->pull('database'));
// 设置系统时区
date_default_timezone_set($this->config('app.default_timezone'));
// 读取语言包
$this->loadLangPack();
// 路由初始化
$this->routeInit();
}
/**
* 初始化应用或模块
* @access public
* @param string $module 模块名
* @return void
*/
public function init($module = '')
{
// 定位模块目录
$module = $module ? $module . DIRECTORY_SEPARATOR : '';
$path = $this->appPath . $module;
// 加载初始化文件
if (is_file($path . 'init.php')) {
include $path . 'init.php';
} elseif (is_file($this->runtimePath . $module . 'init.php')) {
include $this->runtimePath . $module . 'init.php';
} else {
// 加载行为扩展文件
if (is_file($path . 'tags.php')) {
$tags = include $path . 'tags.php';
if (is_array($tags)) {
$this->hook->import($tags);
}
}
// 加载公共文件
if (is_file($path . 'common.php')) {
include_once $path . 'common.php';
}
if ('' == $module) {
// 加载系统助手函数
include $this->thinkPath . 'helper.php';
}
// 加载中间件
if (is_file($path . 'middleware.php')) {
$middleware = include $path . 'middleware.php';
if (is_array($middleware)) {
$this->middleware->import($middleware);
}
}
// 注册服务的容器对象实例
if (is_file($path . 'provider.php')) {
$provider = include $path . 'provider.php';
if (is_array($provider)) {
$this->bindTo($provider);
}
}
// 自动读取配置文件
if (is_dir($path . 'config')) {
$dir = $path . 'config' . DIRECTORY_SEPARATOR;
} elseif (is_dir($this->configPath . $module)) {
$dir = $this->configPath . $module;
}
$files = isset($dir) ? scandir($dir) : [];
foreach ($files as $file) {
if ('.' . pathinfo($file, PATHINFO_EXTENSION) === $this->configExt) {
$this->config->load($dir . $file, pathinfo($file, PATHINFO_FILENAME));
}
}
}
$this->setModulePath($path);
if ($module) {
// 对容器中的对象实例进行配置更新
$this->containerConfigUpdate($module);
}
}
protected function containerConfigUpdate($module)
{
$config = $this->config->get();
// 注册异常处理类
if ($config['app']['exception_handle']) {
Error::setExceptionHandler($config['app']['exception_handle']);
}
Db::init($config['database']);
$this->middleware->setConfig($config['middleware']);
$this->route->setConfig($config['app']);
$this->request->init($config['app']);
$this->cookie->init($config['cookie']);
$this->view->init($config['template']);
$this->log->init($config['log']);
$this->session->setConfig($config['session']);
$this->debug->setConfig($config['trace']);
$this->cache->init($config['cache'], true);
// 加载当前模块语言包
$this->lang->load($this->appPath . $module . DIRECTORY_SEPARATOR . 'lang' . DIRECTORY_SEPARATOR . $this->request->langset() . '.php');
// 模块请求缓存检查
$this->checkRequestCache(
$config['app']['request_cache'],
$config['app']['request_cache_expire'],
$config['app']['request_cache_except']
);
}
/**
* 执行应用程序
* @access public
* @return Response
* @throws Exception
*/
public function run()
{
try {
// 初始化应用
$this->initialize();
// 监听app_init
$this->hook->listen('app_init');
if ($this->bindModule) {
// 模块/控制器绑定
$this->route->bind($this->bindModule);
} elseif ($this->config('app.auto_bind_module')) {
// 入口自动绑定
$name = pathinfo($this->request->baseFile(), PATHINFO_FILENAME);
if ($name && 'index' != $name && is_dir($this->appPath . $name)) {
$this->route->bind($name);
}
}
// 监听app_dispatch
$this->hook->listen('app_dispatch');
$dispatch = $this->dispatch;
if (empty($dispatch)) {
// 路由检测
$dispatch = $this->routeCheck()->init();
}
// 记录当前调度信息
$this->request->dispatch($dispatch);
// 记录路由和请求信息
if ($this->appDebug) {
$this->log('[ ROUTE ] ' . var_export($this->request->routeInfo(), true));
$this->log('[ HEADER ] ' . var_export($this->request->header(), true));
$this->log('[ PARAM ] ' . var_export($this->request->param(), true));
}
// 监听app_begin
$this->hook->listen('app_begin');
// 请求缓存检查
$this->checkRequestCache(
$this->config('request_cache'),
$this->config('request_cache_expire'),
$this->config('request_cache_except')
);
$data = null;
} catch (HttpResponseException $exception) {
$dispatch = null;
$data = $exception->getResponse();
}
$this->middleware->add(function (Request $request, $next) use ($dispatch, $data) {
return is_null($data) ? $dispatch->run() : $data;
});
$response = $this->middleware->dispatch($this->request);
// 监听app_end
$this->hook->listen('app_end', $response);
return $response;
}
protected function getRouteCacheKey()
{
if ($this->config->get('route_check_cache_key')) {
$closure = $this->config->get('route_check_cache_key');
$routeKey = $closure($this->request);
} else {
$routeKey = md5($this->request->baseUrl(true) . ':' . $this->request->method());
}
return $routeKey;
}
protected function loadLangPack()
{
// 读取默认语言
$this->lang->range($this->config('app.default_lang'));
if ($this->config('app.lang_switch_on')) {
// 开启多语言机制 检测当前语言
$this->lang->detect();
}
$this->request->setLangset($this->lang->range());
// 加载系统语言包
$this->lang->load([
$this->thinkPath . 'lang' . DIRECTORY_SEPARATOR . $this->request->langset() . '.php',
$this->appPath . 'lang' . DIRECTORY_SEPARATOR . $this->request->langset() . '.php',
]);
}
/**
* 设置当前地址的请求缓存
* @access public
* @param string $key 缓存标识,支持变量规则 ,例如 item/:name/:id
* @param mixed $expire 缓存有效期
* @param array $except 缓存排除
* @param string $tag 缓存标签
* @return void
*/
public function checkRequestCache($key, $expire = null, $except = [], $tag = null)
{
$cache = $this->request->cache($key, $expire, $except, $tag);
if ($cache) {
$this->setResponseCache($cache);
}
}
public function setResponseCache($cache)
{
list($key, $expire, $tag) = $cache;
if (strtotime($this->request->server('HTTP_IF_MODIFIED_SINCE')) + $expire > $this->request->server('REQUEST_TIME')) {
// 读取缓存
$response = Response::create()->code(304);
throw new HttpResponseException($response);
} elseif ($this->cache->has($key)) {
list($content, $header) = $this->cache->get($key);
$response = Response::create($content)->header($header);
throw new HttpResponseException($response);
}
}
/**
* 设置当前请求的调度信息
* @access public
* @param Dispatch $dispatch 调度信息
* @return $this
*/
public function dispatch(Dispatch $dispatch)
{
$this->dispatch = $dispatch;
return $this;
}
/**
* 记录调试信息
* @access public
* @param mixed $msg 调试信息
* @param string $type 信息类型
* @return void
*/
public function log($msg, $type = 'info')
{
$this->appDebug && $this->log->record($msg, $type);
}
/**
* 获取配置参数 为空则获取所有配置
* @access public
* @param string $name 配置参数名(支持二级配置 .号分割)
* @return mixed
*/
public function config($name = '')
{
return $this->config->get($name);
}
/**
* 路由初始化 导入路由定义规则
* @access public
* @return void
*/
public function routeInit()
{
// 路由检测
if (is_dir($this->routePath)) {
$files = glob($this->routePath . '*.php');
foreach ($files as $file) {
$rules = include $file;
if (is_array($rules)) {
$this->route->import($rules);
}
}
}
if ($this->route->config('route_annotation')) {
// 自动生成路由定义
if ($this->appDebug) {
$suffix = $this->route->config('controller_suffix') || $this->route->config('class_suffix');
$this->build->buildRoute($suffix);
}
$filename = $this->runtimePath . 'build_route.php';
if (is_file($filename)) {
include $filename;
}
}
}
/**
* URL路由检测根据PATH_INFO)
* @access public
* @return Dispatch
*/
public function routeCheck()
{
// 检测路由缓存
if (!$this->appDebug && $this->config->get('route_check_cache')) {
$routeKey = $this->getRouteCacheKey();
$option = $this->config->get('route_cache_option');
if ($option && $this->cache->connect($option)->has($routeKey)) {
return $this->cache->connect($option)->get($routeKey);
} elseif ($this->cache->has($routeKey)) {
return $this->cache->get($routeKey);
}
}
// 获取应用调度信息
$path = $this->request->path();
// 是否强制路由模式
$must = !is_null($this->routeMust) ? $this->routeMust : $this->route->config('url_route_must');
// 路由检测 返回一个Dispatch对象
$dispatch = $this->route->check($path, $must);
if (!empty($routeKey)) {
try {
if ($option) {
$this->cache->connect($option)->tag('route_cache')->set($routeKey, $dispatch);
} else {
$this->cache->tag('route_cache')->set($routeKey, $dispatch);
}
} catch (\Exception $e) {
// 存在闭包的时候缓存无效
}
}
return $dispatch;
}
/**
* 设置应用的路由检测机制
* @access public
* @param bool $must 是否强制检测路由
* @return $this
*/
public function routeMust($must = false)
{
$this->routeMust = $must;
return $this;
}
/**
* 解析模块和类名
* @access protected
* @param string $name 资源地址
* @param string $layer 验证层名称
* @param bool $appendSuffix 是否添加类名后缀
* @return array
*/
protected function parseModuleAndClass($name, $layer, $appendSuffix)
{
if (false !== strpos($name, '\\')) {
$class = $name;
$module = $this->request->module();
} else {
if (strpos($name, '/')) {
list($module, $name) = explode('/', $name, 2);
} else {
$module = $this->request->module();
}
$class = $this->parseClass($module, $layer, $name, $appendSuffix);
}
return [$module, $class];
}
/**
* 实例化应用类库
* @access public
* @param string $name 类名称
* @param string $layer 业务层名称
* @param bool $appendSuffix 是否添加类名后缀
* @param string $common 公共模块名
* @return object
* @throws ClassNotFoundException
*/
public function create($name, $layer, $appendSuffix = false, $common = 'common')
{
$guid = $name . $layer;
if ($this->__isset($guid)) {
return $this->__get($guid);
}
list($module, $class) = $this->parseModuleAndClass($name, $layer, $appendSuffix);
if (class_exists($class)) {
$object = $this->__get($class);
} else {
$class = str_replace('\\' . $module . '\\', '\\' . $common . '\\', $class);
if (class_exists($class)) {
$object = $this->__get($class);
} else {
throw new ClassNotFoundException('class not exists:' . $class, $class);
}
}
$this->__set($guid, $class);
return $object;
}
/**
* 实例化(分层)模型
* @access public
* @param string $name Model名称
* @param string $layer 业务层名称
* @param bool $appendSuffix 是否添加类名后缀
* @param string $common 公共模块名
* @return Model
* @throws ClassNotFoundException
*/
public function model($name = '', $layer = 'model', $appendSuffix = false, $common = 'common')
{
return $this->create($name, $layer, $appendSuffix, $common);
}
/**
* 实例化(分层)控制器 格式:[模块名/]控制器名
* @access public
* @param string $name 资源地址
* @param string $layer 控制层名称
* @param bool $appendSuffix 是否添加类名后缀
* @param string $empty 空控制器名称
* @return object
* @throws ClassNotFoundException
*/
public function controller($name, $layer = 'controller', $appendSuffix = false, $empty = '')
{
list($module, $class) = $this->parseModuleAndClass($name, $layer, $appendSuffix);
if (class_exists($class)) {
return $this->make($class, true);
} elseif ($empty && class_exists($emptyClass = $this->parseClass($module, $layer, $empty, $appendSuffix))) {
return $this->make($emptyClass, true);
}
throw new ClassNotFoundException('class not exists:' . $class, $class);
}
/**
* 实例化验证类 格式:[模块名/]验证器名
* @access public
* @param string $name 资源地址
* @param string $layer 验证层名称
* @param bool $appendSuffix 是否添加类名后缀
* @param string $common 公共模块名
* @return Validate
* @throws ClassNotFoundException
*/
public function validate($name = '', $layer = 'validate', $appendSuffix = false, $common = 'common')
{
$name = $name ?: $this->config('default_validate');
if (empty($name)) {
return new Validate;
}
return $this->create($name, $layer, $appendSuffix, $common);
}
/**
* 数据库初始化
* @access public
* @param mixed $config 数据库配置
* @param bool|string $name 连接标识 true 强制重新连接
* @return \think\db\Query
*/
public function db($config = [], $name = false)
{
return Db::connect($config, $name);
}
/**
* 远程调用模块的操作方法 参数格式 [模块/控制器/]操作
* @access public
* @param string $url 调用地址
* @param string|array $vars 调用参数 支持字符串和数组
* @param string $layer 要调用的控制层名称
* @param bool $appendSuffix 是否添加类名后缀
* @return mixed
* @throws ClassNotFoundException
*/
public function action($url, $vars = [], $layer = 'controller', $appendSuffix = false)
{
$info = pathinfo($url);
$action = $info['basename'];
$module = '.' != $info['dirname'] ? $info['dirname'] : $this->request->controller();
$class = $this->controller($module, $layer, $appendSuffix);
if (is_scalar($vars)) {
if (strpos($vars, '=')) {
parse_str($vars, $vars);
} else {
$vars = [$vars];
}
}
return $this->invokeMethod([$class, $action . $this->config('action_suffix')], $vars);
}
/**
* 解析应用类的类名
* @access public
* @param string $module 模块名
* @param string $layer 层名 controller model ...
* @param string $name 类名
* @param bool $appendSuffix
* @return string
*/
public function parseClass($module, $layer, $name, $appendSuffix = false)
{
$name = str_replace(['/', '.'], '\\', $name);
$array = explode('\\', $name);
$class = Loader::parseName(array_pop($array), 1) . ($this->suffix || $appendSuffix ? ucfirst($layer) : '');
$path = $array ? implode('\\', $array) . '\\' : '';
return $this->namespace . '\\' . ($module ? $module . '\\' : '') . $layer . '\\' . $path . $class;
}
/**
* 获取框架版本
* @access public
* @return string
*/
public function version()
{
return static::VERSION;
}
/**
* 是否为调试模式
* @access public
* @return bool
*/
public function isDebug()
{
return $this->appDebug;
}
/**
* 获取模块路径
* @access public
* @return string
*/
public function getModulePath()
{
return $this->modulePath;
}
/**
* 设置模块路径
* @access public
* @param string $path 路径
* @return void
*/
public function setModulePath($path)
{
$this->modulePath = $path;
$this->env->set('module_path', $path);
}
/**
* 获取应用根目录
* @access public
* @return string
*/
public function getRootPath()
{
return $this->rootPath;
}
/**
* 获取应用类库目录
* @access public
* @return string
*/
public function getAppPath()
{
if (is_null($this->appPath)) {
$this->appPath = Loader::getRootPath() . 'application' . DIRECTORY_SEPARATOR;
}
return $this->appPath;
}
/**
* 获取应用运行时目录
* @access public
* @return string
*/
public function getRuntimePath()
{
return $this->runtimePath;
}
/**
* 获取核心框架目录
* @access public
* @return string
*/
public function getThinkPath()
{
return $this->thinkPath;
}
/**
* 获取路由目录
* @access public
* @return string
*/
public function getRoutePath()
{
return $this->routePath;
}
/**
* 获取应用配置目录
* @access public
* @return string
*/
public function getConfigPath()
{
return $this->configPath;
}
/**
* 获取配置后缀
* @access public
* @return string
*/
public function getConfigExt()
{
return $this->configExt;
}
/**
* 获取应用类库命名空间
* @access public
* @return string
*/
public function getNamespace()
{
return $this->namespace;
}
/**
* 设置应用类库命名空间
* @access public
* @param string $namespace 命名空间名称
* @return $this
*/
public function setNamespace($namespace)
{
$this->namespace = $namespace;
return $this;
}
/**
* 是否启用类库后缀
* @access public
* @return bool
*/
public function getSuffix()
{
return $this->suffix;
}
/**
* 获取应用开启时间
* @access public
* @return float
*/
public function getBeginTime()
{
return $this->beginTime;
}
/**
* 获取应用初始内存占用
* @access public
* @return integer
*/
public function getBeginMem()
{
return $this->beginMem;
}
}

View File

@@ -0,0 +1,415 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
class Build
{
/**
* 应用对象
* @var App
*/
protected $app;
/**
* 应用目录
* @var string
*/
protected $basePath;
public function __construct(App $app)
{
$this->app = $app;
$this->basePath = $this->app->getAppPath();
}
/**
* 根据传入的build资料创建目录和文件
* @access public
* @param array $build build列表
* @param string $namespace 应用类库命名空间
* @param bool $suffix 类库后缀
* @return void
*/
public function run(array $build = [], $namespace = 'app', $suffix = false)
{
// 锁定
$lockfile = $this->basePath . 'build.lock';
if (is_writable($lockfile)) {
return;
} elseif (!touch($lockfile)) {
throw new Exception('应用目录[' . $this->basePath . ']不可写,目录无法自动生成!<BR>请手动生成项目目录~', 10006);
}
foreach ($build as $module => $list) {
if ('__dir__' == $module) {
// 创建目录列表
$this->buildDir($list);
} elseif ('__file__' == $module) {
// 创建文件列表
$this->buildFile($list);
} else {
// 创建模块
$this->module($module, $list, $namespace, $suffix);
}
}
// 解除锁定
unlink($lockfile);
}
/**
* 创建目录
* @access protected
* @param array $list 目录列表
* @return void
*/
protected function buildDir($list)
{
foreach ($list as $dir) {
$this->checkDirBuild($this->basePath . $dir);
}
}
/**
* 创建文件
* @access protected
* @param array $list 文件列表
* @return void
*/
protected function buildFile($list)
{
foreach ($list as $file) {
if (!is_dir($this->basePath . dirname($file))) {
// 创建目录
mkdir($this->basePath . dirname($file), 0755, true);
}
if (!is_file($this->basePath . $file)) {
file_put_contents($this->basePath . $file, 'php' == pathinfo($file, PATHINFO_EXTENSION) ? "<?php\n" : '');
}
}
}
/**
* 创建模块
* @access public
* @param string $module 模块名
* @param array $list build列表
* @param string $namespace 应用类库命名空间
* @param bool $suffix 类库后缀
* @return void
*/
public function module($module = '', $list = [], $namespace = 'app', $suffix = false)
{
$module = $module ? $module : '';
if (!is_dir($this->basePath . $module)) {
// 创建模块目录
mkdir($this->basePath . $module);
}
if (basename($this->app->getRuntimePath()) != $module) {
// 创建配置文件和公共文件
$this->buildCommon($module);
// 创建模块的默认页面
$this->buildHello($module, $namespace, $suffix);
}
if (empty($list)) {
// 创建默认的模块目录和文件
$list = [
'__file__' => ['common.php'],
'__dir__' => ['controller', 'model', 'view', 'config'],
];
}
// 创建子目录和文件
foreach ($list as $path => $file) {
$modulePath = $this->basePath . $module . DIRECTORY_SEPARATOR;
if ('__dir__' == $path) {
// 生成子目录
foreach ($file as $dir) {
$this->checkDirBuild($modulePath . $dir);
}
} elseif ('__file__' == $path) {
// 生成(空白)文件
foreach ($file as $name) {
if (!is_file($modulePath . $name)) {
file_put_contents($modulePath . $name, 'php' == pathinfo($name, PATHINFO_EXTENSION) ? "<?php\n" : '');
}
}
} else {
// 生成相关MVC文件
foreach ($file as $val) {
$val = trim($val);
$filename = $modulePath . $path . DIRECTORY_SEPARATOR . $val . ($suffix ? ucfirst($path) : '') . '.php';
$space = $namespace . '\\' . ($module ? $module . '\\' : '') . $path;
$class = $val . ($suffix ? ucfirst($path) : '');
switch ($path) {
case 'controller': // 控制器
$content = "<?php\nnamespace {$space};\n\nclass {$class}\n{\n\n}";
break;
case 'model': // 模型
$content = "<?php\nnamespace {$space};\n\nuse think\Model;\n\nclass {$class} extends Model\n{\n\n}";
break;
case 'view': // 视图
$filename = $modulePath . $path . DIRECTORY_SEPARATOR . $val . '.html';
$this->checkDirBuild(dirname($filename));
$content = '';
break;
default:
// 其他文件
$content = "<?php\nnamespace {$space};\n\nclass {$class}\n{\n\n}";
}
if (!is_file($filename)) {
file_put_contents($filename, $content);
}
}
}
}
}
/**
* 根据注释自动生成路由规则
* @access public
* @param bool $suffix 类库后缀
* @param string $layer 控制器层目录名
* @return string
*/
public function buildRoute($suffix = false, $layer = '')
{
$namespace = $this->app->getNameSpace();
$content = '<?php ' . PHP_EOL . '//根据 Annotation 自动生成的路由规则';
if (!$layer) {
$layer = $this->app->config('app.url_controller_layer');
}
if ($this->app->config('app.app_multi_module')) {
$modules = glob($this->basePath . '*', GLOB_ONLYDIR);
foreach ($modules as $module) {
$module = basename($module);
if (in_array($module, $this->app->config('app.deny_module_list'))) {
continue;
}
$path = $this->basePath . $module . DIRECTORY_SEPARATOR . $layer . DIRECTORY_SEPARATOR;
$content .= $this->buildDirRoute($path, $namespace, $module, $suffix, $layer);
}
} else {
$path = $this->basePath . $layer . DIRECTORY_SEPARATOR;
$content .= $this->buildDirRoute($path, $namespace, '', $suffix, $layer);
}
$filename = $this->app->getRuntimePath() . 'build_route.php';
file_put_contents($filename, $content);
return $filename;
}
/**
* 生成子目录控制器类的路由规则
* @access protected
* @param string $path 控制器目录
* @param string $namespace 应用命名空间
* @param string $module 模块
* @param bool $suffix 类库后缀
* @param string $layer 控制器层目录名
* @return string
*/
protected function buildDirRoute($path, $namespace, $module, $suffix, $layer)
{
$content = '';
$controllers = glob($path . '*.php');
foreach ($controllers as $controller) {
$controller = basename($controller, '.php');
$class = new \ReflectionClass($namespace . '\\' . ($module ? $module . '\\' : '') . $layer . '\\' . $controller);
if (strpos($layer, '\\')) {
// 多级控制器
$level = str_replace(DIRECTORY_SEPARATOR, '.', substr($layer, 11));
$controller = $level . '.' . $controller;
$length = strlen(strstr($layer, '\\', true));
} else {
$length = strlen($layer);
}
if ($suffix) {
$controller = substr($controller, 0, -$length);
}
$content .= $this->getControllerRoute($class, $module, $controller);
}
$subDir = glob($path . '*', GLOB_ONLYDIR);
foreach ($subDir as $dir) {
$content .= $this->buildDirRoute($dir . DIRECTORY_SEPARATOR, $namespace, $module, $suffix, $layer . '\\' . basename($dir));
}
return $content;
}
/**
* 生成控制器类的路由规则
* @access protected
* @param string $class 控制器完整类名
* @param string $module 模块名
* @param string $controller 控制器名
* @return string
*/
protected function getControllerRoute($class, $module, $controller)
{
$content = '';
$comment = $class->getDocComment();
if (false !== strpos($comment, '@route(')) {
$comment = $this->parseRouteComment($comment);
$route = ($module ? $module . '/' : '') . $controller;
$comment = preg_replace('/route\(\s?([\'\"][\-\_\/\:\<\>\?\$\[\]\w]+[\'\"])\s?\)/is', 'Route::resource(\1,\'' . $route . '\')', $comment);
$content .= PHP_EOL . $comment;
} elseif (false !== strpos($comment, '@alias(')) {
$comment = $this->parseRouteComment($comment, '@alias(');
$route = ($module ? $module . '/' : '') . $controller;
$comment = preg_replace('/alias\(\s?([\'\"][\-\_\/\w]+[\'\"])\s?\)/is', 'Route::alias(\1,\'' . $route . '\')', $comment);
$content .= PHP_EOL . $comment;
}
$methods = $class->getMethods(\ReflectionMethod::IS_PUBLIC);
foreach ($methods as $method) {
$comment = $this->getMethodRouteComment($module, $controller, $method);
if ($comment) {
$content .= PHP_EOL . $comment;
}
}
return $content;
}
/**
* 解析路由注释
* @access protected
* @param string $comment
* @param string $tag
* @return string
*/
protected function parseRouteComment($comment, $tag = '@route(')
{
$comment = substr($comment, 3, -2);
$comment = explode(PHP_EOL, substr(strstr(trim($comment), $tag), 1));
$comment = array_map(function ($item) {return trim(trim($item), ' \t*');}, $comment);
if (count($comment) > 1) {
$key = array_search('', $comment);
$comment = array_slice($comment, 0, false === $key ? 1 : $key);
}
$comment = implode(PHP_EOL . "\t", $comment) . ';';
if (strpos($comment, '{')) {
$comment = preg_replace_callback('/\{\s?.*?\s?\}/s', function ($matches) {
return false !== strpos($matches[0], '"') ? '[' . substr(var_export(json_decode($matches[0], true), true), 7, -1) . ']' : $matches[0];
}, $comment);
}
return $comment;
}
/**
* 获取方法的路由注释
* @access protected
* @param string $module 模块
* @param string $controller 控制器名
* @param \ReflectMethod $reflectMethod
* @return string|void
*/
protected function getMethodRouteComment($module, $controller, $reflectMethod)
{
$comment = $reflectMethod->getDocComment();
if (false !== strpos($comment, '@route(')) {
$comment = $this->parseRouteComment($comment);
$action = $reflectMethod->getName();
if ($suffix = $this->app->config('app.action_suffix')) {
$action = substr($action, 0, -strlen($suffix));
}
$route = ($module ? $module . '/' : '') . $controller . '/' . $action;
$comment = preg_replace('/route\s?\(\s?([\'\"][\-\_\/\:\<\>\?\$\[\]\w]+[\'\"])\s?\,?\s?[\'\"]?(\w+?)[\'\"]?\s?\)/is', 'Route::\2(\1,\'' . $route . '\')', $comment);
$comment = preg_replace('/route\s?\(\s?([\'\"][\-\_\/\:\<\>\?\$\[\]\w]+[\'\"])\s?\)/is', 'Route::rule(\1,\'' . $route . '\')', $comment);
return $comment;
}
}
/**
* 创建模块的欢迎页面
* @access protected
* @param string $module 模块名
* @param string $namespace 应用类库命名空间
* @param bool $suffix 类库后缀
* @return void
*/
protected function buildHello($module, $namespace, $suffix = false)
{
$filename = $this->basePath . ($module ? $module . DIRECTORY_SEPARATOR : '') . 'controller' . DIRECTORY_SEPARATOR . 'Index' . ($suffix ? 'Controller' : '') . '.php';
if (!is_file($filename)) {
$content = file_get_contents($this->app->getThinkPath() . 'tpl' . DIRECTORY_SEPARATOR . 'default_index.tpl');
$content = str_replace(['{$app}', '{$module}', '{layer}', '{$suffix}'], [$namespace, $module ? $module . '\\' : '', 'controller', $suffix ? 'Controller' : ''], $content);
$this->checkDirBuild(dirname($filename));
file_put_contents($filename, $content);
}
}
/**
* 创建模块的公共文件
* @access protected
* @param string $module 模块名
* @return void
*/
protected function buildCommon($module)
{
$filename = $this->app->getConfigPath() . ($module ? $module . DIRECTORY_SEPARATOR : '') . 'app.php';
$this->checkDirBuild(dirname($filename));
if (!is_file($filename)) {
file_put_contents($filename, "<?php\n//配置文件\nreturn [\n\n];");
}
$filename = $this->basePath . ($module ? $module . DIRECTORY_SEPARATOR : '') . 'common.php';
if (!is_file($filename)) {
file_put_contents($filename, "<?php\n");
}
}
/**
* 创建目录
* @access protected
* @param string $dirname 目录名称
* @return void
*/
protected function checkDirBuild($dirname)
{
if (!is_dir($dirname)) {
mkdir($dirname, 0755, true);
}
}
}

View File

@@ -0,0 +1,133 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
use think\cache\Driver;
/**
* Class Cache
*
* @package think
*
* @mixin Driver
* @mixin \think\cache\driver\File
*/
class Cache
{
/**
* 缓存实例
* @var array
*/
protected $instance = [];
/**
* 缓存配置
* @var array
*/
protected $config = [];
/**
* 操作句柄
* @var object
*/
protected $handler;
public function __construct(array $config = [])
{
$this->config = $config;
$this->init($config);
}
/**
* 连接缓存
* @access public
* @param array $options 配置数组
* @param bool|string $name 缓存连接标识 true 强制重新连接
* @return Driver
*/
public function connect(array $options = [], $name = false)
{
if (false === $name) {
$name = md5(serialize($options));
}
if (true === $name || !isset($this->instance[$name])) {
$type = !empty($options['type']) ? $options['type'] : 'File';
if (true === $name) {
$name = md5(serialize($options));
}
$this->instance[$name] = Loader::factory($type, '\\think\\cache\\driver\\', $options);
}
return $this->instance[$name];
}
/**
* 自动初始化缓存
* @access public
* @param array $options 配置数组
* @param bool $force 强制更新
* @return Driver
*/
public function init(array $options = [], $force = false)
{
if (is_null($this->handler) || $force) {
if ('complex' == $options['type']) {
$default = $options['default'];
$options = isset($options[$default['type']]) ? $options[$default['type']] : $default;
}
$this->handler = $this->connect($options);
}
return $this->handler;
}
public static function __make(Config $config)
{
return new static($config->pull('cache'));
}
public function getConfig()
{
return $this->config;
}
public function setConfig(array $config)
{
$this->config = array_merge($this->config, $config);
}
/**
* 切换缓存类型 需要配置 cache.type 为 complex
* @access public
* @param string $name 缓存标识
* @return Driver
*/
public function store($name = '')
{
if ('' !== $name && 'complex' == $this->config['type']) {
return $this->connect($this->config[$name], strtolower($name));
}
return $this->init();
}
public function __call($method, $args)
{
return call_user_func_array([$this->init(), $method], $args);
}
}

View File

@@ -0,0 +1,552 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: zhangyajun <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think;
use ArrayAccess;
use ArrayIterator;
use Countable;
use IteratorAggregate;
use JsonSerializable;
class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable
{
/**
* 数据集数据
* @var array
*/
protected $items = [];
public function __construct($items = [])
{
$this->items = $this->convertToArray($items);
}
public static function make($items = [])
{
return new static($items);
}
/**
* 是否为空
* @access public
* @return bool
*/
public function isEmpty()
{
return empty($this->items);
}
public function toArray()
{
return array_map(function ($value) {
return ($value instanceof Model || $value instanceof self) ? $value->toArray() : $value;
}, $this->items);
}
public function all()
{
return $this->items;
}
/**
* 合并数组
*
* @access public
* @param mixed $items
* @return static
*/
public function merge($items)
{
return new static(array_merge($this->items, $this->convertToArray($items)));
}
/**
* 交换数组中的键和值
*
* @access public
* @return static
*/
public function flip()
{
return new static(array_flip($this->items));
}
/**
* 按指定键整理数据
*
* @access public
* @param mixed $items 数据
* @param string $indexKey 键名
* @return array
*/
public function dictionary($items = null, &$indexKey = null)
{
if ($items instanceof self || $items instanceof Paginator) {
$items = $items->all();
}
$items = is_null($items) ? $this->items : $items;
if ($items && empty($indexKey)) {
$indexKey = is_array($items[0]) ? 'id' : $items[0]->getPk();
}
if (isset($indexKey) && is_string($indexKey)) {
return array_column($items, null, $indexKey);
}
return $items;
}
/**
* 比较数组,返回差集
*
* @access public
* @param mixed $items 数据
* @param string $indexKey 指定比较的键名
* @return static
*/
public function diff($items, $indexKey = null)
{
if ($this->isEmpty() || is_scalar($this->items[0])) {
return new static(array_diff($this->items, $this->convertToArray($items)));
}
$diff = [];
$dictionary = $this->dictionary($items, $indexKey);
if (is_string($indexKey)) {
foreach ($this->items as $item) {
if (!isset($dictionary[$item[$indexKey]])) {
$diff[] = $item;
}
}
}
return new static($diff);
}
/**
* 比较数组,返回交集
*
* @access public
* @param mixed $items 数据
* @param string $indexKey 指定比较的键名
* @return static
*/
public function intersect($items, $indexKey = null)
{
if ($this->isEmpty() || is_scalar($this->items[0])) {
return new static(array_diff($this->items, $this->convertToArray($items)));
}
$intersect = [];
$dictionary = $this->dictionary($items, $indexKey);
if (is_string($indexKey)) {
foreach ($this->items as $item) {
if (isset($dictionary[$item[$indexKey]])) {
$intersect[] = $item;
}
}
}
return new static($intersect);
}
/**
* 返回数组中所有的键名
*
* @access public
* @return array
*/
public function keys()
{
$current = current($this->items);
if (is_scalar($current)) {
$array = $this->items;
} elseif (is_array($current)) {
$array = $current;
} else {
$array = $current->toArray();
}
return array_keys($array);
}
/**
* 删除数组的最后一个元素(出栈)
*
* @access public
* @return mixed
*/
public function pop()
{
return array_pop($this->items);
}
/**
* 通过使用用户自定义函数,以字符串返回数组
*
* @access public
* @param callable $callback
* @param mixed $initial
* @return mixed
*/
public function reduce(callable $callback, $initial = null)
{
return array_reduce($this->items, $callback, $initial);
}
/**
* 以相反的顺序返回数组。
*
* @access public
* @return static
*/
public function reverse()
{
return new static(array_reverse($this->items));
}
/**
* 删除数组中首个元素,并返回被删除元素的值
*
* @access public
* @return mixed
*/
public function shift()
{
return array_shift($this->items);
}
/**
* 在数组结尾插入一个元素
* @access public
* @param mixed $value
* @param mixed $key
* @return void
*/
public function push($value, $key = null)
{
if (is_null($key)) {
$this->items[] = $value;
} else {
$this->items[$key] = $value;
}
}
/**
* 把一个数组分割为新的数组块.
*
* @access public
* @param int $size
* @param bool $preserveKeys
* @return static
*/
public function chunk($size, $preserveKeys = false)
{
$chunks = [];
foreach (array_chunk($this->items, $size, $preserveKeys) as $chunk) {
$chunks[] = new static($chunk);
}
return new static($chunks);
}
/**
* 在数组开头插入一个元素
* @access public
* @param mixed $value
* @param mixed $key
* @return void
*/
public function unshift($value, $key = null)
{
if (is_null($key)) {
array_unshift($this->items, $value);
} else {
$this->items = [$key => $value] + $this->items;
}
}
/**
* 给每个元素执行个回调
*
* @access public
* @param callable $callback
* @return $this
*/
public function each(callable $callback)
{
foreach ($this->items as $key => $item) {
$result = $callback($item, $key);
if (false === $result) {
break;
} elseif (!is_object($item)) {
$this->items[$key] = $result;
}
}
return $this;
}
/**
* 用回调函数处理数组中的元素
* @access public
* @param callable|null $callback
* @return static
*/
public function map(callable $callback)
{
return new static(array_map($callback, $this->items));
}
/**
* 用回调函数过滤数组中的元素
* @access public
* @param callable|null $callback
* @return static
*/
public function filter(callable $callback = null)
{
if ($callback) {
return new static(array_filter($this->items, $callback));
}
return new static(array_filter($this->items));
}
/**
* 根据字段条件过滤数组中的元素
* @access public
* @param string $field 字段名
* @param mixed $operator 操作符
* @param mixed $value 数据
* @return static
*/
public function where($field, $operator, $value = null)
{
if (is_null($value)) {
$value = $operator;
$operator = '=';
}
return $this->filter(function ($data) use ($field, $operator, $value) {
if (strpos($field, '.')) {
list($field, $relation) = explode('.', $field);
$result = isset($data[$field][$relation]) ? $data[$field][$relation] : null;
} else {
$result = isset($data[$field]) ? $data[$field] : null;
}
switch (strtolower($operator)) {
case '===':
return $result === $value;
case '!==':
return $result !== $value;
case '!=':
case '<>':
return $result != $value;
case '>':
return $result > $value;
case '>=':
return $result >= $value;
case '<':
return $result < $value;
case '<=':
return $result <= $value;
case 'like':
return is_string($result) && false !== strpos($result, $value);
case 'not like':
return is_string($result) && false === strpos($result, $value);
case 'in':
return is_scalar($result) && in_array($result, $value, true);
case 'not in':
return is_scalar($result) && !in_array($result, $value, true);
case 'between':
list($min, $max) = is_string($value) ? explode(',', $value) : $value;
return is_scalar($result) && $result >= $min && $result <= $max;
case 'not between':
list($min, $max) = is_string($value) ? explode(',', $value) : $value;
return is_scalar($result) && $result > $max || $result < $min;
case '==':
case '=':
default:
return $result == $value;
}
});
}
/**
* 返回数据中指定的一列
* @access public
* @param mixed $columnKey 键名
* @param mixed $indexKey 作为索引值的列
* @return array
*/
public function column($columnKey, $indexKey = null)
{
return array_column($this->toArray(), $columnKey, $indexKey);
}
/**
* 对数组排序
*
* @access public
* @param callable|null $callback
* @return static
*/
public function sort(callable $callback = null)
{
$items = $this->items;
$callback = $callback ?: function ($a, $b) {
return $a == $b ? 0 : (($a < $b) ? -1 : 1);
};
uasort($items, $callback);
return new static($items);
}
/**
* 指定字段排序
* @access public
* @param string $field 排序字段
* @param string $order 排序
* @param bool $intSort 是否为数字排序
* @return $this
*/
public function order($field, $order = null, $intSort = true)
{
return $this->sort(function ($a, $b) use ($field, $order, $intSort) {
$fieldA = isset($a[$field]) ? $a[$field] : null;
$fieldB = isset($b[$field]) ? $b[$field] : null;
if ($intSort) {
return 'desc' == strtolower($order) ? $fieldB >= $fieldA : $fieldA >= $fieldB;
} else {
return 'desc' == strtolower($order) ? strcmp($fieldB, $fieldA) : strcmp($fieldA, $fieldB);
}
});
}
/**
* 将数组打乱
*
* @access public
* @return static
*/
public function shuffle()
{
$items = $this->items;
shuffle($items);
return new static($items);
}
/**
* 截取数组
*
* @access public
* @param int $offset
* @param int $length
* @param bool $preserveKeys
* @return static
*/
public function slice($offset, $length = null, $preserveKeys = false)
{
return new static(array_slice($this->items, $offset, $length, $preserveKeys));
}
// ArrayAccess
public function offsetExists($offset)
{
return array_key_exists($offset, $this->items);
}
public function offsetGet($offset)
{
return $this->items[$offset];
}
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
$this->items[] = $value;
} else {
$this->items[$offset] = $value;
}
}
public function offsetUnset($offset)
{
unset($this->items[$offset]);
}
//Countable
public function count()
{
return count($this->items);
}
//IteratorAggregate
public function getIterator()
{
return new ArrayIterator($this->items);
}
//JsonSerializable
public function jsonSerialize()
{
return $this->toArray();
}
/**
* 转换当前数据集为JSON字符串
* @access public
* @param integer $options json参数
* @return string
*/
public function toJson($options = JSON_UNESCAPED_UNICODE)
{
return json_encode($this->toArray(), $options);
}
public function __toString()
{
return $this->toJson();
}
/**
* 转换成数组
*
* @access public
* @param mixed $items
* @return array
*/
protected function convertToArray($items)
{
if ($items instanceof self) {
return $items->all();
}
return (array) $items;
}
}

View File

@@ -0,0 +1,398 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
use Yaconf;
class Config implements \ArrayAccess
{
/**
* 配置参数
* @var array
*/
protected $config = [];
/**
* 配置前缀
* @var string
*/
protected $prefix = 'app';
/**
* 配置文件目录
* @var string
*/
protected $path;
/**
* 配置文件后缀
* @var string
*/
protected $ext;
/**
* 是否支持Yaconf
* @var bool
*/
protected $yaconf;
/**
* 构造方法
* @access public
*/
public function __construct($path = '', $ext = '.php')
{
$this->path = $path;
$this->ext = $ext;
$this->yaconf = class_exists('Yaconf');
}
public static function __make(App $app)
{
$path = $app->getConfigPath();
$ext = $app->getConfigExt();
return new static($path, $ext);
}
/**
* 设置开启Yaconf
* @access public
* @param bool|string $yaconf 是否使用Yaconf
* @return void
*/
public function setYaconf($yaconf)
{
if ($this->yaconf) {
$this->yaconf = $yaconf;
}
}
/**
* 设置配置参数默认前缀
* @access public
* @param string $prefix 前缀
* @return void
*/
public function setDefaultPrefix($prefix)
{
$this->prefix = $prefix;
}
/**
* 解析配置文件或内容
* @access public
* @param string $config 配置文件路径或内容
* @param string $type 配置解析类型
* @param string $name 配置名(如设置即表示二级配置)
* @return mixed
*/
public function parse($config, $type = '', $name = '')
{
if (empty($type)) {
$type = pathinfo($config, PATHINFO_EXTENSION);
}
$object = Loader::factory($type, '\\think\\config\\driver\\', $config);
return $this->set($object->parse(), $name);
}
/**
* 加载配置文件(多种格式)
* @access public
* @param string $file 配置文件名
* @param string $name 一级配置名
* @return mixed
*/
public function load($file, $name = '')
{
if (is_file($file)) {
$filename = $file;
} elseif (is_file($this->path . $file . $this->ext)) {
$filename = $this->path . $file . $this->ext;
}
if (isset($filename)) {
return $this->loadFile($filename, $name);
} elseif ($this->yaconf && Yaconf::has($file)) {
return $this->set(Yaconf::get($file), $name);
}
return $this->config;
}
/**
* 获取实际的yaconf配置参数
* @access protected
* @param string $name 配置参数名
* @return string
*/
protected function getYaconfName($name)
{
if ($this->yaconf && is_string($this->yaconf)) {
return $this->yaconf . '.' . $name;
}
return $name;
}
/**
* 获取yaconf配置
* @access public
* @param string $name 配置参数名
* @param mixed $default 默认值
* @return mixed
*/
public function yaconf($name, $default = null)
{
if ($this->yaconf) {
$yaconfName = $this->getYaconfName($name);
if (Yaconf::has($yaconfName)) {
return Yaconf::get($yaconfName);
}
}
return $default;
}
protected function loadFile($file, $name)
{
$name = strtolower($name);
$type = pathinfo($file, PATHINFO_EXTENSION);
if ('php' == $type) {
return $this->set(include $file, $name);
} elseif ('yaml' == $type && function_exists('yaml_parse_file')) {
return $this->set(yaml_parse_file($file), $name);
}
return $this->parse($file, $type, $name);
}
/**
* 检测配置是否存在
* @access public
* @param string $name 配置参数名(支持多级配置 .号分割)
* @return bool
*/
public function has($name)
{
if (false === strpos($name, '.')) {
$name = $this->prefix . '.' . $name;
}
return !is_null($this->get($name));
}
/**
* 获取一级配置
* @access public
* @param string $name 一级配置名
* @return array
*/
public function pull($name)
{
$name = strtolower($name);
if ($this->yaconf) {
$yaconfName = $this->getYaconfName($name);
if (Yaconf::has($yaconfName)) {
$config = Yaconf::get($yaconfName);
return isset($this->config[$name]) ? array_merge($this->config[$name], $config) : $config;
}
}
return isset($this->config[$name]) ? $this->config[$name] : [];
}
/**
* 获取配置参数 为空则获取所有配置
* @access public
* @param string $name 配置参数名(支持多级配置 .号分割)
* @param mixed $default 默认值
* @return mixed
*/
public function get($name = null, $default = null)
{
if ($name && false === strpos($name, '.')) {
$name = $this->prefix . '.' . $name;
}
// 无参数时获取所有
if (empty($name)) {
return $this->config;
}
if ('.' == substr($name, -1)) {
return $this->pull(substr($name, 0, -1));
}
if ($this->yaconf) {
$yaconfName = $this->getYaconfName($name);
if (Yaconf::has($yaconfName)) {
return Yaconf::get($yaconfName);
}
}
$name = explode('.', $name);
$name[0] = strtolower($name[0]);
$config = $this->config;
// 按.拆分成多维数组进行判断
foreach ($name as $val) {
if (isset($config[$val])) {
$config = $config[$val];
} else {
return $default;
}
}
return $config;
}
/**
* 设置配置参数 name为数组则为批量设置
* @access public
* @param string|array $name 配置参数名(支持三级配置 .号分割)
* @param mixed $value 配置值
* @return mixed
*/
public function set($name, $value = null)
{
if (is_string($name)) {
if (false === strpos($name, '.')) {
$name = $this->prefix . '.' . $name;
}
$name = explode('.', $name, 3);
if (count($name) == 2) {
$this->config[strtolower($name[0])][$name[1]] = $value;
} else {
$this->config[strtolower($name[0])][$name[1]][$name[2]] = $value;
}
return $value;
} elseif (is_array($name)) {
// 批量设置
if (!empty($value)) {
if (isset($this->config[$value])) {
$result = array_merge($this->config[$value], $name);
} else {
$result = $name;
}
$this->config[$value] = $result;
} else {
$result = $this->config = array_merge($this->config, $name);
}
} else {
// 为空直接返回 已有配置
$result = $this->config;
}
return $result;
}
/**
* 移除配置
* @access public
* @param string $name 配置参数名(支持三级配置 .号分割)
* @return void
*/
public function remove($name)
{
if (false === strpos($name, '.')) {
$name = $this->prefix . '.' . $name;
}
$name = explode('.', $name, 3);
if (count($name) == 2) {
unset($this->config[strtolower($name[0])][$name[1]]);
} else {
unset($this->config[strtolower($name[0])][$name[1]][$name[2]]);
}
}
/**
* 重置配置参数
* @access public
* @param string $prefix 配置前缀名
* @return void
*/
public function reset($prefix = '')
{
if ('' === $prefix) {
$this->config = [];
} else {
$this->config[$prefix] = [];
}
}
/**
* 设置配置
* @access public
* @param string $name 参数名
* @param mixed $value 值
*/
public function __set($name, $value)
{
return $this->set($name, $value);
}
/**
* 获取配置参数
* @access public
* @param string $name 参数名
* @return mixed
*/
public function __get($name)
{
return $this->get($name);
}
/**
* 检测是否存在参数
* @access public
* @param string $name 参数名
* @return bool
*/
public function __isset($name)
{
return $this->has($name);
}
// ArrayAccess
public function offsetSet($name, $value)
{
$this->set($name, $value);
}
public function offsetExists($name)
{
return $this->has($name);
}
public function offsetUnset($name)
{
$this->remove($name);
}
public function offsetGet($name)
{
return $this->get($name);
}
}

View File

@@ -0,0 +1,829 @@
<?php
// +----------------------------------------------------------------------
// | TopThink [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2015 http://www.topthink.com All rights reserved.
// +----------------------------------------------------------------------
// | Author: zhangyajun <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think;
use think\console\Command;
use think\console\command\Help as HelpCommand;
use think\console\Input;
use think\console\input\Argument as InputArgument;
use think\console\input\Definition as InputDefinition;
use think\console\input\Option as InputOption;
use think\console\Output;
use think\console\output\driver\Buffer;
class Console
{
private $name;
private $version;
/** @var Command[] */
private $commands = [];
private $wantHelps = false;
private $catchExceptions = true;
private $autoExit = true;
private $definition;
private $defaultCommand;
private static $defaultCommands = [
'help' => "think\\console\\command\\Help",
'list' => "think\\console\\command\\Lists",
'build' => "think\\console\\command\\Build",
'clear' => "think\\console\\command\\Clear",
'make:command' => "think\\console\\command\\make\\Command",
'make:controller' => "think\\console\\command\\make\\Controller",
'make:model' => "think\\console\\command\\make\\Model",
'make:middleware' => "think\\console\\command\\make\\Middleware",
'make:validate' => "think\\console\\command\\make\\Validate",
'optimize:autoload' => "think\\console\\command\\optimize\\Autoload",
'optimize:config' => "think\\console\\command\\optimize\\Config",
'optimize:schema' => "think\\console\\command\\optimize\\Schema",
'optimize:route' => "think\\console\\command\\optimize\\Route",
'run' => "think\\console\\command\\RunServer",
'version' => "think\\console\\command\\Version",
'route:list' => "think\\console\\command\\RouteList",
];
/**
* Console constructor.
* @access public
* @param string $name 名称
* @param string $version 版本
* @param null|string $user 执行用户
*/
public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN', $user = null)
{
$this->name = $name;
$this->version = $version;
if ($user) {
$this->setUser($user);
}
$this->defaultCommand = 'list';
$this->definition = $this->getDefaultInputDefinition();
}
/**
* 设置执行用户
* @param $user
*/
public function setUser($user)
{
if (DIRECTORY_SEPARATOR == '\\') {
return;
}
$user = posix_getpwnam($user);
if ($user) {
posix_setuid($user['uid']);
posix_setgid($user['gid']);
}
}
/**
* 初始化 Console
* @access public
* @param bool $run 是否运行 Console
* @return int|Console
*/
public static function init($run = true)
{
static $console;
if (!$console) {
$config = Container::get('config')->pull('console');
$console = new self($config['name'], $config['version'], $config['user']);
$commands = $console->getDefinedCommands($config);
// 添加指令集
$console->addCommands($commands);
}
if ($run) {
// 运行
return $console->run();
} else {
return $console;
}
}
/**
* @access public
* @param array $config
* @return array
*/
public function getDefinedCommands(array $config = [])
{
$commands = self::$defaultCommands;
if (!empty($config['auto_path']) && is_dir($config['auto_path'])) {
// 自动加载指令类
$files = scandir($config['auto_path']);
if (count($files) > 2) {
$beforeClass = get_declared_classes();
foreach ($files as $file) {
if (pathinfo($file, PATHINFO_EXTENSION) == 'php') {
include $config['auto_path'] . $file;
}
}
$afterClass = get_declared_classes();
$commands = array_merge($commands, array_diff($afterClass, $beforeClass));
}
}
$file = Container::get('env')->get('app_path') . 'command.php';
if (is_file($file)) {
$appCommands = include $file;
if (is_array($appCommands)) {
$commands = array_merge($commands, $appCommands);
}
}
return $commands;
}
/**
* @access public
* @param string $command
* @param array $parameters
* @param string $driver
* @return Output|Buffer
*/
public static function call($command, array $parameters = [], $driver = 'buffer')
{
$console = self::init(false);
array_unshift($parameters, $command);
$input = new Input($parameters);
$output = new Output($driver);
$console->setCatchExceptions(false);
$console->find($command)->run($input, $output);
return $output;
}
/**
* 执行当前的指令
* @access public
* @return int
* @throws \Exception
* @api
*/
public function run()
{
$input = new Input();
$output = new Output();
$this->configureIO($input, $output);
try {
$exitCode = $this->doRun($input, $output);
} catch (\Exception $e) {
if (!$this->catchExceptions) {
throw $e;
}
$output->renderException($e);
$exitCode = $e->getCode();
if (is_numeric($exitCode)) {
$exitCode = (int) $exitCode;
if (0 === $exitCode) {
$exitCode = 1;
}
} else {
$exitCode = 1;
}
}
if ($this->autoExit) {
if ($exitCode > 255) {
$exitCode = 255;
}
exit($exitCode);
}
return $exitCode;
}
/**
* 执行指令
* @access public
* @param Input $input
* @param Output $output
* @return int
*/
public function doRun(Input $input, Output $output)
{
if (true === $input->hasParameterOption(['--version', '-V'])) {
$output->writeln($this->getLongVersion());
return 0;
}
$name = $this->getCommandName($input);
if (true === $input->hasParameterOption(['--help', '-h'])) {
if (!$name) {
$name = 'help';
$input = new Input(['help']);
} else {
$this->wantHelps = true;
}
}
if (!$name) {
$name = $this->defaultCommand;
$input = new Input([$this->defaultCommand]);
}
$command = $this->find($name);
$exitCode = $this->doRunCommand($command, $input, $output);
return $exitCode;
}
/**
* 设置输入参数定义
* @access public
* @param InputDefinition $definition
*/
public function setDefinition(InputDefinition $definition)
{
$this->definition = $definition;
}
/**
* 获取输入参数定义
* @access public
* @return InputDefinition The InputDefinition instance
*/
public function getDefinition()
{
return $this->definition;
}
/**
* Gets the help message.
* @access public
* @return string A help message.
*/
public function getHelp()
{
return $this->getLongVersion();
}
/**
* 是否捕获异常
* @access public
* @param bool $boolean
* @api
*/
public function setCatchExceptions($boolean)
{
$this->catchExceptions = (bool) $boolean;
}
/**
* 是否自动退出
* @access public
* @param bool $boolean
* @api
*/
public function setAutoExit($boolean)
{
$this->autoExit = (bool) $boolean;
}
/**
* 获取名称
* @access public
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* 设置名称
* @access public
* @param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* 获取版本
* @access public
* @return string
* @api
*/
public function getVersion()
{
return $this->version;
}
/**
* 设置版本
* @access public
* @param string $version
*/
public function setVersion($version)
{
$this->version = $version;
}
/**
* 获取完整的版本号
* @access public
* @return string
*/
public function getLongVersion()
{
if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) {
return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
}
return '<info>Console Tool</info>';
}
/**
* 注册一个指令 (便于动态创建指令)
* @access public
* @param string $name 指令名
* @return Command
*/
public function register($name)
{
return $this->add(new Command($name));
}
/**
* 添加指令集
* @access public
* @param array $commands
*/
public function addCommands(array $commands)
{
foreach ($commands as $key => $command) {
if (is_subclass_of($command, "\\think\\console\\Command")) {
// 注册指令
$this->add($command, is_numeric($key) ? '' : $key);
}
}
}
/**
* 注册一个指令(对象)
* @access public
* @param mixed $command 指令对象或者指令类名
* @param string $name 指令名 留空则自动获取
* @return mixed
*/
public function add($command, $name)
{
if ($name) {
$this->commands[$name] = $command;
return;
}
if (is_string($command)) {
$command = new $command();
}
$command->setConsole($this);
if (!$command->isEnabled()) {
$command->setConsole(null);
return;
}
if (null === $command->getDefinition()) {
throw new \LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
}
$this->commands[$command->getName()] = $command;
foreach ($command->getAliases() as $alias) {
$this->commands[$alias] = $command;
}
return $command;
}
/**
* 获取指令
* @access public
* @param string $name 指令名称
* @return Command
* @throws \InvalidArgumentException
*/
public function get($name)
{
if (!isset($this->commands[$name])) {
throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name));
}
$command = $this->commands[$name];
if (is_string($command)) {
$command = new $command();
}
$command->setConsole($this);
if ($this->wantHelps) {
$this->wantHelps = false;
/** @var HelpCommand $helpCommand */
$helpCommand = $this->get('help');
$helpCommand->setCommand($command);
return $helpCommand;
}
return $command;
}
/**
* 某个指令是否存在
* @access public
* @param string $name 指令名称
* @return bool
*/
public function has($name)
{
return isset($this->commands[$name]);
}
/**
* 获取所有的命名空间
* @access public
* @return array
*/
public function getNamespaces()
{
$namespaces = [];
foreach ($this->commands as $name => $command) {
if (is_string($command)) {
$namespaces = array_merge($namespaces, $this->extractAllNamespaces($name));
} else {
$namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
foreach ($command->getAliases() as $alias) {
$namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
}
}
}
return array_values(array_unique(array_filter($namespaces)));
}
/**
* 查找注册命名空间中的名称或缩写。
* @access public
* @param string $namespace
* @return string
* @throws \InvalidArgumentException
*/
public function findNamespace($namespace)
{
$allNamespaces = $this->getNamespaces();
$expr = preg_replace_callback('{([^:]+|)}', function ($matches) {
return preg_quote($matches[1]) . '[^:]*';
}, $namespace);
$namespaces = preg_grep('{^' . $expr . '}', $allNamespaces);
if (empty($namespaces)) {
$message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
if (1 == count($alternatives)) {
$message .= "\n\nDid you mean this?\n ";
} else {
$message .= "\n\nDid you mean one of these?\n ";
}
$message .= implode("\n ", $alternatives);
}
throw new \InvalidArgumentException($message);
}
$exact = in_array($namespace, $namespaces, true);
if (count($namespaces) > 1 && !$exact) {
throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))));
}
return $exact ? $namespace : reset($namespaces);
}
/**
* 查找指令
* @access public
* @param string $name 名称或者别名
* @return Command
* @throws \InvalidArgumentException
*/
public function find($name)
{
$allCommands = array_keys($this->commands);
$expr = preg_replace_callback('{([^:]+|)}', function ($matches) {
return preg_quote($matches[1]) . '[^:]*';
}, $name);
$commands = preg_grep('{^' . $expr . '}', $allCommands);
if (empty($commands) || count(preg_grep('{^' . $expr . '$}', $commands)) < 1) {
if (false !== $pos = strrpos($name, ':')) {
$this->findNamespace(substr($name, 0, $pos));
}
$message = sprintf('Command "%s" is not defined.', $name);
if ($alternatives = $this->findAlternatives($name, $allCommands)) {
if (1 == count($alternatives)) {
$message .= "\n\nDid you mean this?\n ";
} else {
$message .= "\n\nDid you mean one of these?\n ";
}
$message .= implode("\n ", $alternatives);
}
throw new \InvalidArgumentException($message);
}
$exact = in_array($name, $commands, true);
if (count($commands) > 1 && !$exact) {
$suggestions = $this->getAbbreviationSuggestions(array_values($commands));
throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions));
}
return $this->get($exact ? $name : reset($commands));
}
/**
* 获取所有的指令
* @access public
* @param string $namespace 命名空间
* @return Command[]
* @api
*/
public function all($namespace = null)
{
if (null === $namespace) {
return $this->commands;
}
$commands = [];
foreach ($this->commands as $name => $command) {
if ($this->extractNamespace($name, substr_count($namespace, ':') + 1) === $namespace) {
$commands[$name] = $command;
}
}
return $commands;
}
/**
* 获取可能的指令名
* @access public
* @param array $names
* @return array
*/
public static function getAbbreviations($names)
{
$abbrevs = [];
foreach ($names as $name) {
for ($len = strlen($name); $len > 0; --$len) {
$abbrev = substr($name, 0, $len);
$abbrevs[$abbrev][] = $name;
}
}
return $abbrevs;
}
/**
* 配置基于用户的参数和选项的输入和输出实例。
* @access protected
* @param Input $input 输入实例
* @param Output $output 输出实例
*/
protected function configureIO(Input $input, Output $output)
{
if (true === $input->hasParameterOption(['--ansi'])) {
$output->setDecorated(true);
} elseif (true === $input->hasParameterOption(['--no-ansi'])) {
$output->setDecorated(false);
}
if (true === $input->hasParameterOption(['--no-interaction', '-n'])) {
$input->setInteractive(false);
}
if (true === $input->hasParameterOption(['--quiet', '-q'])) {
$output->setVerbosity(Output::VERBOSITY_QUIET);
} else {
if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) {
$output->setVerbosity(Output::VERBOSITY_DEBUG);
} elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) {
$output->setVerbosity(Output::VERBOSITY_VERY_VERBOSE);
} elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
$output->setVerbosity(Output::VERBOSITY_VERBOSE);
}
}
}
/**
* 执行指令
* @access protected
* @param Command $command 指令实例
* @param Input $input 输入实例
* @param Output $output 输出实例
* @return int
* @throws \Exception
*/
protected function doRunCommand(Command $command, Input $input, Output $output)
{
return $command->run($input, $output);
}
/**
* 获取指令的基础名称
* @access protected
* @param Input $input
* @return string
*/
protected function getCommandName(Input $input)
{
return $input->getFirstArgument();
}
/**
* 获取默认输入定义
* @access protected
* @return InputDefinition
*/
protected function getDefaultInputDefinition()
{
return new InputDefinition([
new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'),
new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this console version'),
new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'),
new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
]);
}
public static function addDefaultCommands(array $classnames)
{
self::$defaultCommands = array_merge(self::$defaultCommands, $classnames);
}
/**
* 获取可能的建议
* @access private
* @param array $abbrevs
* @return string
*/
private function getAbbreviationSuggestions($abbrevs)
{
return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : '');
}
/**
* 返回命名空间部分
* @access public
* @param string $name 指令
* @param string $limit 部分的命名空间的最大数量
* @return string
*/
public function extractNamespace($name, $limit = null)
{
$parts = explode(':', $name);
array_pop($parts);
return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
}
/**
* 查找可替代的建议
* @access private
* @param string $name
* @param array|\Traversable $collection
* @return array
*/
private function findAlternatives($name, $collection)
{
$threshold = 1e3;
$alternatives = [];
$collectionParts = [];
foreach ($collection as $item) {
$collectionParts[$item] = explode(':', $item);
}
foreach (explode(':', $name) as $i => $subname) {
foreach ($collectionParts as $collectionName => $parts) {
$exists = isset($alternatives[$collectionName]);
if (!isset($parts[$i]) && $exists) {
$alternatives[$collectionName] += $threshold;
continue;
} elseif (!isset($parts[$i])) {
continue;
}
$lev = levenshtein($subname, $parts[$i]);
if ($lev <= strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) {
$alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
} elseif ($exists) {
$alternatives[$collectionName] += $threshold;
}
}
}
foreach ($collection as $item) {
$lev = levenshtein($name, $item);
if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
$alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
}
}
$alternatives = array_filter($alternatives, function ($lev) use ($threshold) {
return $lev < 2 * $threshold;
});
asort($alternatives);
return array_keys($alternatives);
}
/**
* 设置默认的指令
* @access public
* @param string $commandName The Command name
*/
public function setDefaultCommand($commandName)
{
$this->defaultCommand = $commandName;
}
/**
* 返回所有的命名空间
* @access private
* @param string $name
* @return array
*/
private function extractAllNamespaces($name)
{
$parts = explode(':', $name, -1);
$namespaces = [];
foreach ($parts as $part) {
if (count($namespaces)) {
$namespaces[] = end($namespaces) . ':' . $part;
} else {
$namespaces[] = $part;
}
}
return $namespaces;
}
public function __debugInfo()
{
$data = get_object_vars($this);
unset($data['commands'], $data['definition']);
return $data;
}
}

Some files were not shown because too many files have changed in this diff Show More