diff --git a/.gitignore b/.gitignore index ce2d3bfc5..7846e89ed 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .idea composer.lock *.log +thinkphp diff --git a/.travis.yml b/.travis.yml index 7b5ae6410..36f7b6f90 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,39 +1,42 @@ +sudo: false + language: php -sudo: false +branches: + only: + - stable cache: directories: - $HOME/.composer/cache -matrix: - fast_finish: true - include: - - php: 5.4 - - php: 5.5 - - php: 5.6 - - php: 7.0 - - php: hhvm - allow_failures: - - php: hhvm - before_install: - composer self-update install: - - ./thinkphp/tests/script/install.sh + - 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: - ## LINT - - find thinkphp ! -path "thinkphp/vendor/*" -type f -name \*.php -exec php -l {} \; - ## PHP_CodeSniffer - - thinkphp/vendor/bin/phpcs --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 --standard=PSR2 --ignore="thinkphp/vendor/*" thinkphp - ## PHP Copy/Paste Detector - - thinkphp/vendor/bin/phpcpd --verbose --exclude vendor thinkphp || true - ## PHPLOC - - thinkphp/vendor/bin/phploc --exclude vendor thinkphp - ## PHPUNIT - - thinkphp/vendor/bin/phpunit --coverage-clover=coverage.xml --configuration=thinkphp/phpunit.xml + - php think unit -after_success: - - bash <(curl -s https://codecov.io/bash) +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 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..56c9a4c44 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,1236 @@ +## 2019-1-11 V5.0.24 + +本次更新包含了一个安全更新,建议更新 + +- 改进关联的save方法 +- 改进模型数据验证 +- Collection增加values方法 +- 改进unique验证方法 +- 改进Request类的method方法 + +## 2018-12-9 V5.0.23 + +本次版本更新主要涉及一个安全更新,推荐尽快更新到最新版本。 + +* Query支持调用模型的查询范围 +* 聚合查询字段支持`DISTINCT` +* 改进闭包验证的参数 +* 多对多关联支持指定中间表数据名称 +* after/before验证支持指定字段验证 +* 改进多对多关联 +* 改进验证类 +* 增加`afterWith`和`beforeWith`验证规则 用于比较日期字段 +* 完善规则提示 +* 改进断线重连 +* 修正软删除的`destroy`方法 +* 修复模型的`save`方法当`data`变量为空 数据不验证 +* 模型增加`replace`方法 +* MorphOne 增加 make 方法创建关联对象实例 +* 改进`count`方法返回值类型 +* 改进聚合查询方法的正则判断 +* 改进`sqlsrv`驱动 +* 完善关联的`save`方法 +* 修正控制器名获取 + + +## 2018-10-22 V5.0.22 + +该版本主要增加了JSON日志格式的支持,并且包含了一个安全更新。 + +* 调试模式下关闭路由解析缓存 +* 改进Log类支持`json`日志格式 +* 改进聚合查询的安全性 +* 改进`count`查询的返回值类型 + +## 2018-9-7 V5.0.21 + +该版本主要做了一些已知问题的修正,改进了对Swoole的支持,以及增加路由解析缓存功能。 + +* 增加路由解析缓存功能 +* 改进url生成的端口问题 +* 改进缓存驱动 +* 改进value方法的缓存处理 +* 修正Builder类的insertAll方法 +* 改进对Swoole的支持(使用参考:[xavier-swoole](https://github.com/xavieryang007/xavier-swoole)) + +## 2018-5-11 V5.0.20 + +该版本为修正版本,修正了一些已知的问题。 + +* `join`方法的条件支持传入`Expression`对象 +* 改进驱动的`parseKey`方法 +* 改进Request类的`host`方法 +* 使用`exp`表达式更新数据的异常提示 +* 修正查询 +* 改进多对多关联的中间表模型更新 + +## 2018-4-25 V5.0.19 + +该版本属于改进版本,主要改进了composer自动加载及内置模板引擎的一处可能的安全隐患。 + +* 改进composer自动加载 +* 改进模板引擎一处安全隐患 +* 改进`comment`方法解析 +* 改进分布式写入数据后及时读取的问题 +* 改进url操作方法的自动转换 +* 改进分页类魔术方法的返回值 +* SQL日志增加主从标记 + +## 2018-4-14 V5.0.18 + +该版本主要修正上一个发布的一些BUG,并且改进了`exp`表达式查询/写入的严谨性。 + +* 修正`field`方法`*`兼容问题; +* 修正`inc/dec`方法; +* 修正`setInc/setDec`方法; +* 改进`insertAll`方法; +* 改进`parseTime`方法; +* 改进`exp`表达式查询/写入的严谨性; + +## 2018-4-12 V5.0.17 + +该版本主要是一些修正和改进,并且包含了一个安全更新。 + +* 改进Response类`create`方法 +* 改进`inc/dec`查询 +* 默认模板渲染规则支持直接使用操作方法名 +* 改进视图驱动 +* 改进Request类ip方法 支持代理设置 +* 修正request类的`create`方法 +* 闭包查询使用`cache(true)`抛出异常 +* 改进composer自动加载文件 +* 增加`Expression`类及相关方法 + +## 2018-3-26 V5.0.16 + +该版本主要做了一些修正和改进,由于包含了一个安全更新,是一个推荐更新的版本。 + +* 改进Url生成 +* 改进composer自动加载性能 +* 改进一对一查询 +* 改进查询缓存 +* 改进field方法 +* 优化Template类 +* 修正分页参数 +* 改进默认模板的自动识别 +* 改进Query类查询 +* Collection类改进 +* 改进模型类`readTransform`方法对序列化类型的处理 +* 改进trace显示 +* 文件日志支持自动清理 +* 改进断线重连的判断 +* 改进验证方法 +* 修正Query类view方法的数组表名定义 +* 改进参数绑定 +* 改进文件缓存的并发删除 +* 改进`inc/dec/exp`更新的安全性 +* 增加控制台配置 + +## 2018-1-31 V5.0.15 + +该版本主要进行了一些修正和完善 + +* 改进View类 +* 改进chunk方法 +* 改进模板引擎的表达式语法 +* 改进自关联查询多级调用问题 +* 关联定义增加`selfRelation`方法用于设置是否自关联 +* 改进file类型的缓存`inc`和`dec`方法不改变缓存有效期 +* 改进软删除 支持设置`deleteTime`属性关闭 +* 改进`union`查询 +* 改进查询缓存 +* 优化File缓存自动生成空目录的问题 +* 改进日志写入并发问题 +* 修正`MorphTo`关联 +* 改进`join`自关联查询 +* 改进`case`标签解析 +* 改进Url类对`url_convert`配置的支持 + + +## 2018-1-1 V5.0.14 + +V5.0.14版本主对复合主键进行了更多支持,改进了PHP7的兼容性,并且对数据库的一些问题做了改进。 + +主要更新如下: + +* 改进Validate类的unique验证 +* Validate类增加checkRule方法用于静态验证多个规则 +* 改进多对多关联的save方法 +* 改进多对多的pivot对象 +* 修正setDec方法的延迟写入 +* max和min方法增加第二个参数用于设置是否强制转换数字 +* 改进View类 +* 改进join关联自身的问题 +* 改进union查询 +* 改进Url类 +* 改进同名路由不同请求的注册 +* 改进Builder类parseData对空数组的判断 +* 改进模板替换 +* 调整BelongsTo的hasWhere方法 +* 改进模板的编译缓存命名规则 增加布局模板的标识 +* 改进insertall方法 +* 改进chunk方法支持复合主键 +* 改进Error类的一个兼容问题 +* 改进model类的save方法的复合主键包含自增的情况 +* save方法改进复合主键的支持 +* 改进mysql的insertAll方法 +* 改进redis长连接多编号库的情况 + +## 2017-12-12 V5.0.13 + +`V5.0.13`主要是对模型和日志方面做了一些改进 + +### [数据库和模型] + +* 改进Model类`save`方法对`oracle`的支持 +* 改进中间表模型的实例化 +* 改进`Pivot`类 +* 模型`saveall`方法支持配合`isUpdate`方法 +* 模型类增加`force`方法设置是否强制更新所有数据 +* 关联自动删除增加一对多关联删除支持 +* 改进`hasWhere`查询的数据重复问题 +* 改进一对多`with`关联查询的`field`支持 +* 模型`saveall`方法支持返回数据集 读取`resultSetType`属性 +* 改进废弃字段判断 +* 模型的`hasWhere`方法增加`fields`参数 +* 改进断线重连异常捕获机制 +* 修正Query类的`inc`和`dec`方法的Mysql关键词问题 +* 修正数据集对象的BUG + +### [其它] + +* 增加`app_dispatch`钩子位置 +* cookie类`httponly`参数默认改为false +* File日志驱动增加`single`参数配置是否记录单个文件日志 +* 单个日志文件支持大小设置 +* 改进日志记录的ip地址 +* Redis缓存驱动改用`serialize`序列化替代json序列化 +* 改进异常捕获 +* 改进上传文件验证 +* 修正redis驱动 +* 改进File缓存的`clear`方法 +* 代码格式化规范 +* 改进一处PHP7.2的兼容问题 +* 调试模式下不读取字段缓存文件 +* `default_filter`支持在模块中配置生效 + +## 2017-11-06 V5.0.12 + +5.0.12是一个修正版本,包含了上个版本发布以来的一些修正和完善,主要包括: + +* 上传类和验证类的多语言支持; +* 模型增加排除和废弃字段支持; +* 改进insertAll方法的分批处理; +* 改进对枚举类型的参数绑定支持; +* 修正社区反馈的问题; + + +### [数据库和模型] + +* 改进Connection类的getRealSql方法 +* 改进append方法支持一对一关联的bind设置 +* 改进whereTime查询 +* 改进model类的`destroy`方法 +* 修正softdelete +* 修正`chunk`方法对时间字段的支持 +* Collection类增加`push`方法 +* 改进alias方法 +* 修正模型类的`append`处理 +* 改进`appendRelationAttr`方法 +* 改进HasManyThrough关联 +* 改进MorphTo关联 +* 模型增加废除字段`disuse`定义 +* 增加排除字段方法`except` +* 修正`has`方法 +* 改进参数绑定类型对枚举类型的支持 +* 改进`insertAll`方法的分批处理 + + +### [其它] + +* 改进Loader类`controller`和`validate`方法支持多层 +* 验证提示信息支持多语言 +* File类错误信息支持多语言 +* 模板渲染异常处理 +* 修正rest控制器 +* 改进trace驱动 +* 改进Cache类的`remember`方法 +* 改进`url_common_param`的情况下urlencode的问题 +* 改进Url类 +* 改进`exception_handle`配置参数对闭包的支持 +* 执行路由缓存命令前检测RUNTIME_PATH是否存在 +* 调整部分`CacheDriver::dec`在为空的时候递减的行为 +* 优化移动端的显示 +* 改进对JSON-Handle插件的支持 +* 改进redis的`get`方法 +* 改进Request类的`host`方法 + + +## 2017-09-08 V5.0.11 + +5.0.11是一个安全及修正版本,包含了上个版本发布以来的一些修正和完善,更新了几处可能的安全问题,主要包括: + +* 完善缓存驱动; +* 改进数据库查询; +* 改进URL生成类; +* 缓存有效期支持指定过期时间; + +### [数据库和模型] + +* 改进数据库驱动类 +* 改进`group`方法的字段关键字冲突 +* 修正聚合查询返回null的问题 +* 改进Db类的强制重连 +* 改进关联的属性绑定 +* 修正事务的断线重连 +* 修正对象的条件查询 +* Db类增加`clear`方法 +* 改进数组查询条件中的`null`查询 +* 改进Query类的`chunk`方法支持排序设置 +* 改进HasOne和HasMany关联的`has`方法 +* 改进软删除的关联删除 +* 改进一个字段多次查询条件 + +### [其它] + +* 缓存有效期支持指定过期时间(`DateTime`); +* 改进Url生成对端口号的支持 +* 改进`RouteNotFound`异常提示 +* 改进路由分组的全局完整路由匹配 +* 修正部分验证规则的错误提示问题 +* 支持数据集和模型的XML响应输出 +* 改进模板的三元运算标签 +* 改进控制器不存在的错误提示 +* input助手函数支持`route`变量获取 +* 支持在配置文件中读取额外配置参数 +* 完善分页类 +* 修复Trait命名空间重复问题 +* 修正Request类的env方法 +* 优先使用Cookie中的多语言设置 +* 获取缓存标签的时候过滤无效的缓存标识 +* 修正路由批量注册的一个BUG +* `exception_handle`配置参数支持使用闭包定义`render`处理 +* 请求缓存支持缓存标签设置 +* 缓存类`remember`方法增加并发锁定机制 +* 改进上传类对`swf`的支持 +* 改进Session类的`prefix`方法 + +## 2017-07-04 V5.0.10 + +5.0.10是一个修正版本,并包含了一个安全更新,推荐更新,主要包含: + +* 数据库和模型的多处改进 +* 添加新的行为监听 +* 路由支持Response设置 +* 改进调试模式下数据库敏感信息暴露 + +### [数据库和模型] + +* 修正join其他表时生成的delete语句错误 +* 修正远程一对多 +* insertall支持replace +* 修正多对多默认的中间表获取 +* 改进更新后的模型`update_time`数据更新 +* model类增加`removeRelation`方法 +* 模型类增加`setInc`和`setDec`方法 +* 模型类增加`autoWriteTimestamp`方法动态设置时间字段写入 +* 改进驱动类方法的断线重连判断 +* 改进多对多的数据更新 +* 改进BelongsToMany关联查询 +* 修正Query类的value和column方法 +* 改进in查询的去重问题 +* 修正模型类的scope方法传值问题 +* 调整模型的save方法`before_update`检查位置 +* 修改器和获取器方法支持第三个关联数据参数 + +### [其它] + +* 默认关闭调试模式 +* 修复配置extra目录临时文件的错误加载 +* 添加log存储完成行为监听 `log_write_done` +* 改进Build类生成公共文件的目录判断 +* 增加`response_send`行为监听 +* 路由增加response参数用于绑定response处理行为 +* 改进redirect的参数传入 +* 改进环境变量的布尔值读取 +* 改进Url类的域名传入 +* 修正命令行文件生成 +* 改进命令行下面的URL生成 +* 添加`app_host`参数设置默认的URL根地址 +* 改进`Request`类`isSsl`方法判断支持CDN +* 增加`record_trace`配置参数用于日志记录trace信息 + +## 2017-05-20 V5.0.9 + +5.0.9是一个修正版本,推荐更新,主要更新包含: + +### [数据库和模型] + +* 修正关联自动写入 +* 修正模型数据变化判断对为空数据的支持 +* 修正Query类的useSoftDelete方法返回值 +* 修正一对一嵌套关联数组定义的问题 +* 修正使用了手动参数绑定的时候的缓存BUG +* 改进数据库类的一处不能嵌套查询的缺陷 +* 改进数据库断线重连判断 +* 改进模型的appendRelationAttr方法 +* 改进模型类destroy方法传入空数组的时候不进行任何删除操作 +* 改进一对多关联数据的输出 +* 改进模型的save方法对allowField方法的支持 +* 改进分页类的toarray方法 增加总页数 +* 比较运算增加闭包子查询支持 +* db助手函数默认不再强制重新连接 +* 改进belongsToMany的查询字段指定 +* 分页类增加each方法 + +### [其它] + +* 修正路由分组的路由规则大小写识别问题 +* 修正命令行的日志切割生成 +* 修复URL生成时路由规则中的参数没有进行 urlencode +* 改进Request类的filter过滤机制 支持正则 +* 改进Response类支持手动设置contentType +* 修正异常模板中助手函数未定义错误 + +## 2017-04-28 V5.0.8 + +### 主要调整 + +* 改进关联模型 +* 改进日志记录 +* 增加多态一对一关联 +* 修正社区反馈的一些BUG + +### [ 请求和路由 ] + +* 修正Request类`cookie`方法对前缀的支持 +* 改进全局请求缓存的缓存标识 +* 改进Request类`param`方法 +* 修正别名路由 + +### [ 模型和数据库 ] + +* 改进模型数据的更新检查 +* 改进Query类的`column`方法 +* 改进软删除条件在使用闭包查询情况下多次生成的问题 +* belongsToMany增加数据同步方法 +* 查询范围支持静态调用 +* 增加多态一对一(MorphOne)关联 +* 改进BelongsTo关联 +* 改进多态关联支持关联数据添加和注销 +* 改进多对多关联,支持中间表模型自定义 并且定义的时候不需要使用完整表名 +* 改进浮点数类型转换避免出现逗号 +* 调整关联模型的save方法返回值 +* 模型类的get方法第一个参数必须 如果传入null则返回null +* model的save方法改进如果数据没有更新不执行 +* Query增加`useSoftDelete`方法可以单独设置软删除条件 +* 重载BelongsToMany的`selectOrFail`和`findOrFail`方法 +* 重载BelongsToMany的`select` 、`find`和 `paginate`方法 +* 增加模型和`Pivot`对象的`parent`属性 +* 多对多关联支持设置中间表模型 +* 改进Query类的`view`方法中字段的关键字问题 +* 主从数据库的时候开启事务始终操作主库 + +### [ 其它 ] + +* 改进Cookie类的`get`方法支持获取全部 +* `schema`指令增加`config`参数,支持传入数据库连接配置 +* 改进cache类的`store`方法为当次有效 +* 修正cache助手函数对`option`传参的支持 +* 修复`optimize:autoload`命令在`EXTEND_PATH`目录不存在的情况下,类库映射生成错误问题 +* 支持自定义的根命名空间也可以生成类库映射缓存 +* 验证字段比较支持对比其他字段 +* 修复`Session::prefix('xxx');`设置当前作用域BUG +* 改进`optimize::schema`指令 +* 修复`clear`指令无法删除多级目录下文件的问题 +* 改进默认语言读取和自动侦测 +* 改进日志记录格式 并且命令行下面日志改为实时写入 +* 修正模板标签默认值某些情况无效bug +* 改进Url生成对完整域名的支持 +* 改进`Clear`指令不删除`.gitignore` 文件 +* 修复Memcache缓存驱动的`inc`方法 + +### 调整 + +* 如果自定义了应用的命名空间的话,原来的`app_namespace`配置参数改为`APP_NAMESPACE`常量在入口文件中定义 +* 多对多关联的中间表名称不需要添加表前缀 +* 模型的scope方法之后只能使用数据库查询方法而不能使用模型的方法 + +## 2017-02-24 V5.0.7 + +### 主要调整 + +本次更新主要为BUG修正和改进,主要改进如下: + +* 改进全局请求缓存对子域名的支持; +* 改进数据缓存自动更新机制; +* 关联统计支持指定统计属性名; +* 模型嵌套关联支持数组方式; +* HasOne关联支持`has`和`hasWhere`方法; +* 路由的`ext`和`deny_ext`参数允许设置为空(表示不允许任何后缀或者必须使用后缀访问); + +### 修正如下 + +* 修正 IN / NOT IN 型查询条件为空导致的 sql 语法错误 +* 修正分页类的`toArray`方法对简洁模式的支持 +* 修正Model类`delete`方法对多主键的处理 +* 修正软删除对`Mongodb`的支持 +* 修正`Connection`类一处可能的错误 +* 改进Query类的find方法的缓存机制 +* 修正BelongsTo关联 +* 修正JOIN方式一对一关联预载入闭包查询 +* 修正Query类的`insert`方法一处可能存在的警告错误 +* 修正Model类一处Collection的`use`冲突 +* 修正Model类`hasWhere`方法 +* 修正URl生成对`ext`参数的支持 +* 文件缓存`clear`方法会删除空目录 +* 修正Route类的`parseUrlPath`方法一处问题 + +### 调整如下 + +* 默认关闭session的安全参数`secure`,此选项仅能在HTTPS下设置开启 + +## 2017-02-07 V5.0.6 + +### 主要调整: + +本次更新主要为BUG修正及优化(可无缝升级): + +* 数据库支持断线重连机制; +* 改进查询事件的回调参数; +* 改进数据自动缓存机制; +* 增加时间字段自动格式转换设置; +* `MongoDb`和`Oracle`扩展更新至最新核心框架; + +### [数据库和模型] + +* 修正hasMany关联的`has`方法 +* 去除一些数据库惯例配置 避免使用数据库扩展的时候影响 +* 改进多对多的`attach`方法的返回值 +* 增加Mysql的断线重连机制和开关 +* 改进Query类的`find`方法数据缓存机制 +* 改进Query类查询事件的回调参数 +* 改进Query类的自动缓存更新 +* Model类增加`readonly`方法 +* 改进Model类的`has`和`hasWhere`方法 +* 改进模型类的`get`和`all`方法 第二个参数为true或者数字表示缓存参数 +* 修复闭包查询条件为空导致的 sql 语法错误 +* 改进Query类的`setBuilder`方法 避免因自定义连接器类后找不到生成器类 +* 删除Connection类废弃属性`resultSetType` +* 优化Connection类`close`方法 +* 修正Connection类的`bindParam`方法对存储过程的支持 +* 数据库配置参数`datetime_format` 设置为`false`表示关闭时间字段自动转换输出 +* 改进软删除的数据库兼容性问题 支持`Mongodb` + +### [其它] + +* 改进Url类生成 `root`为`/`的情况 +* redirect助手函数和controller类的redirect方法增加with参数 +* 全局请求缓存添加排除规则 添加request_cache_except配置参数 +* Cache类store方法参数允许为空 表示获取当前缓存驱动句柄 +* 改进Validate类的ip验证规则 + +## 2017-01-23 V5.0.5 +### 主要调整: + +本次更新主要改进了数据访问层和模型关联: + +* 增加快捷查询及设置方法; +* 增加关联统计功能; +* 增加关联查询延迟预载入功能; +* 增加关联一对一自动写入和删除; +* 改进存储过程查询; +* 改进关联数据输出; +* 优化查询性能; +* 模型时间字段自动格式化输出; + +### [请求和路由] + +* 改进路由定义的后缀检测 +* Route类的`rest`方法支持覆盖定义 +* 改进Request类的`put`和`post`方法对`json`格式参数的接收 +* Request类增加`contentType`方法 +* 改进Route类`setRule`方法 +* 改进Request类的`create`方法 +* 改进路由到控制器类的方法对默认渲染模板的影响 +* 修正Url类`build`方法定义路由别名后的BUG + +### [数据库和模型] + +* 增加关联统计功能 +* 增加一对一关联自动写入功能 +* 修正聚合模型的`delete`方法 +* 改进Model类的`useGlobalScope`方法 +* Model类的日期类型支持设置为类名 +* Query类增加`data`/`inc`/`dec`/`exp`方法用于快捷设置数据 `insert`和`update`方法参数可以为空 读取`data`设置数据 +* 优化Connection的查询性能 +* 修正Builder类的`parseOrder`方法 +* 修正BelongsToMany类的`attach`方法 +* BelongsToMany类的`attach`方法改进 支持批量写入 +* 改进BelongsToMany类的`saveall`方法 增加第三个参数 用于指定额外参数是否一致 +* Query类的`order`方法支持多次调用合并 +* 改进`count`方法对`group`查询的支持 +* 增加时间戳自动写入的判断 +* 改进Model类`writeTransform`方法 +* 改进Model的时间戳字段写入和读取 +* 写入数据为对象的时候检测是否有`__toString`方法 +* 改进Mysql驱动的`getFields`方法 +* 改进自动时间字段的输出 +* `like`查询条件支持数组 +* 自动时间字段的获取自动使用时间格式化 +* 改进单个字段多次Or查询情况的查询 +* 修正`null`查询的条件合并 +* 改进Query类`paginate`方法第一个参数可以使用数组参数 +* 改进数据集对象的返回,由Query类的select方法进行数据集转换,原生查询不再支持返回数据集对象 +* 增加`whereNull`、`whereIn`等一系列快捷查询方法 +* `fetchPdo`方法调整 +* 改进对存储过程调用的支持 改进`getRealSql`的调用机制 改进数据表字段使用中划线的参数绑定支持 +* 数据库配置参数增加`result_type` 用于设置数据返回类型 方法参数名称调整 +* 改进Query类的`whereTime`方法支持更多的时间日期表达式(默认查询条件为大于指定时间表达式) +* 取消`min`/`max`/`sum`/`avg`方法的参数默认值 +* Query类增加`getPdo`方法用于返回`PDOStatement`对象 +* 改进`today`的日期表达式查询 +* 改进关联属性的获取 +* 改进关联定义中包含查询条件后重复执行的问题 +* 改进参数绑定支持中文字段自动绑定 +* 改进Builder类的`insertall`方法 增加对null和对象数据的处理 +* 改进参数绑定类型 支持`bit`类型自动绑定 +* Connection类`model`方法更改为`getQuery` +* 优化Connection类`__call`方法 +* 修正聚合模型 +* 一对一关联预载入默认改为IN查询方式 +* 增加`collection`助手函数用于数据集转换 +* 增加`load_relation`助手函数用于数组的延迟预载入 +* 改进Model类的`has`方法第二个参数支持使用数组和闭包,无需再使用`hasWhere` +* `relation`方法支持嵌套关联查询 +* 增加`think\model\Collection`作为模型的数据集查询集合对象 +* 取消关联定义的`alias`参数(仅`morphTo`保留) +* Model类的`delete`方法,支持没有主键的情况 +* Model类的`allowField`方法支持逗号分割的字符串 +* 改进写入数据的自动参数绑定的参数名混淆问题 +* 关联预载入查询的属性名默认使用小写+下划线命名 +* Query类的`with`和`relation`方法支持多次调用 +* Collection类增加`hidden`、`visible`和`append`方法 +* 修正软删除的强制删除方法 + +### [其它] + +* `unique`验证规则支持指定完整模型类 并且默认会优先检测模型类是否存在 不存在则检测数据表 +* 改进`Loader`类的`model`、`controller` 和 `validate`方法 支持直接传入类名实例化 +* `Session`类增加安全选项`httponly`和`secure` +* 可以允许自定义`Output`的driver,以适应命令行模式下调用其它命令行指令 +* 改进`loader`类`action`的参数污染问题 +* Validate类的`confirm`验证改为恒等判断 +* 改进`Validate`类的错误信息处理 +* 修正`Validate`类的布尔值规则验证 +* 改进`cookie`助手函数对前缀的支持 +* 文件缓存默认开启子目录缓存避免文件过多导致性能问题 + +### [调整] +* Connection类`model`方法更改为`getQuery` +* 原生查询不再支持返回数据集对象 +* 分页查询返回类型变成`think\Paginator`(用法不变) +* 模型的时间日期字段会自动进行格式化输出,不需要进行额外处理。 +* Session类添加了`secure`和`httponly`参数,并且默认是true + +## 2016-12-20 V5.0.4 +### 主要调整: + +* 关联模型重构并增加多态一对多关联; +* 数据库支持一个字段多次调用不同查询条件; +* 增加数据库CURD事件支持; +* 路由到类和控制器的方法支持传入额外参数; +* 支持全局模板变量赋值; +* 模型支持独立设置查询数据集对象; +* 日志针对命令行及调试做出改进; +* 改进Hook类的行为方法调用 + +### [请求和路由] +* 请求缓存支持模块单独开启 +* Request类`post`方法支持获取`json`方式的请求数据 +* 路由到类的方法和控制器方法 支持传入额外参数,用于方法的参数 +* 改进控制器自动搜索的目录规范 +* 改进请求缓存 +* 改进自动参数绑定 +* 修正路由的请求缓存设置 +* 改进Route类name方法 + +### [数据库和模型] +* 增加数据库查询(CURD)事件 +* 改进多表更新的字段不存在问题 +* 改进Model类的`useGlobalScope`方法 +* 修正子查询作为表名查询的问题 +* Model类增加`resultSetType`属性 用于指定模型查询的数据集对象(默认为空返回数组) +* Model类增加`toCollection`方法(自动调用) +* 关联模型架构调整 +* 改进预载入`with`方法的参数支持小写和下划线定义 +* 修正关联多对多一处错误 +* 改进关联多对多的查询 +* 关联模型支持多态一对多关联 +* 预载入关联查询支持关联对象属性绑定到当前模型 +* 支持追加关联对象的属性到当前模型数据 +* 一对一关联预载入支持JOIN和IN两种方式(默认为JOIN) +* 改进多对多查询 +* 改进模型更新的数据变化比较规则 +* 查询支持一个字段多次查询条件 +* 改进sql日志的sql语句 +* 修正`join`自身表的别名覆盖问题 +* 模型类的`connection`属性和数据库默认配置合并 +* 改进`in`和`between`查询条件的自动参数绑定 +* 改进Query类对数据集对象以及关联字段排序的支持 +* 增加模型的快捷事件方法 +* 改进Query类的`getTableInfo`方法缓存读取 +* model类的`saveAll`方法支持调用`allowField`方法进行字段过滤 +* 修正关联查询的时候 `whereTime`方法的bug +* 改进Query类的聚合查询 +* table方法支持字符串方式的子查询 +* 修正`count` `avg`方法使用`fetchsql`无法正确返回sql的问题 + +### [其它] +* 改进命令行下的日志记录 +* 部署模式下简化日志记录 +* 增加debug日志类型 仅限调试模式记录 +* 改进Template类`parseTemplateFile`方法 +* 改进Validate类的`getRuleMsg`方法 +* 控制器的`error`方法在AJAX请求默认返回url为空 +* Validate类架构方法增加`field`参数 用于设置验证字段的描述 +* 改进App类`invokeMethod`方法对架构函数依赖注入的支持 +* 增加RedirectResponse的`restore`方法返回值 +* View类增加`share`静态方法 用于静态赋值模板变量 +* 验证类增加`hasScene`方法判断是否存在某个场景的验证配置 +* 修正redis和session驱动的`destroy`方法返回值 +* 空操作方法的参数传入去掉操作方法后缀 +* 在控制器中调用request和view增加类型提示 +* 改进`input`助手函数支持多维数据获取 +* Cache类增加`pull`和`remember`方法 +* 改进验证类的`confirm`验证规则 支持自动规则识别 +* 改进验证类的错误信息定义 +* 增加Validate类自定义验证错误信息的替换规则 +* Cookie类增加`forever`方法用于永久保存 +* 模板渲染支持从视图根目录读取模板 +* 改进Hook类的exec方法 + +### [调整] +* Db类查询不再支持设置自定义数据集对象 +* 废除Query类的`fetchClass`方法 +* 控制器的`error`方法在AJAX请求默认返回的url为空 +* 关联方法定义不支持使用小写下划线,必须使用驼峰法 +* 行为类的方法必须使用驼峰法命名 + +## 2016-11-11 V5.0.3 +### 主要调整: +* 请求缓存增强; +* 路由增强; +* 数据库和模型完善; +* 支持反射的异常捕获; +* File类改进; +* 修正社区反馈的一些BUG; + +### [ 请求和路由 ] + +* 资源路由自动注册的路由规则的时候会记录当前使用的资源标识; +* 增强请求缓存功能和规则定义,支持全局自动缓存 +* 修正控制器自动搜索的大小写问题 +* 修正路由绑定到命名空间后 类的自动定位 +* 改进Route类的parseRule方法 路由地址中的变量替换不自动去除路由变量 +* 改进控制器自动搜索 +* Route类增加setOption和getOption方法 用于记录当前路由执行过程中的参数信息 +* 优化路由分组方法 +* 改进分组路由的url生成 + +### [ 数据库和模型 ] + +* 一对一关联查询方法支持定义`field`方法 +* 聚合模型支持设置`field`属性 +* 改进Query类的`alias`方法 +* 改进Query类`join`和`view`方法的table参数 +* 改进Query类`where`方法 +* 改进Query类的`paginate`方法,支持`order`方法 +* 改进Query类的`min`和`max`方法支持日期类型 +* 修正软删除`withTrashed`方法 +* 优化Connection类的`getRealSql`方法生成的sql + +### [ 其它 ] +* 增加request_cache和request_cache_expire配置参数用于配置全局请求缓存; +* 修正input助手函数的数组过滤 +* cache助手函数支持清空操作 +* 改进Config类load方法 一级配置名称强制转为小写 +* 修正Url多次生成的问题 +* File类修正某些环境下面无法识别上传文件的问题 +* 改进App类的空操作方法调用 +* 域名部署URL生成不依赖 url_domain_deploy 配置参数 +* 修正Url类域名部署的问题 +* 视图文件目录支持集中式存放 不放入模块目录 +* cache助手函数支持 remember方法 +* Request类的input方法或者input助手函数的`filter`参数支持传入null 表示不过滤 + +## 2016-10-24 V5.0.2 +### 主要调整: + +* 数据库和模型完善; +* 路由功能完善; +* 增加`yaml`配置格式支持; +* 依赖注入完善; +* Session类完善; +* Cookie类完善; +* Validate类完善; +* 支持反射类的异常捕获; +* 修正社区反馈BUG; + +### [ 请求和路由 ] +* 依赖注入的类如果定义了`invoke`方法则自动调用 +* Request类的`header`方法增加自定义header支持 +* Request类禁止直接实例化调用 +* 改进Request类ip方法 +* 路由变量规则支持闭包定义 +* 路由参数增加`ajax`和`pjax`判断 +* 别名路由增加允许和排除操作 +* 改进路由域名绑定后的url生成 +* 路由生成改进对路由到类的支持 +* 路由生成支持`url_param_type`配置参数 +* 路由生成支持别名路由 +* Route重定向规则支持更多` schema` +* 别名路由支持定义单独方法的请求类型 +* 改进路由分组的url生成 +* 路由规则的组合变量支持可选分隔符定义 +* 改进路由合并参数的获取 +* 路由规则支持单独设置url分隔符,路由参数为 `param_depr` +* 自动搜索控制器支持自定义访问控制器层的情况 +* 改进路由标识不区分大小写 +* 改进路由地址是否定义过路由规则的检测 + +### [ 数据库和模型 ] +* 改进Query类的join方法 +* 改进Query类分页方法的参数绑定 +* 修正软删除方法 +* 修正Query类parseOrder方法一处错误 +* 修正sqlsrv驱动parseOrder方法 +* 修正Query类setInc和setDec方法 +* 改进Model类的save方法支持非自增主键的处理 +* 整型字段的参数绑定如果为空写入默认值0 +* 改进Model类has和hasWhere方法 +* 改进Query类的value方法缓存判断 +* 改进Query类join方法对子查询支持 +* 改进Query类的table方法和alias方法用法 +* 关联预载入支持`hasOne`自关联 +* 改进Builder类的parseKey方法 +* 改进Builder类的join/alias/table方法的解析 +* 改进全局查询范围 +* 改进Query类的聚合查询方法的返回值 +* 改进关联属性的读取 +* 改进聚合模型主键和关联键相同的情况 +* 改进模型在开启`class_suffix`参数情况下的name属性的识别 + +### [ 其它 ] +* Cache类增加`remember`方法 用于当获取的缓存不存在的时候自动写入 +* Session类增加`flash`方法用于设置下一次请求有效的值 +* Session类增加`flush`方法用于清空当前请求有效的值 +* Session类增加`push`方法用于更新数组数据 +* 增加yaml配置格式支持 +* 改进App类的反射异常无法捕获问题 +* 修正session助手函数的清空操作 +* 改进验证类的`image`方法 +* 改进验证类的`activeUrl`方法 +* 改进自定义验证规则的使用 +* 改进控制器自动搜索后的控制器名获取 +* 修正import方法加载extend目录类库 +* 修正json_encode时 "Failed calling XXX::jsonSerialize()" 的异常 +* 改进Loader类model和validate方法的单例问题 +* 改进方法执行的日志记录 +* 改进模板引擎的Think变量解析 +* 改进Lang类`load`方法 +* 验证错误信息支持多语言读取 +* 改进ROOT_PATH常量 +* 改进语言包加载 +* 改进模板session和cookie变量获取,自动判断前缀 +* 缓存驱动统一增加handler方法用于获取操作对象的句柄(某些缓存类型可能为null) +* File类增加`__call`方法用于兼容5.0版本的`md5`和 `sha1`方法 +* 改进文件缓存驱动的`clear`方法 +* Lang类增加`setLangCookieExpire`方法设置多语言cookie过期时间 +* 增加`route_complete_match`配置参数 + +### [ 调整 ] +下列模型属性和方法由原来的静态(static)定义改为动态定义: +* 聚合模型的`relationModel`属性 +* Model类的`useGlobalScope `属性 +* 全局查询范围方法`base`改为动态方法 +* 软删除属性 `deleteTime`属性 + + +## 2016-9-28 V5.0.1 +### 主要调整: +* [依赖注入](215849)完善; +* [扩展配置](118027)文件位置调整; +* 新增数据表[字段缓存命令](211524); +* 支持设置当前的查询对象; +* 支持[请求和路由缓存](215850); + +### [ 请求和路由 ] +* 改进Controller类的`success`和`error`方法的跳转地址识别 支持更多Scheme +* 操作方法和架构方法支持任何对象自动注入 +* Requesst类增加`getInput`方法 用于获取` php://input`值 +* 路由到方法的时候 支持架构方法注入请求对象 +* 改进Route类路由到类的判断 +* Request增加`cache`方法,支持请求缓存 +* 绑定到模块后 路由依然优先检查 +* 路由增加请求缓存参数 +* 修正路由组合变量的可选变量的BUG + +### [ 数据库 ] +* 修正`pgsql`数据库驱动的数据表字段信息读取 +* 改进Query类的`view`方法 第二个参数默认值更改为true 获取全部的字段 +* 数据库配置信息增加`query`参数用于配置查询对象名称 +* 型类增加`query`属性用于配置模型需要的查询对象名称 +* 改进数据表字段缓存读取 +* 改进数据表字段缓存生成 模型为抽象类或者 没有继承Model类 不生成字段缓存 +* 改进模型的字段缓存 虚拟模型不生成字段缓存 +* 改进数据表字段缓存生成 支持读取模块的模型生成 +* 改进聚合模型的`save`方法 主键写入 +* 模型类的field属性定义简化 取消`Query`类的`allowField`和`setFieldType`方法及相关属性 +* 改进数据表字段缓存生成 支持生成多个数据库的 +* 更新数据库驱动类 改进`getTables`方法 +* 增加` optimize:schema` 命令 用于生成数据表字段信息缓存 +* 修正一个查询条件多个条件的时候的参数绑定BUG +* 分页查询方法`paginate`第二个参数传入数字表示总记录数 +* 修正mysql的`JSON`字段查询 +* 改进Query类的getOptions方法 当name参数不存在的时候返回null + +### [ 模型和关联 ] +* 模型类的field属性不需要添加字段类型定义 +* 改进Model类 添加`getDb`静态方法获取db查询对象 +* 改进聚合模型`save`方法返回值 +* 改进Relation类`save`方法 +* 修正关联模型 多对多`save`方法一处问题 +* 改进Model类的save方法 修正不按主键查询的更新问题 +* 时间字段获取器获取的时候为NULL则不做转换 + +### [ 其它 ] + +* 改进配置缓存生成 支持扩展配置 +* 取消`extra_config_list`配置参数 扩展配置文件直接放到 `extra`目录下面即可自动加载(数据库配置文件位置不变) +* cache助手函数支持判断缓存是否有效 +* 修正 模板引擎驱动类的`config`方法 +* 修复在配置Model属性field=true情况下,通过`__call`调用db()引发的BUG +* 改进模板引擎驱动的config方法 支持获取配置参数值 +* 改进redirct的url地址解析 +* 删除`File`类的`md5`和`sha1`方法 改为`hash`方法 支持更多的散列值类型生成 +* 增加`response_end`行为标签 +* 改进默认语言的加载 + +## 2016-9-15 V5.0 + +### [ 请求和路由 ] + +* Request对象支持动态绑定属性 +* 定义了路由规则的URL原地址禁止访问 +* 改进路由规则存储结构 +* 路由分组功能增强,支持嵌套和虚拟分组 +* 路由URL高效反解 +* 改进Request对象param方法获取优先级 +* 路由增加name方法设置和获取路由标识 +* 增加MISS和AUTO路由规则 +* Route类增加auto方法 支持注册一个自动解析URL的路由 +* 路由规则支持模型绑定 +* 路由变量统一使用param方法获取 +* 路由规则标识功能和自动标识 +* 增加生成路由缓存指令 optimize:route +* Request对象增加route方法单独获取路由变量 +* Request对象的param get post put request delete server cookie env方法的第一个参数传入false 则表示获取原始数据 不进行过滤 +* 改进自动路由标识生成 支持不同的路由规则 指向同一个路由标识,改进Url自动生成对路由标识的支持 +* 改进Request类 filter属性的初始化 +* 改进Request类的isAjax和isPjax方法 +* Request类增加token方法 +* 路由配置文件支持多个 使用 route_config_file 配置参数配置 +* 域名绑定支持https检测 +* 改进域名绑定 支持同时绑定模块和其他 支持绑定到数组定义的路由规则,取消域名绑定到分组 +* 路由规则增加PATCH请求类型支持 +* 增加route_complete_match配置参数设置全局路由规则定义是否采用完整匹配 可以由路由规则的参数complete_match 进行覆盖 +* 改进路由的 后缀参数识别 优先于系统的伪静态后缀参数 +* Url类增加root方法用于指定当前root地址(不含域名) +* 改进Url生成对可选参数的支持 + +### [ 数据库 ] + +* 查询条件自动参数绑定 +* 改进分页方法支持参数绑定 +* Query类的cache方法增加缓存标签参数 +* Query类的update和delete方法支持调用cache方法 会自动清除指定key的缓存 配合查询方法的cache方法一起使用 +* 改进Query类的延迟写入方法 +* Query类的column和value方法支持fetchsql +* 改进日期查询方法 +* 改进存储过程方法exec的支持 +* 改进Connection类的getLastInsID方法获取 +* 记录数据库的连接日志(连接时间和DSN) +* 改进Query类的select方法的返回结果集判断 +* Connection类增加getNumRows方法 +* 数据库事务方法取消返回值 +* 改进Query类的chunk方法对主键的获取 +* 改进当数据库驱动类型使用完整命名空间的时候 Query类的builder方法的问题 + +### [ 模型 ] + +* 增加软删除功能 +* 关联模型和预载入改进 +* 关联预载入查询闭包支持更多的连贯操作 +* 完善savell方法支持更新和验证 +* 关联定义统一返回Relation类 +* Model类的has和hasWhere方法对join类型的支持 +* Model类的data方法 批量赋值数据的时候 清空原始数据 +* Model类的get方法第三个参数传入true的时候会自动更新缓存 +* Model类增加只读字段支持 +* Model类增加useGlobalScope方法设置是否启用全局查询范围 +* Model类的base方法改为静态定义 全局多次调用有效 +* Model类支持设定主键、字段信息和字段类型,不依赖自动获取,提高性能 +* Model类的data方法 支持修改器 +* 改进Relation类对非数字类型主键的支持 +* 改进Relation类的一对多删除 +* 修正Relation类的一对多关联预载入查询 + +### [ 日志和缓存 ] + +* 支持日志类型分离存储 +* 日志允许设置记录级别 +* 增加缓存标签功能 +* 缓存类增加pull方法用于获取并删除 +* cache助手函数增加tag参数 +* 简化日志信息,隐藏数据库密码 +* 增加cache/session redis驱动的库选择逻辑; +* memcached驱动的配置参数支持option参数 +* 调试模式下面 日志记录增加页面的header和param参数记录 +* memcached缓存驱动增加连接账号密码参数 +* 缓存支持设置complex类型 支持配置多种缓存并用store切换 +* 缓存类增加tag方法 用于缓存标签设置 clear方法支持清除某个缓存标签的数据 +* File类型日志驱动支持设置单独文件记录不同的日志级别 +* 改进文件缓存和日志的存储文件名命名规范 +* 缓存类增加inc和dec方法 针对数值型数据提供自增和自减操作 +* Cache类增加has方法 get方法支持默认值 + +### [ 其它 ] + +* 视图类支持设置模板引擎参数 +* 增加表单令牌生成和验证 +* 增加中文验证规则 +* 增加image和文件相关验证规则 +* 重定向Response对象支持with方法隐含传参 +* 改进Session类自动初始化 +* session类增加pull方法用于获取并删除 +* 增加Env类用于获取环境变量 +* Request类get/post/put等更改赋值后param方法依然有效 +* 改进Jump跳转地址支持Url::build 解析 +* 优化Hook类 +* 应用调试模式和页面trace支持环境变量设置 +* config助手函数支持 config('?name') 用法 +* 支持使用BIND_MODULE常量的方式绑定模块 +* 入口文件自动绑定模块功能 +* 改进验证异常类的错误信息和模板输出,支持批量验证的错误信息抛出 +* 完善console 增加output一些常用的方法 +* 增加token助手函数 用于在页面快速显示令牌 +* 增加halt方法用于变量调试并中断输出 +* 改进Validate类的number验证规则 和 integer区分开 +* optimize:autoload增加对extend扩展目录的扫描 +* 改进Validate类的boolean验证规则 支持表单数据 +* 改进cookie助手函数支持 判断是否存在某个cookie值 +* 改进abort助手函数 支持抛出HttpResponseException异常 +* 改进File类增加对上传错误的处理 +* 改进File类move方法的返回对象增加上传表单信息,增加获取文件散列值的方法 +* 改进File类的move方法的返回对象改为返回File对象实例 +* 增加clear和optimize:config 指令 +* 改进File类和Validate类的图像文件类型验证 +* 控制器的操作方法支持注入Request之外的对象实例 +* Request类 param(true) 支持获取带文件的数据 +* input助手函数第一个参数增加默认值 +* Validate类增加image验证规则 并改进max min length支持多种数据类型 +* json输出时数据编码失败后抛出异常 + +### [ 调整 ] +* 废除路由映射(静态路由)定义 +* 取消url_deny_suffix配置 改由路由的deny_ext参数设置 +* 模型save方法返回值改为影响的记录数,取消getId参数 +* Request对象controller方法返回驼峰控制器名 +* 控制器前置操作方法不存在则抛出异常 +* Loader类db方法增加name标识参数 +* db助手函数增加第三个参数用于指定连接标识 +* Sqlsrv驱动默认不对数据表字段进行小写转换 +* 移除sae驱动 改为扩展包 +* Oracle驱动移出核心包 +* Firebird驱动移出核心包 +* 取消别名定义文件alias.php +* 配置参数读取的时候取消环境变量判断 需要读取环境变量的时候使用Env类 +* 环境变量定义文件更改为 .env 由原来的PHP数组改为ini格式定义(支持数组方式) +* 状态配置和扩展配置的加载顺序调整 便于状态配置文件中可以更改扩展配置的参数 +* 取消域名绑定到路由分组功能 +* 控制器类的success和error方法url参数支持传入空字符串,则不做任何处理 +* 控制器的error success result redirect方法均不需要使用return +* 创建目录的权限修改为0644 + + +## 2016-7-1 RC4版本 +### [ 底层架构 ] +* 增加Request类 并支持自动注入 +* 统一Composer的自动加载机制 +* 增加Response类的子类扩展 +* 增加File类用于上传和文件操作 +* 取消模式扩展 SAE支持降权 +* 优化框架入口文件 +* 改进异常机制 +* App类输入/输出调整 +* 单元测试的完美支持 +* 增加新的控制台指令 +* 取消系统路径之外的大部分常量定义 +* 类库映射文件由命令行动态生成 包含应用类库 + +### [ 数据库 ] + +* 增加分表规则方法 +* 增加日期和时间表达式查询方法 +* 增加分页查询方法 +* 增加视图查询方法 +* 默认保持数据表字段大小写 +* 数据缓存自动更新机制 +* 完善事务嵌套支持 +* 改进存储过程数据读取 +* 支持设置数据库查询数据集返回类型 + +### [ 模型 ] +* 增加Merge扩展模型 +* 模型支持动态查询 +* 增加更多的类型自动转换支持 +* 增加全局查询范围 +* toJson/toArray支持隐藏和增加属性输出 +* 增加远程一对多关联 + +### [ 其它 ] +* 日志存储结构调整 +* Trace调试功能从日志类独立并增强 +* 原Input类功能并入Request类 +* 类库映射文件采用命令行生成 包含应用类库 +* 验证类的check方法data数据取消引用传参 +* 路由增加MISS路由规则 +* 路由增加路由别名功能 + +## 2016-4-23 RC3版本 +### [ 底层架构 ] +* 框架核心仓库和应用仓库分离 便于composer独立更新 +* 数据库类重构,拆分为Connection(连接器)/Query(查询器)/Builder(SQL生成器) +* 模型类重构,更加对象化 + +### [ 数据库 ] + +* 新的查询语法 +* 闭包查询和闭包事务 +* Query对象查询 +* 数据分批处理 +* 数据库SQL执行监听 + +### [ 模型 ] +* 对象化操作 +* 支持静态调用(查询) +* 支持读取器/修改器 +* 时间戳字段 +* 对象/数组访问 +* JSON序列化 +* 事件触发 +* 命名范围 +* 类型自动转换 +* 数据验证和完成 +* 关联查询/写入 +* 关联预载入 + +### [ 其它更新 ] +* 路由类增加快速路由支持 +* 验证Validate类重构 +* Build类增加快速创建模块的方法 +* Url生成类改进 +* Validate类改进 +* View类及模板引擎驱动设计改进 +* 取消模板引擎的模板主题设计 +* 修正社区反馈的一些问题 +* 助手函数重新命名 +* `router.php`文件位置移动 + +## 2016-3-11 RC2版本 + +* 重新设计的自动验证和自动完成机制(原有自动验证和完成支持采用traits\model\Auto兼容); +* 验证类Validate独立设计; +* 自动生成功能交给Console完成; +* 对数据表字段大小写的处理; +* 改进Controller类(取消traits\contorller\View); +* 改进Input类; +* 改进Url类; +* 改进Cookie类; +* 优化Loader类; +* 优化Route类; +* 优化Template类; +* Session类自动初始化; +* 增加traits\model\Bulk模型扩展用于大批量数据写入和更新; +* 缓存类和日志类增加Test驱动; +* 对异常机制和错误处理的改进; +* 增加URL控制器和操作是否自动转换开关; +* 支持类名后缀设置; +* 取消操作绑定到类的功能; +* 取消use_db_switch参数设计; + +## 2016-1-30 RC1版本 +### [ 底层架构 ] + +* 真正的惰性加载 +* 核心类库组件化 +* 框架引导文件 +* 完善的类库自动加载(支持Composer) +* 采用Traits扩展 +* API友好(输出、异常和调试) +* 文件命名规范调整 + +### [ 调试和异常 ] + +* 专为API开发而设计的输出、调试和异常处理 +* 日志类支持本地文件/SAE/页面Trace/SocketLog输出,可以实现远程浏览器插件调试 +* 内置trace方法直接远程调试 +* 异常预警通知驱动设计 +* 数据库SQL性能分析支持 + +### [ 路由 ] + +* 动态注册路由 +* 自定义路由检测方法 +* 路由分组功能 +* 规则路由中的变量支持采用正则规则定义(包括全局和局部) +* 闭包路由 +* 支持路由到多层控制器 + +### [ 控制器 ] + +* 控制器类无需继承controller类 +* 灵活的多层控制器支持 +* 可以Traits引入高级控制器功能 +* rest/yar/rpc/hprose/jsonrpc控制器扩展 +* 前置操作方法支持排除和指定操作 + + +### [ 模型 ] + +* 简化的核心模型 +* Traits引入高级模型/视图模型/关联模型 +* 主从分布时候主数据库读操作支持 +* 改进的join方法和order方法 + +### [ 视图 ] + +* 视图解析驱动设计(模板引擎) +* 所有方法不再直接输出而是返回交由系统统一输出处理 +* 动态切换模板主题设计 +* 动态切换模板引擎设计 + +### [ 数据库 ] + +* 完全基于PDO实现 +* 简化的数据库驱动设计 +* SQL性能监控(需要开启数据库调试模式) +* PDO参数绑定改进 + +### [ 其他方面 ] + +* 目录和MVC文件自动生成支持 +* I函数默认添加变量修饰符为/s +* 一个行为类里面支持为多个标签位定义不同的方法 +* 更多的社交扩展类库 \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 68744cbf8..000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,65 +0,0 @@ -## 基本流程 - -1. fork本项目; -2. 克隆(clone)你 fork 的项目到本地; -3. 新建分支(branch)并检出(checkout)新分支; -4. 添加本项目到你的本地 git 仓库作为上游(upstream); -5. 进行修改,若你的修改包含方法或函数的增减,请记得修改[单元测试文件](thinkphp/tests); -6. 变基(衍合 rebase)你的分支到上游 master 分支; -7. push 你的本地仓库到 github; -8. 提交 pull requests; -9. 等待 CI 验证(若不通过则重复 5~7,github 会自动更新你的 pull requests); -10. 等待管理员处理,并及时 rebase 你的分支到上游 master 分支(若上游 master 分支有修改),若有必要,可以 `git push -f` 强行推送 rebase 后的分支到自己的 github fork。 - -## 注意事项 - -* 本项目代码格式化标准选用 **PSR-2**; -* 类名和类文件名遵循 **PSR-4**; -* 若对上述修改流程有任何不清楚的地方,请查阅 GIT 教程,如 [这个](http://backlogtool.com/git-guide/cn/); -* CI 会在 PHP 5.4 5.5 5.6 7.0 和 HHVM 上进行测试,其中 HHVM 下的测试容许报错,请确保你的修改符合 PHP 5.4~5.6 和 PHP 7.0 的语法规范; -* 管理员不会合并造成 CI faild 的修改,若出现 CI faild 请检查自己的源代码或修改相应的[单元测试文件](thinkphp/tests); -* 对于代码**不同方面**的修改,请在自己 fork 的项目中**创建不同的分支**(原因参见`修改流程`第9条备注部分); -* 对于 Issues 的处理,请在 pull requests 时使用诸如 `fix #xxx(Issue ID)` 的 title 直接关闭 issue。 -* 变基及交互式变基操作参见 [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 -{ - "enable_auto_align": true, - "indent_with_space": true, - "psr1_naming": true, - "psr2": true, - "version": 1 -} -``` - -或其他 编辑器 / IDE 配合 PSR2 自动格式化工具 - -### Git GUI - -* SourceTree -* GitHub Desktop - -或其他 Git 图形界面客户端 diff --git a/LICENSE.txt b/LICENSE.txt index 574a39c40..2cb9a8a9f 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ ThinkPHP遵循Apache2开源协议发布,并提供免费使用。 -版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn) +版权所有Copyright © 2006-2017 by ThinkPHP (http://thinkphp.cn) All rights reserved。 ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。 diff --git a/README.md b/README.md index e4e8346f8..64525831c 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,10 @@ -thinkphp5.0 beta +ThinkPHP 5.0 =============== -[![Build Status](https://img.shields.io/travis/top-think/think.svg)](https://travis-ci.org/top-think/think) -[![Coverage Status](https://img.shields.io/codecov/c/github/top-think/think.svg)](https://codecov.io/github/top-think/think) -[![Downloads](https://img.shields.io/github/downloads/top-think/think/total.svg)](https://github.com/top-think/think/releases) -[![Releases](https://img.shields.io/github/release/top-think/think.svg)](https://github.com/top-think/think/releases/latest) -[![Releases Downloads](https://img.shields.io/github/downloads/top-think/think/latest/total.svg)](https://github.com/top-think/think/releases/latest) -[![Packagist Status](https://img.shields.io/packagist/v/top-think/think.svg)](https://packagist.org/packages/topthink/think) -[![Packagist Downloads](https://img.shields.io/packagist/dt/top-think/think.svg)](https://packagist.org/packages/topthink/think) +[![Total Downloads](https://poser.pugx.org/topthink/think/downloads)](https://packagist.org/packages/topthink/think) +[![Latest Stable Version](https://poser.pugx.org/topthink/think/v/stable)](https://packagist.org/packages/topthink/think) +[![Latest Unstable Version](https://poser.pugx.org/topthink/think/v/unstable)](https://packagist.org/packages/topthink/think) +[![License](https://poser.pugx.org/topthink/think/license)](https://packagist.org/packages/topthink/think) ThinkPHP5在保持快速开发和大道至简的核心理念不变的同时,PHP版本要求提升到5.4,对已有的CBD模式做了更深的强化,优化核心,减少依赖,基于全新的架构思想和命名空间实现,是ThinkPHP突破原有框架思路的颠覆之作,其主要特性包括: @@ -15,7 +12,9 @@ ThinkPHP5在保持快速开发和大道至简的核心理念不变的同时,PH + 核心功能组件化 + 强化路由功能 + 更灵活的控制器 + + 重构的模型和数据库类 + 配置文件可分离 + + 重写的自动验证和完成 + 简化扩展机制 + API支持完善 + 改进的Log类 @@ -27,10 +26,9 @@ ThinkPHP5在保持快速开发和大道至简的核心理念不变的同时,PH + 分布式环境支持 + 更多的社交类库 -> ThinkPHP5的运行环境要求PHP5.4以上,目前处于开发测试阶段,不排除正式发布之前有所调整, -请谨慎用于实际项目 ^_^。 +> ThinkPHP5的运行环境要求PHP5.4以上。 -详细开发文档参考 [ThinkPHP5开发手册](http://www.kancloud.cn/thinkphp/thinkphp5-guide) +详细开发文档参考 [ThinkPHP5完全开发手册](http://www.kancloud.cn/manual/thinkphp5) ## 目录结构 @@ -38,12 +36,8 @@ ThinkPHP5在保持快速开发和大道至简的核心理念不变的同时,PH ~~~ www WEB部署目录(或者子目录) -├─composer.json composer定义文件 -├─README.md README文件 -├─LICENSE.txt 授权说明文件 ├─application 应用目录 │ ├─common 公共模块目录(可以更改) -│ ├─runtime 应用的运行时目录(可写,可定制) │ ├─module_name 模块目录 │ │ ├─config.php 模块配置文件 │ │ ├─common.php 模块函数文件 @@ -52,15 +46,17 @@ www WEB部署目录(或者子目录) │ │ ├─view 视图目录 │ │ └─ ... 更多类库目录 │ │ +│ ├─command.php 命令行工具配置文件 │ ├─common.php 公共函数文件 │ ├─config.php 公共配置文件 │ ├─route.php 路由配置文件 +│ ├─tags.php 应用行为扩展定义文件 │ └─database.php 数据库配置文件 │ ├─public WEB目录(对外访问目录) │ ├─index.php 入口文件 -│ ├─.htaccess 用于apache的重写 -│ └─router.php 快速测试文件(用于PHP内置webserver) +│ ├─router.php 快速测试文件 +│ └─.htaccess 用于apache的重写 │ ├─thinkphp 框架系统目录 │ ├─lang 语言文件目录 @@ -68,15 +64,22 @@ www WEB部署目录(或者子目录) │ │ ├─think Think类库包目录 │ │ └─traits 系统Trait目录 │ │ -│ ├─mode 应用模式目录 │ ├─tpl 系统模板目录 -│ ├─tests 单元测试文件目录 -│ ├─vendor 第三方类库目录(Composer依赖库) │ ├─base.php 基础定义文件 +│ ├─console.php 控制台入口文件 │ ├─convention.php 框架惯例配置文件 │ ├─helper.php 助手函数文件 │ ├─phpunit.xml phpunit配置文件 │ └─start.php 框架入口文件 +│ +├─extend 扩展类库目录 +├─runtime 应用的运行时目录(可写,可定制) +├─vendor 第三方类库目录(Composer依赖库) +├─build.php 自动生成定义文件(参考) +├─composer.json composer 定义文件 +├─LICENSE.txt 授权说明文件 +├─README.md README 文件 +├─think 命令行入口文件 ~~~ > router.php用于php自带webserver支持,可用于快速测试 @@ -85,7 +88,7 @@ www WEB部署目录(或者子目录) ## 命名规范 -ThinkPHP5的命名规范如下: +`ThinkPHP5`遵循PSR-2命名规范和PSR-4自动加载规范,并且注意如下规范: ### 目录和文件 @@ -95,23 +98,25 @@ ThinkPHP5的命名规范如下: * 类名和类文件名保持一致,统一采用驼峰法命名(首字母大写); ### 函数和类、属性命名 -* 类的命名采用驼峰法,并且首字母大写,例如 `User`、`UserType`,不需要添加后缀,例如UserController应该直接命名为User; + +* 类的命名采用驼峰法,并且首字母大写,例如 `User`、`UserType`,默认不需要添加后缀,例如`UserController`应该直接命名为`User`; * 函数的命名使用小写字母和下划线(小写字母开头)的方式,例如 `get_client_ip`; -* 方法的命名使用驼峰法,并且首字母小写或者使用下划线“_”,例如 `getUserName`,`_parseType`,通常下划线开头的方法属于私有方法; -* 属性的命名使用驼峰法,并且首字母小写或者使用下划线“_”,例如 `tableName`、`_instance`,通常下划线开头的属性属于私有属性; +* 方法的命名使用驼峰法,并且首字母小写,例如 `getUserName`; +* 属性的命名使用驼峰法,并且首字母小写,例如 `tableName`、`instance`; * 以双下划线“__”打头的函数或方法作为魔法方法,例如 `__call` 和 `__autoload`; ### 常量和配置 -* 常量以大写字母和下划线命名,例如 `APP_DEBUG`和 `APP_MODE`; -* 配置参数以小写字母和下划线命名,例如 `url_route_on`; + +* 常量以大写字母和下划线命名,例如 `APP_PATH`和 `THINK_PATH`; +* 配置参数以小写字母和下划线命名,例如 `url_route_on` 和`url_convert`; ### 数据表和字段 -* 数据表和字段采用小写加下划线方式命名,并注意字段名不要以下划线开头,例如 think_user 表和 user_name字段,类似 _username 这样的数据表字段可能会被过滤。 + +* 数据表和字段采用小写加下划线方式命名,并注意字段名不要以下划线开头,例如 `think_user` 表和 `user_name`字段,不建议使用驼峰和中文作为数据表字段命名。 ## 参与开发 -注册并登录 Github 帐号, fork 本项目并进行改动。 -更多细节参阅 [CONTRIBUTING.md](CONTRIBUTING.md) +请参阅 [ThinkPHP5 核心框架包](https://github.com/top-think/framework)。 ## 版权信息 @@ -119,7 +124,7 @@ ThinkPHP遵循Apache2开源协议发布,并提供免费使用。 本项目包含的第三方源码和二进制文件之版权信息另行标注。 -版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn) +版权所有Copyright © 2006-2018 by ThinkPHP (http://thinkphp.cn) All rights reserved。 diff --git a/application/.htaccess b/application/.htaccess new file mode 100644 index 000000000..3418e55a6 --- /dev/null +++ b/application/.htaccess @@ -0,0 +1 @@ +deny from all \ No newline at end of file diff --git a/thinkphp/library/think/Exception.php b/application/command.php similarity index 75% rename from thinkphp/library/think/Exception.php rename to application/command.php index a1ca8404c..826bb2b23 100644 --- a/thinkphp/library/think/Exception.php +++ b/application/command.php @@ -2,14 +2,11 @@ // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO IT JUST THINK ] // +---------------------------------------------------------------------- -// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved. +// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- -// | Author: liu21st +// | Author: yunwuxin <448901948@qq.com> // +---------------------------------------------------------------------- -namespace think; - -class Exception extends \Exception -{} +return []; diff --git a/thinkphp/library/think/model/View.php b/application/common.php similarity index 70% rename from thinkphp/library/think/model/View.php rename to application/common.php index 05e9da074..55d22f266 100644 --- a/thinkphp/library/think/model/View.php +++ b/application/common.php @@ -2,17 +2,11 @@ // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO IT JUST THINK ] // +---------------------------------------------------------------------- -// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved. +// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- -// | Author: liu21st +// | Author: 流年 // +---------------------------------------------------------------------- -namespace think\model; - -T('model/View'); -class View extends \think\Model -{ - use \traits\model\View; -} +// 应用公共文件 diff --git a/application/config.php b/application/config.php index cdff2606f..ee241715b 100644 --- a/application/config.php +++ b/application/config.php @@ -2,23 +2,242 @@ // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO IT JUST THINK ] // +---------------------------------------------------------------------- -// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved. +// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- // | Author: liu21st // +---------------------------------------------------------------------- -// $Id$ return [ - 'url_route_on' => true, - 'log' => [ - 'type' => 'trace', // 支持 socket trace file - // 以下为socket类型配置 - 'host' => '111.202.76.133', - //日志强制记录到配置的client_id - 'force_client_ids' => [], - //限制允许读取日志的client_id - 'allow_client_ids' => [], + // +---------------------------------------------------------------------- + // | 应用设置 + // +---------------------------------------------------------------------- + + // 应用调试模式 + 'app_debug' => false, + // 应用Trace + 'app_trace' => false, + // 应用模式状态 + 'app_status' => '', + // 是否支持多模块 + 'app_multi_module' => true, + // 入口自动绑定模块 + 'auto_bind_module' => false, + // 注册的根命名空间 + 'root_namespace' => [], + // 扩展函数文件 + 'extra_file_list' => [THINK_PATH . 'helper' . EXT], + // 默认输出类型 + 'default_return_type' => 'html', + // 默认AJAX 数据返回格式,可选json xml ... + 'default_ajax_return' => 'json', + // 默认JSONP格式返回的处理方法 + 'default_jsonp_handler' => 'jsonpReturn', + // 默认JSONP处理方法 + 'var_jsonp_handler' => 'callback', + // 默认时区 + 'default_timezone' => 'PRC', + // 是否开启多语言 + '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_controller' => 'Error', + // 操作方法后缀 + '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' => '/', + // URL伪静态后缀 + 'url_html_suffix' => 'html', + // URL普通方式参数 用于自动生成 + 'url_common_param' => false, + // URL参数方式 0 按名称成对解析 1 按顺序解析 + 'url_param_type' => 0, + // 是否开启路由 + 'url_route_on' => true, + // 路由使用完整匹配 + 'route_complete_match' => false, + // 路由配置文件(支持配置多个) + 'route_config_file' => ['route'], + // 是否开启路由解析缓存 + 'route_check_cache' => false, + // 是否强制使用路由 + 'url_route_must' => false, + // 域名部署 + 'url_domain_deploy' => 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' => [], + + // +---------------------------------------------------------------------- + // | 模板设置 + // +---------------------------------------------------------------------- + + 'template' => [ + // 模板引擎类型 支持 php think 支持扩展 + 'type' => 'Think', + // 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 + 'auto_rule' => 1, + // 模板路径 + 'view_path' => '', + // 模板后缀 + 'view_suffix' => 'html', + // 模板文件名分隔符 + 'view_depr' => DS, + // 模板引擎普通标签开始标记 + 'tpl_begin' => '{', + // 模板引擎普通标签结束标记 + 'tpl_end' => '}', + // 标签库标签开始标记 + 'taglib_begin' => '{', + // 标签库标签结束标记 + 'taglib_end' => '}', + ], + + // 视图输出字符串内容替换 + 'view_replace_str' => [], + // 默认跳转页面对应的模板文件 + 'dispatch_success_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl', + 'dispatch_error_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl', + + // +---------------------------------------------------------------------- + // | 异常及错误设置 + // +---------------------------------------------------------------------- + + // 异常页面的模板文件 + 'exception_tmpl' => THINK_PATH . 'tpl' . DS . 'think_exception.tpl', + + // 错误显示信息,非调试模式有效 + 'error_message' => '页面错误!请稍后再试~', + // 显示错误信息 + 'show_error_msg' => false, + // 异常处理handle类 留空使用 \think\exception\Handle + 'exception_handle' => '', + + // +---------------------------------------------------------------------- + // | 日志设置 + // +---------------------------------------------------------------------- + + 'log' => [ + // 日志记录方式,内置 file socket 支持扩展 + 'type' => 'File', + // 日志保存目录 + 'path' => LOG_PATH, + // 日志记录级别 + 'level' => [], + ], + + // +---------------------------------------------------------------------- + // | Trace设置 开启 app_trace 后 有效 + // +---------------------------------------------------------------------- + 'trace' => [ + // 内置Html Console 支持扩展 + 'type' => 'Html', + ], + + // +---------------------------------------------------------------------- + // | 缓存设置 + // +---------------------------------------------------------------------- + + '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, + ], + + // +---------------------------------------------------------------------- + // | Cookie设置 + // +---------------------------------------------------------------------- + 'cookie' => [ + // cookie 名称前缀 + 'prefix' => '', + // cookie 保存时间 + 'expire' => 0, + // cookie 保存路径 + 'path' => '/', + // cookie 有效域名 + 'domain' => '', + // cookie 启用安全传输 + 'secure' => false, + // httponly设置 + 'httponly' => '', + // 是否使用 setcookie + 'setcookie' => true, + ], + + //分页配置 + 'paginate' => [ + 'type' => 'bootstrap', + 'var_page' => 'page', + 'list_rows' => 15, ], ]; diff --git a/application/database.php b/application/database.php index 885ebf841..66ad466d9 100644 --- a/application/database.php +++ b/application/database.php @@ -2,43 +2,54 @@ // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO IT JUST THINK ] // +---------------------------------------------------------------------- -// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved. +// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- // | Author: liu21st // +---------------------------------------------------------------------- -// $Id$ return [ // 数据库类型 - 'type' => 'mysql', - // 数据库连接DSN配置 - 'dsn' => '', + 'type' => 'mysql', // 服务器地址 - 'hostname' => '127.0.0.1', + 'hostname' => '127.0.0.1', // 数据库名 - 'database' => '', - // 数据库用户名 - 'username' => 'root', - // 数据库密码 - 'password' => '', - // 数据库连接端口 - 'hostport' => '', + 'database' => '', + // 用户名 + 'username' => 'root', + // 密码 + 'password' => '', + // 端口 + 'hostport' => '', + // 连接dsn + 'dsn' => '', // 数据库连接参数 - 'params' => [], + 'params' => [], // 数据库编码默认采用utf8 - 'charset' => 'utf8', + 'charset' => 'utf8', // 数据库表前缀 - 'prefix' => '', + 'prefix' => '', // 数据库调试模式 - 'debug' => APP_DEBUG, + 'debug' => true, // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) - 'deploy' => 0, + 'deploy' => 0, // 数据库读写是否分离 主从式有效 - 'rw_separate' => false, + 'rw_separate' => false, // 读写分离后 主服务器数量 - 'master_num' => 1, + 'master_num' => 1, // 指定从服务器序号 - 'slave_no' => '', + '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, ]; diff --git a/application/index/controller/Index.php b/application/index/controller/Index.php index d6a375353..bee187ac1 100644 --- a/application/index/controller/Index.php +++ b/application/index/controller/Index.php @@ -5,6 +5,6 @@ class Index { public function index() { - return '

:)

欢迎使用 ThinkPHP5

'; + return '

:)

ThinkPHP V5
十年磨一剑 - 为API开发设计的高性能框架

[ V5.0 版本由 七牛云 独家赞助发布 ]
'; } } diff --git a/application/route.php b/application/route.php index 45bcf79d6..591e2c311 100644 --- a/application/route.php +++ b/application/route.php @@ -2,13 +2,12 @@ // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO IT JUST THINK ] // +---------------------------------------------------------------------- -// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved. +// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- // | Author: liu21st // +---------------------------------------------------------------------- -// $Id$ return [ '__pattern__' => [ diff --git a/thinkphp/library/think/model/Adv.php b/application/tags.php similarity index 54% rename from thinkphp/library/think/model/Adv.php rename to application/tags.php index da02eb2ff..4b18d1050 100644 --- a/thinkphp/library/think/model/Adv.php +++ b/application/tags.php @@ -2,20 +2,27 @@ // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO IT JUST THINK ] // +---------------------------------------------------------------------- -// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved. +// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- // | Author: liu21st // +---------------------------------------------------------------------- -namespace think\model; - -T('model/Adv'); -T('model/Transaction'); - -class Adv extends \think\Model -{ - use \traits\model\Adv; - use \traits\model\Transaction; -} +// 应用行为扩展定义文件 +return [ + // 应用初始化 + 'app_init' => [], + // 应用开始 + 'app_begin' => [], + // 模块初始化 + 'module_init' => [], + // 操作开始执行 + 'action_begin' => [], + // 视图内容过滤 + 'view_filter' => [], + // 日志写入 + 'log_write' => [], + // 应用结束 + 'app_end' => [], +]; diff --git a/build.php b/build.php index e14e37cf7..a12d26c15 100644 --- a/build.php +++ b/build.php @@ -2,26 +2,24 @@ // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO IT JUST THINK ] // +---------------------------------------------------------------------- -// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved. +// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- // | Author: liu21st // +---------------------------------------------------------------------- -// $Id$ return [ - // 生成运行时目录 - '__dir__' => ['runtime/cache', 'runtime/log', 'runtime/temp'], - '__file__' => ['tags.php'], + // 生成应用公共文件 + '__file__' => ['common.php', 'config.php', 'database.php'], - // 定义index模块的自动生成 - 'index' => [ - '__file__' => ['tags.php'], + // 定义demo模块的自动生成 (按照实际定义的文件名生成) + 'demo' => [ + '__file__' => ['common.php'], '__dir__' => ['behavior', 'controller', 'model', 'view'], 'controller' => ['Index', 'Test', 'UserType'], - 'model' => [], + 'model' => ['User', 'UserType'], 'view' => ['index/index'], ], - // 。。。 其他更多的模块定义 + // 其他更多的模块定义 ]; diff --git a/composer.json b/composer.json index 622e81a2c..61d3fa7c0 100644 --- a/composer.json +++ b/composer.json @@ -2,9 +2,13 @@ "name": "topthink/think", "description": "the new thinkphp framework", "type": "project", - "keywords": ["framework","thinkphp","ORM"], + "keywords": [ + "framework", + "thinkphp", + "ORM" + ], "homepage": "http://thinkphp.cn/", - "license": "Apache2", + "license": "Apache-2.0", "authors": [ { "name": "liu21st", @@ -12,17 +16,18 @@ } ], "require": { - "php": ">=5.4.0" + "php": ">=5.4.0", + "topthink/framework": "5.0.*" + }, + "autoload": { + "psr-4": { + "app\\": "application" + } }, - "require-dev": { - "johnkary/phpunit-speedtrap": "^1.0", - "mikey179/vfsStream": "~1.6", - "phploc/phploc": "*", - "phpunit/phpunit": "4.8.*", - "sebastian/phpcpd": "*", - "squizlabs/php_codesniffer": "2.*" + "extra": { + "think-path": "thinkphp" }, "config": { - "vendor-dir": "thinkphp/vendor" + "preferred-install": "dist" } } diff --git a/thinkphp/lang/.gitignore b/extend/.gitignore similarity index 100% rename from thinkphp/lang/.gitignore rename to extend/.gitignore diff --git a/public/.htaccess b/public/.htaccess index 929995c67..cbc786893 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -1,8 +1,8 @@ - Options +FollowSymlinks + Options +FollowSymlinks -Multiviews RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L] - \ No newline at end of file + diff --git a/public/index.php b/public/index.php index 4faeb7994..6b7ec30e0 100644 --- a/public/index.php +++ b/public/index.php @@ -2,21 +2,16 @@ // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO IT JUST THINK ] // +---------------------------------------------------------------------- -// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved. +// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- // | Author: liu21st // +---------------------------------------------------------------------- -// 应用入口文件 +// [ 应用入口文件 ] -// 定义项目路径 +// 定义应用目录 define('APP_PATH', __DIR__ . '/../application/'); -// 开启调试模式 -define('APP_DEBUG', true); - // 加载框架引导文件 require __DIR__ . '/../thinkphp/start.php'; -// 执行应用 -\think\App::run(); diff --git a/public/router.php b/public/router.php index 579b63a3a..1b648c42c 100644 --- a/public/router.php +++ b/public/router.php @@ -2,7 +2,7 @@ // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO IT JUST THINK ] // +---------------------------------------------------------------------- -// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved. +// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- @@ -10,8 +10,11 @@ // +---------------------------------------------------------------------- // $Id$ -if (file_exists($_SERVER["DOCUMENT_ROOT"] . $_SERVER["REQUEST_URI"])) { +if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"])) { return false; } else { - require "index.php"; -} \ No newline at end of file + if (!isset($_SERVER['PATH_INFO'])) { + $_SERVER['PATH_INFO'] = $_SERVER['REQUEST_URI']; + } + require __DIR__ . "/index.php"; +} diff --git a/thinkphp/vendor/.gitignore b/runtime/.gitignore similarity index 100% rename from thinkphp/vendor/.gitignore rename to runtime/.gitignore diff --git a/thinkphp/library/think/model/Relation.php b/think similarity index 65% rename from thinkphp/library/think/model/Relation.php rename to think index 8190923a1..4e2688f3a 100644 --- a/thinkphp/library/think/model/Relation.php +++ b/think @@ -1,18 +1,17 @@ +#!/usr/bin/env php +// | Author: yunwuxin <448901948@qq.com> // +---------------------------------------------------------------------- -namespace think\model; +// 定义项目路径 +define('APP_PATH', __DIR__ . '/application/'); -T('model/Relation'); -class Relation extends \think\Model -{ - use \traits\model\Relation; -} +// 加载框架引导文件 +require __DIR__.'/thinkphp/console.php'; diff --git a/thinkphp/base.php b/thinkphp/base.php deleted file mode 100644 index 0368cd32d..000000000 --- a/thinkphp/base.php +++ /dev/null @@ -1,60 +0,0 @@ - -// +---------------------------------------------------------------------- - -// 开始运行时间和内存使用 -define('START_TIME', microtime(true)); -define('START_MEM', memory_get_usage()); -// 版本信息 -define('THINK_VERSION', '5.0.0beta'); -// 系统常量 -defined('DS') or define('DS', DIRECTORY_SEPARATOR); -defined('THINK_PATH') or define('THINK_PATH', dirname(__FILE__) . DS); -defined('LIB_PATH') or define('LIB_PATH', THINK_PATH . 'library' . DS); -defined('EXTEND_PATH') or define('EXTEND_PATH', THINK_PATH . 'extend' . DS); -defined('MODE_PATH') or define('MODE_PATH', THINK_PATH . 'mode' . DS); // 系统应用模式目录 -defined('CORE_PATH') or define('CORE_PATH', LIB_PATH . 'think' . DS); -defined('ORG_PATH') or define('ORG_PATH', LIB_PATH . 'org' . DS); -defined('TRAIT_PATH') or define('TRAIT_PATH', LIB_PATH . 'traits' . DS); -defined('APP_PATH') or define('APP_PATH', dirname($_SERVER['SCRIPT_FILENAME']) . DS); -defined('APP_NAMESPACE') or define('APP_NAMESPACE', 'app'); -defined('COMMON_MODULE') or define('COMMON_MODULE', 'common'); -defined('RUNTIME_PATH') or define('RUNTIME_PATH', realpath(APP_PATH) . DS . 'runtime' . DS); -defined('DATA_PATH') or define('DATA_PATH', RUNTIME_PATH . 'data' . DS); -defined('LOG_PATH') or define('LOG_PATH', RUNTIME_PATH . 'log' . DS); -defined('CACHE_PATH') or define('CACHE_PATH', RUNTIME_PATH . 'cache' . DS); -defined('TEMP_PATH') or define('TEMP_PATH', RUNTIME_PATH . 'temp' . DS); -defined('VENDOR_PATH') or define('VENDOR_PATH', THINK_PATH . 'vendor' . DS); -defined('EXT') or define('EXT', '.php'); -defined('MODEL_LAYER') or define('MODEL_LAYER', 'model'); -defined('VIEW_LAYER') or define('VIEW_LAYER', 'view'); -defined('CONTROLLER_LAYER') or define('CONTROLLER_LAYER', 'controller'); -defined('APP_MULTI_MODULE') or define('APP_MULTI_MODULE', true); // 是否多模块 -defined('APP_DEBUG') or define('APP_DEBUG', false); // 是否调试模式 -defined('APP_HOOK') or define('APP_HOOK', false); // 是否开启HOOK -defined('ENV_PREFIX') or define('ENV_PREFIX', 'T_'); // 环境变量的配置前缀 -defined('IS_API') or define('IS_API', false); // 是否API接口 -defined('APP_AUTO_BUILD') or define('APP_AUTO_BUILD', false); // 是否自动生成应用模块 -defined('APP_AUTO_RUN') or define('APP_AUTO_RUN', false); // 是否自动运行 - -// 应用模式 默认为普通模式 -defined('APP_MODE') or define('APP_MODE', function_exists('saeAutoLoader') ? 'sae' : 'common'); - -// 环境常量 -define('IS_CGI', strpos(PHP_SAPI, 'cgi') === 0 ? 1 : 0); -define('IS_WIN', strstr(PHP_OS, 'WIN') ? 1 : 0); -define('IS_CLI', PHP_SAPI == 'cli' ? 1 : 0); -define('IS_AJAX', (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') ? true : false); -define('NOW_TIME', $_SERVER['REQUEST_TIME']); -define('REQUEST_METHOD', IS_CLI ? 'GET' : $_SERVER['REQUEST_METHOD']); -define('IS_GET', REQUEST_METHOD == 'GET' ? true : false); -define('IS_POST', REQUEST_METHOD == 'POST' ? true : false); -define('IS_PUT', REQUEST_METHOD == 'PUT' ? true : false); -define('IS_DELETE', REQUEST_METHOD == 'DELETE' ? true : false); diff --git a/thinkphp/convention.php b/thinkphp/convention.php deleted file mode 100644 index fa1409cbf..000000000 --- a/thinkphp/convention.php +++ /dev/null @@ -1,189 +0,0 @@ - '', - // 扩展配置文件 - 'extra_config_list' => ['database', 'route'], - // 扩展函数文件 - 'extra_file_list' => [THINK_PATH . 'helper' . EXT], - // 默认输出类型 - 'default_return_type' => 'html', - // 默认语言 - 'default_lang' => 'zh-cn', - // response是否返回方式 - 'response_return' => false, - // 默认AJAX 数据返回格式,可选JSON XML ... - 'default_ajax_return' => 'JSON', - // 默认JSONP格式返回的处理方法 - 'default_jsonp_handler' => 'jsonpReturn', - // 默认JSONP处理方法 - 'var_jsonp_handler' => 'callback', - // 默认时区 - 'default_timezone' => 'PRC', - // 是否开启多语言 - 'lang_switch_on' => false, - // 支持的多语言列表 - 'lang_list' => ['zh-cn'], - // 语言变量 - 'lang_detect_var' => 'lang', - // 语言cookie变量 - 'lang_cookie_var' => 'think_lang', - - // +---------------------------------------------------------------------- - // | 模块设置 - // +---------------------------------------------------------------------- - - // 默认模块名 - 'default_module' => 'index', - // 禁止访问模块 - 'deny_module_list' => [COMMON_MODULE, 'runtime'], - // 默认控制器名 - 'default_controller' => 'Index', - // 默认操作名 - 'default_action' => 'index', - // 默认的空控制器名 - 'empty_controller' => 'Error', - // 操作方法后缀 - 'action_suffix' => '', - // 操作绑定到类 - 'action_bind_class' => false, - - // +---------------------------------------------------------------------- - // | URL设置 - // +---------------------------------------------------------------------- - - // PATHINFO变量名 用于兼容模式 - 'var_pathinfo' => 's', - // 兼容PATH_INFO获取 - 'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'], - // pathinfo分隔符 - 'pathinfo_depr' => '/', - // 获取当前页面地址的系统变量 默认为REQUEST_URI - 'url_request_uri' => 'REQUEST_URI', - // 基础URL路径 - 'base_url' => $_SERVER["SCRIPT_NAME"], - // URL伪静态后缀 - 'url_html_suffix' => '.html', - // URL普通方式参数 用于自动生成 - 'url_common_param' => false, - // url变量绑定 - 'url_params_bind' => true, - // URL变量绑定的类型 0 按变量名绑定 1 按变量顺序绑定 - 'url_parmas_bind_type' => 0, - //url禁止访问的后缀 - 'url_deny_suffix' => 'ico|png|gif|jpg', - // 是否开启路由 - 'url_route_on' => true, - // 是否强制使用路由 - 'url_route_must' => false, - // URL模块映射 - 'url_module_map' => [], - // 域名部署 - 'url_domain_deploy' => false, - // 域名根,如.thinkphp.cn - 'url_domain_root' => '', - // 是否开启 rest 操作方法 - 'url_rest_action' => false, - - // +---------------------------------------------------------------------- - // | 视图及模板设置 - // +---------------------------------------------------------------------- - - // 默认跳转页面对应的模板文件 - 'dispatch_jump_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl', - // 默认的模板引擎 - 'template_engine' => 'Think', - - // +---------------------------------------------------------------------- - // | 异常及错误设置 - // +---------------------------------------------------------------------- - - // 异常页面的模板文件 - 'exception_tmpl' => THINK_PATH . 'tpl' . DS . 'think_exception.tpl', - // 错误显示信息,非调试模式有效 - 'error_message' => '页面错误!请稍后再试~', - // 错误定向页面 - 'error_page' => '', - // 显示错误信息 - 'show_error_msg' => false, - - // +---------------------------------------------------------------------- - // | 日志设置 - // +---------------------------------------------------------------------- - - 'log' => [ - 'type' => 'File', // 支持 file socket trace sae - 'path' => LOG_PATH, - ], - - // +---------------------------------------------------------------------- - // | 缓存设置 - // +---------------------------------------------------------------------- - - 'cache' => [ - 'type' => 'File', - 'path' => CACHE_PATH, - 'prefix' => '', - 'expire' => 0, - ], - - // +---------------------------------------------------------------------- - // | 会话设置 - // +---------------------------------------------------------------------- - - // 是否使用session - 'use_session' => true, - 'session' => [ - 'id' => '', - 'var_session_id' => '', // SESSION_ID的提交变量,解决flash上传跨域 - 'prefix' => 'think', - 'type' => '', - 'auto_start' => true, - ], - - // +---------------------------------------------------------------------- - // | 数据库设置 - // +---------------------------------------------------------------------- - - // 是否启用多状态数据库配置 如果启用的话 需要跟随app_status配置不同的数据库信息 - 'use_db_switch' => false, - 'db_fields_strict' => true, - 'database' => [ - // 数据库类型 - 'type' => 'mysql', - // 数据库连接DSN配置 - 'dsn' => '', - // 服务器地址 - 'hostname' => 'localhost', - // 数据库名 - 'database' => '', - // 数据库用户名 - 'username' => 'root', - // 数据库密码 - 'password' => '', - // 数据库连接端口 - 'hostport' => '', - // 数据库连接参数 - 'params' => [], - // 数据库编码默认采用utf8 - 'charset' => 'utf8', - // 数据库表前缀 - 'prefix' => '', - // 数据库调试模式 - 'debug' => false, - // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) - 'deploy' => 0, - // 数据库读写是否分离 主从式有效 - 'rw_separate' => false, - // 读写分离后 主服务器数量 - 'master_num' => 1, - // 指定从服务器序号 - 'slave_no' => '', - ], - -]; diff --git a/thinkphp/helper.php b/thinkphp/helper.php deleted file mode 100644 index 61cb5c98b..000000000 --- a/thinkphp/helper.php +++ /dev/null @@ -1,300 +0,0 @@ - -// +---------------------------------------------------------------------- - -//------------------------ -// ThinkPHP 助手函数 -//------------------------- - -// 获取多语言变量 -function L($name, $vars = [], $lang = '') -{ - return \think\Lang::get($name, $vars, $lang); -} - -// 获取配置参数 -function C($name = '', $value = null, $range = '') -{ - if (is_null($value) && is_string($name)) { - return \think\Config::get($name, $range); - } else { - return \think\Config::set($name, $value, $range); - } -} - -// 获取输入数据 支持默认值和过滤 -function I($key, $default = null, $filter = '', $merge = false, $data = []) -{ - if (0 === strpos($key, '?')) { - $key = substr($key, 1); - $has = '?'; - } else { - $has = ''; - } - if ($pos = strpos($key, '.')) { - // 指定参数来源 - $method = substr($key, 0, $pos); - if (in_array($method, ['get', 'post', 'put', 'param', 'request', 'session', 'cookie', 'server', 'globals', 'env', 'path', 'file', 'data'])) { - $key = substr($key, $pos + 1); - } else { - $method = 'param'; - } - } else { - // 默认为自动判断 - $method = 'param'; - } - return \think\Input::$method($has . $key, $default, $filter, $merge, $data); -} - -/** - * 记录时间(微秒)和内存使用情况 - * @param string $start 开始标签 - * @param string $end 结束标签 - * @param integer $dec 小数位 - * @return mixed - */ -function G($start, $end = '', $dec = 6) -{ - if ('' == $end) { - \think\Debug::remark($start); - } else { - return 'm' == $dec ? \think\Debug::getRangeMem($start, $end) : \think\Debug::getRangeTime($start, $end, $dec); - } -} - -/** - * 实例化一个没有模型文件的Model - * @param string $name Model名称 支持指定基础模型 例如 MongoModel:User - * @param string $tablePrefix 表前缀 - * @param mixed $connection 数据库连接信息 - * @return \Think\Model - */ -function M($name = '', $tablePrefix = '', $connection = '') -{ - return \think\Loader::table($name, ['prefix' => $tablePrefix, 'connection' => $connection]); -} - -/** - * 实例化Model - * @param string $name Model名称 - * @param string $layer 业务层名称 - * @return object - */ -function D($name = '', $layer = MODEL_LAYER) -{ - return \think\Loader::model($name, $layer); -} - -/** - * 实例化数据库类 - * @param array $config 数据库配置参数 - * @return object - */ -function db($config = []) -{ - return \think\Db::connect($config); -} - -/** - * 实例化控制器 格式:[模块/]控制器 - * @param string $name 资源地址 - * @param string $layer 控制层名称 - * @return object - */ -function A($name, $layer = CONTROLLER_LAYER) -{ - return \think\Loader::controller($name, $layer); -} - -/** - * 调用模块的操作方法 参数格式 [模块/控制器/]操作 - * @param string $url 调用地址 - * @param string|array $vars 调用参数 支持字符串和数组 - * @param string $layer 要调用的控制层名称 - * @return mixed - */ -function R($url, $vars = [], $layer = CONTROLLER_LAYER) -{ - return \think\Loader::action($url, $vars, $layer); -} - -/** - * 导入所需的类库 同java的Import 本函数有缓存功能 - * @param string $class 类库命名空间字符串 - * @param string $baseUrl 起始路径 - * @param string $ext 导入的文件扩展名 - * @return boolean - */ -function import($class, $baseUrl = '', $ext = EXT) -{ - return \think\Loader::import($class, $baseUrl, $ext); -} - -/** - * 快速导入第三方框架类库 所有第三方框架的类库文件统一放到 系统的Vendor目录下面 - * @param string $class 类库 - * @param string $ext 类库后缀 - * @return boolean - */ -function vendor($class, $ext = EXT) -{ - return \think\Loader::import($class, VENDOR_PATH, $ext); -} - -/** - * 快速导入Traits - * @param string $class trait库 - * @param string $ext 类库后缀 - * @return boolean - */ -function T($class, $ext = EXT) -{ - return \think\Loader::import($class, TRAIT_PATH, $ext); -} - -/** - * 抛出异常处理 - * - * @param string $msg 异常消息 - * @param integer $code 异常代码 默认为0 - * - * @throws \think\Exception - */ -function E($msg, $code = 0) -{ - throw new \think\Exception($msg, $code); -} - -/** - * 浏览器友好的变量输出 - * @param mixed $var 变量 - * @param boolean $echo 是否输出 默认为true 如果为false 则返回输出字符串 - * @param string $label 标签 默认为空 - * @return void|string - */ -function dump($var, $echo = true, $label = null) -{ - return \think\Debug::dump($var, $echo, $label); -} - -/** - * 渲染输出Widget - * @param string $name Widget名称 - * @param array $data 传人的参数 - * @return mixed - */ -function W($name, $data = []) -{ - return \think\Loader::action($name, $data, 'Widget'); -} - -function U($url, $vars = '', $suffix = true, $domain = false) -{ - return \think\Url::build($url, $vars, $suffix, $domain); -} - -function session($name, $value = '') -{ - if (is_array($name)) { - // 初始化 - \think\Session::init($name); - } elseif (is_null($name)) { - // 清除 - \think\Session::clear($value); - } elseif ('' === $value) { - // 获取 - return \think\Session::get($name); - } elseif (is_null($value)) { - // 删除session - return \think\Session::delete($name); - } else { - // 设置session - return \think\Session::set($name, $value); - } -} - -function cookie($name, $value = '') -{ - if (is_array($name)) { - // 初始化 - \think\Cookie::init($name); - } elseif (is_null($name)) { - // 清除 - \think\Cookie::clear($value); - } elseif ('' === $value) { - // 获取 - return \think\Cookie::get($name); - } elseif (is_null($value)) { - // 删除session - return \think\Cookie::delete($name); - } else { - // 设置session - return \think\Cookie::set($name, $value); - } -} - -/** - * 缓存管理 - * @param mixed $name 缓存名称,如果为数组表示进行缓存设置 - * @param mixed $value 缓存值 - * @param mixed $options 缓存参数 - * @return mixed - */ -function S($name, $value = '', $options = null) -{ - if (is_array($options)) { - // 缓存操作的同时初始化 - \think\Cache::connect($options); - } elseif (is_array($name)) { - // 缓存初始化 - return \think\Cache::connect($name); - } - if ('' === $value) { - // 获取缓存 - return \think\Cache::get($name); - } elseif (is_null($value)) { - // 删除缓存 - return \think\Cache::rm($name); - } else { - // 缓存数据 - if (is_array($options)) { - $expire = isset($options['expire']) ? $options['expire'] : null; //修复查询缓存无法设置过期时间 - } else { - $expire = is_numeric($options) ? $options : null; //默认快捷缓存设置过期时间 - } - return \think\Cache::set($name, $value, $expire); - } -} - -/** - * 记录日志信息 - * @param mixed $log log信息 支持字符串和数组 - * @param string $level 日志级别 - * @return void|array - */ -function trace($log = '[think]', $level = 'log') -{ - if ('[think]' === $log) { - return \think\Log::getLog(); - } else { - \think\Log::record($log, $level); - } -} - -/** - * 渲染模板输出 - * @param string $template 模板文件 - * @param array $vars 模板变量 - * @return string - */ -function V($template, $vars) -{ - return \think\View::instance(\think\Config::get())->fetch($template, $vars); -} diff --git a/thinkphp/library/think/App.php b/thinkphp/library/think/App.php deleted file mode 100644 index fa3733ea6..000000000 --- a/thinkphp/library/think/App.php +++ /dev/null @@ -1,407 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -/** - * App 应用管理 - * @author liu21st - */ -class App -{ - - // 应用调度机制 - private static $dispatch = []; - - /** - * 执行应用程序 - * @access public - * @return void - */ - public static function run() - { - // 初始化应用(公共模块) - self::initModule(COMMON_MODULE, Config::get()); - - // 读取扩展配置文件 - if (Config::get('extra_config_list')) { - foreach (Config::get('extra_config_list') as $name => $file) { - $file = strpos($file, '.') ? $file : APP_PATH . $file . EXT; - Config::load($file, is_string($name) ? $name : pathinfo($file, PATHINFO_FILENAME)); - } - } - - // 获取配置参数 - $config = Config::get(); - - // 加载额外文件 - if (!empty($config['extra_file_list'])) { - foreach ($config['extra_file_list'] as $file) { - $file = strpos($file, '.') ? $file : APP_PATH . $file . EXT; - if (is_file($file)) { - include_once $file; - } - } - } - - // 设置系统时区 - date_default_timezone_set($config['default_timezone']); - - // 监听app_init - APP_HOOK && Hook::listen('app_init'); - - // 开启多语言机制 - if ($config['lang_switch_on']) { - // 获取当前语言 - defined('LANG_SET') or define('LANG_SET', Lang::range()); - // 加载系统语言包 - Lang::load(THINK_PATH . 'lang' . DS . LANG_SET . EXT); - if (!APP_MULTI_MODULE) { - Lang::load(APP_PATH . 'lang' . DS . LANG_SET . EXT); - } - } - - // 启动session CLI 不开启 - if (!IS_CLI && $config['use_session']) { - Session::init($config['session']); - } - - if (empty(self::$dispatch['type'])) { - // 未指定调度类型 则进行URL路由检测 - self::route($config); - } - // 记录路由信息 - APP_DEBUG && Log::record('[ ROUTE ] ' . var_export(self::$dispatch, true), 'info'); - // 监听app_begin - APP_HOOK && Hook::listen('app_begin'); - - // 根据类型调度 - switch (self::$dispatch['type']) { - case 'redirect': - // 执行重定向跳转 - header('Location: ' . self::$dispatch['url'], true, self::$dispatch['status']); - break; - case 'module': - // 模块/控制器/操作 - $data = self::module(self::$dispatch['module'], $config); - break; - case 'controller': - // 执行控制器操作 - $data = Loader::action(self::$dispatch['controller'], self::$dispatch['params']); - break; - case 'method': - // 执行回调方法 - $data = self::invokeMethod(self::$dispatch['method'], self::$dispatch['params']); - break; - case 'function': - // 规则闭包 - $data = self::invokeFunction(self::$dispatch['function'], self::$dispatch['params']); - break; - default: - throw new Exception('dispatch type not support', 10008); - } - // 监听app_end - APP_HOOK && Hook::listen('app_end', $data); - // 输出数据到客户端 - return Response::send($data, Response::type(), Config::get('response_return')); - } - - // 执行函数或者闭包方法 支持参数调用 - private static function invokeFunction($function, $vars = []) - { - $reflect = new \ReflectionFunction($function); - $args = self::bindParams($reflect, $vars); - // 记录执行信息 - APP_DEBUG && Log::record('[ RUN ] ' . $reflect->getFileName() . '[ ' . var_export($vars, true) . ' ]', 'info'); - return $reflect->invokeArgs($args); - } - - // 调用反射执行类的方法 支持参数绑定 - private static function invokeMethod($method, $vars = []) - { - if (empty($vars)) { - // 自动获取请求变量 - switch ($_SERVER['REQUEST_METHOD']) { - case 'POST': - $vars = array_merge($_GET, $_POST); - break; - case 'PUT': - parse_str(file_get_contents('php://input'), $vars); - break; - default: - $vars = $_GET; - } - } - if (is_array($method)) { - $class = is_object($method[0]) ? $method[0] : new $method[0]; - $reflect = new \ReflectionMethod($class, $method[1]); - } else { - // 静态方法 - $reflect = new \ReflectionMethod($method); - } - $args = self::bindParams($reflect, $vars); - // 记录执行信息 - APP_DEBUG && Log::record('[ RUN ] ' . $reflect->getFileName() . '[ ' . var_export($args, true) . ' ]', 'info'); - return $reflect->invokeArgs(isset($class) ? $class : null, $args); - } - - // 绑定参数 - private static function bindParams($reflect, $vars) - { - $args = []; - if ($reflect->getNumberOfParameters() > 0) { - $params = $reflect->getParameters(); - foreach ($params as $param) { - $name = $param->getName(); - if (isset($vars[$name])) { - $args[] = $vars[$name]; - } elseif ($param->isDefaultValueAvailable()) { - $args[] = $param->getDefaultValue(); - } else { - throw new Exception('method param miss:' . $name, 10004); - } - } - // 全局过滤 - array_walk_recursive($args, 'think\\Input::filterExp'); - } - return $args; - } - - // 执行 模块/控制器/操作 - private static function module($result, $config) - { - if (APP_MULTI_MODULE) { - // 多模块部署 - $module = strtolower($result[0] ?: $config['default_module']); - if ($maps = $config['url_module_map']) { - if (isset($maps[$module])) { - // 记录当前别名 - define('MODULE_ALIAS', $module); - // 获取实际的项目名 - $module = $maps[MODULE_ALIAS]; - } elseif (array_search($module, $maps)) { - // 禁止访问原始项目 - $module = ''; - } - } - // 获取模块名称 - define('MODULE_NAME', strip_tags($module)); - - // 模块初始化 - if (MODULE_NAME && !in_array(MODULE_NAME, $config['deny_module_list']) && is_dir(APP_PATH . MODULE_NAME)) { - APP_HOOK && Hook::listen('app_begin'); - define('MODULE_PATH', APP_PATH . MODULE_NAME . DS); - define('VIEW_PATH', MODULE_PATH . VIEW_LAYER . DS); - // 初始化模块 - self::initModule(MODULE_NAME, $config); - } else { - throw new Exception('module [ ' . MODULE_NAME . ' ] not exists ', 10005); - } - } else { - // 单一模块部署 - define('MODULE_NAME', ''); - define('MODULE_PATH', APP_PATH); - define('VIEW_PATH', MODULE_PATH . VIEW_LAYER . DS); - } - - // 获取控制器名 - define('CONTROLLER_NAME', strtolower(strip_tags($result[1] ?: Config::get('default_controller')))); - // 获取操作名 - define('ACTION_NAME', strtolower(strip_tags($result[2] ?: Config::get('default_action')))); - - // 执行操作 - if (!preg_match('/^[A-Za-z](\/|\.|\w)*$/', CONTROLLER_NAME)) { - // 安全检测 - throw new Exception('illegal controller name:' . CONTROLLER_NAME, 10000); - } - if (Config::get('action_bind_class')) { - $class = self::bindActionClass(Config::get('empty_controller')); - $instance = new $class; - // 操作绑定到类后 固定执行run入口 - $action = 'run'; - } else { - $instance = Loader::controller(CONTROLLER_NAME, '', Config::get('empty_controller')); - // 获取当前操作名 - $action = ACTION_NAME . Config::get('action_suffix'); - } - - try { - // 操作方法开始监听 - $call = [$instance, $action]; - APP_HOOK && Hook::listen('action_begin', $call); - if (!preg_match('/^[A-Za-z](\w)*$/', $action)) { - // 非法操作 - throw new \ReflectionException(); - } - // 执行操作方法 - $data = self::invokeMethod($call); - } catch (\ReflectionException $e) { - // 操作不存在 - if (method_exists($instance, '_empty')) { - $method = new \ReflectionMethod($instance, '_empty'); - $data = $method->invokeArgs($instance, [$action, '']); - APP_DEBUG && Log::record('[ RUN ] ' . $method->getFileName(), 'info'); - } else { - throw new Exception('method [ ' . (new \ReflectionClass($instance))->getName() . '->' . $action . ' ] not exists ', 10002); - } - } - return $data; - } - - // 操作绑定到类:模块\controller\控制器\操作类 - private static function bindActionClass($emptyController) - { - if (is_dir(MODULE_PATH . CONTROLLER_LAYER . DS . str_replace('.', DS, CONTROLLER_NAME))) { - $namespace = MODULE_NAME . '\\' . CONTROLLER_LAYER . '\\' . str_replace('.', '\\', CONTROLLER_NAME) . '\\'; - } else { - // 空控制器 - $namespace = MODULE_NAME . '\\' . CONTROLLER_LAYER . '\\' . $emptyController . '\\'; - } - $actionName = strtolower(ACTION_NAME); - if (class_exists($namespace . $actionName)) { - $class = $namespace . $actionName; - } elseif (class_exists($namespace . '_empty')) { - // 空操作 - $class = $namespace . '_empty'; - } else { - throw new Exception('bind action class not exists :' . ACTION_NAME, 10003); - } - return $class; - } - - // 初始化模块 - private static function initModule($module, $config) - { - // 定位模块目录 - $module = (COMMON_MODULE == $module || !APP_MULTI_MODULE) ? '' : $module . DS; - - // 加载初始化文件 - if (is_file(APP_PATH . $module . 'init' . EXT)) { - include APP_PATH . $module . 'init' . EXT; - } else { - $path = APP_PATH . $module; - // 加载模块配置 - Config::load(APP_PATH . $module . 'config' . EXT); - - // 加载应用状态配置 - if ($config['app_status']) { - Config::load(APP_PATH . $module . $config['app_status'] . EXT); - } - - // 加载别名文件 - if (is_file($path . 'alias' . EXT)) { - Loader::addMap(include $path . 'alias' . EXT); - } - - // 加载行为扩展文件 - if (APP_HOOK && is_file($path . 'tags' . EXT)) { - Hook::import(include $path . 'tags' . EXT); - } - - // 加载公共文件 - if (is_file($path . 'common' . EXT)) { - include $path . 'common' . EXT; - } - - // 加载当前模块语言包 - if ($config['lang_switch_on'] && $module) { - Lang::load($path . 'lang' . DS . LANG_SET . EXT); - } - } - } - - // 分析 PATH_INFO - private static function parsePathinfo($config) - { - if (isset($_GET[$config['var_pathinfo']])) { - // 判断URL里面是否有兼容模式参数 - $_SERVER['PATH_INFO'] = $_GET[$config['var_pathinfo']]; - unset($_GET[$config['var_pathinfo']]); - } elseif (IS_CLI) { - // CLI模式下 index.php module/controller/action/params/... - $_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : ''; - } - - // 监听path_info - APP_HOOK && Hook::listen('path_info'); - // 分析PATHINFO信息 - if (!isset($_SERVER['PATH_INFO'])) { - foreach ($config['pathinfo_fetch'] as $type) { - if (!empty($_SERVER[$type])) { - $_SERVER['PATH_INFO'] = (0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME'])) ? - substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type]; - break; - } - } - } - } - - /** - * URL路由检测(根据PATH_INFO) - * @access public - * @param $config - * @throws Exception - */ - public static function route($config) - { - // 解析PATH_INFO - self::parsePathinfo($config); - - if (empty($_SERVER['PATH_INFO'])) { - $_SERVER['PATH_INFO'] = ''; - define('__INFO__', ''); - define('__EXT__', ''); - } else { - $_SERVER['PATH_INFO'] = trim($_SERVER['PATH_INFO'], '/'); - define('__INFO__', $_SERVER['PATH_INFO']); - // URL后缀 - define('__EXT__', strtolower(pathinfo($_SERVER['PATH_INFO'], PATHINFO_EXTENSION))); - // 检测URL禁用后缀 - if ($config['url_deny_suffix'] && preg_match('/\.(' . $config['url_deny_suffix'] . ')$/i', __INFO__)) { - throw new Exception('url suffix deny'); - } - // 去除正常的URL后缀 - $_SERVER['PATH_INFO'] = preg_replace($config['url_html_suffix'] ? '/\.(' . trim($config['url_html_suffix'], '.') . ')$/i' : '/\.' . __EXT__ . '$/i', '', __INFO__); - } - - $depr = $config['pathinfo_depr']; - // 路由检测 - if (!empty($config['url_route_on'])) { - // 开启路由 - if (!empty($config['route'])) { - // 注册路由定义文件 - Route::register($config['route']); - } - // 路由检测(根据路由定义返回不同的URL调度) - $result = Route::check($_SERVER['PATH_INFO'], $depr, $config['url_domain_deploy']); - if (false === $result) { - // 路由无效 - if ($config['url_route_must']) { - throw new Exception('route not define '); - } else { - // 继续分析为模块/控制器/操作/参数...方式URL - $result = Route::parseUrl($_SERVER['PATH_INFO'], $depr); - } - } - } else { - // 分析URL地址 采用 模块/控制器/操作/参数... - $result = Route::parseUrl($_SERVER['PATH_INFO'], $depr); - } - // 注册调度机制 - self::dispatch($result); - } - - // 指定应用调度 - public static function dispatch($dispatch) - { - self::$dispatch = $dispatch; - } -} diff --git a/thinkphp/library/think/Build.php b/thinkphp/library/think/Build.php deleted file mode 100644 index 6d9776524..000000000 --- a/thinkphp/library/think/Build.php +++ /dev/null @@ -1,152 +0,0 @@ - -// +---------------------------------------------------------------------- -namespace think; - -class Build -{ - public static function run($build) - { - // 锁定 - $lockfile = APP_PATH . 'build.lock'; - if (is_writable($lockfile)) { - return; - } elseif (!touch($lockfile)) { - throw new Exception('应用目录[' . APP_PATH . ']不可写,目录无法自动生成!
请手动生成项目目录~', 10006); - } - foreach ($build as $module => $list) { - if ('__dir__' == $module) { - // 创建目录列表 - self::buildDir($list); - } elseif ('__file__' == $module) { - // 创建文件列表 - self::buildFile($list); - } else { - // 创建模块 - self::buildModule($module, $list); - } - } - // 解除锁定 - unlink($lockfile); - } - - // 创建目录 - protected static function buildDir($list) - { - foreach ($list as $dir) { - if (!is_dir(APP_PATH . $dir)) { - // 创建目录 - mkdir(APP_PATH . $dir, 0777, true); - } - } - } - - // 创建文件 - protected static function buildFile($list) - { - foreach ($list as $file) { - if (!is_dir(APP_PATH . dirname($file))) { - // 创建目录 - mkdir(APP_PATH . dirname($file), 0777, true); - } - if (!is_file(APP_PATH . $file)) { - file_put_contents(APP_PATH . $file, 'php' == pathinfo($file, PATHINFO_EXTENSION) ? " $file) { - $modulePath = APP_PATH . $module . DS; - if ('__dir__' == $path) { - // 生成子目录 - foreach ($file as $dir) { - if (!is_dir($modulePath . $dir)) { - // 创建目录 - mkdir($modulePath . $dir, 0777, true); - } - } - } elseif ('__file__' == $path) { - // 生成(空白)文件 - foreach ($file as $name) { - if (!is_file($modulePath . $name)) { - file_put_contents($modulePath . $name, 'php' == pathinfo($name, PATHINFO_EXTENSION) ? " -// +---------------------------------------------------------------------- - -namespace think; - -class Cache -{ - protected static $instance = []; - public static $readTimes = 0; - public static $writeTimes = 0; - - /** - * 操作句柄 - * @var object - * @access protected - */ - protected static $handler = null; - - /** - * 连接缓存 - * @access public - * @param array $options 配置数组 - * @return object - */ - public static function connect(array $options = []) - { - $md5 = md5(serialize($options)); - if (!isset(self::$instance[$md5])) { - $type = !empty($options['type']) ? $options['type'] : 'File'; - $class = (!empty($options['namespace']) ? $options['namespace'] : '\\think\\cache\\driver\\') . ucwords($type); - unset($options['type']); - self::$instance[$md5] = new $class($options); - // 记录初始化信息 - APP_DEBUG && Log::record('[ CACHE ] INIT ' . $type . ':' . var_export($options, true), 'info'); - } - self::$handler = self::$instance[$md5]; - return self::$handler; - } - - public static function __callStatic($method, $params) - { - if (is_null(self::$handler)) { - // 自动初始化缓存 - self::connect(Config::get('cache')); - } - return call_user_func_array([self::$handler, $method], $params); - } -} diff --git a/thinkphp/library/think/Config.php b/thinkphp/library/think/Config.php deleted file mode 100644 index b656e8a56..000000000 --- a/thinkphp/library/think/Config.php +++ /dev/null @@ -1,164 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -class Config -{ - // 配置参数 - private static $config = []; - // 参数作用域 - private static $range = '_sys_'; - - // 设定配置参数的作用域 - public static function range($range) - { - self::$range = $range; - if (!isset(self::$config[$range])) { - self::$config[$range] = []; - } - } - - /** - * 解析配置文件或内容 - * - * @param string $config 配置文件路径或内容 - * @param string $type 配置解析类型 - * @param string $range 作用域 - */ - public static function parse($config, $type = '', $range = '') - { - $range = $range ?: self::$range; - if (empty($type)) { - $type = pathinfo($config, PATHINFO_EXTENSION); - } - $class = (false === strpos($type, '\\')) ? '\\think\\config\\driver\\' . ucwords($type) : $type; - self::set((new $class())->parse($config), '', $range); - } - - /** - * 加载配置文件(PHP格式) - * - * @param string $file 配置文件名 - * @param string $name 配置名(如设置即表示二级配置) - * @param string $range 作用域 - * @return mixed - */ - public static function load($file, $name = '', $range = '') - { - $range = $range ?: self::$range; - if (!isset(self::$config[$range])) { - self::$config[$range] = []; - } - // 记录加载信息 - APP_DEBUG && Log::record('[ CONFIG ] ' . $file, 'info'); - return is_file($file) ? self::set(include $file, $name, $range) : self::$config[$range]; - } - - /** - * 检测配置是否存在 - * - * @param string $name 配置参数名(支持二级配置 .号分割) - * @param string $range 作用域 - * @return bool - */ - public static function has($name, $range = '') - { - $range = $range ?: self::$range; - $name = strtolower($name); - - if (!strpos($name, '.')) { - return isset(self::$config[$range][$name]); - } else { - // 二维数组设置和获取支持 - $name = explode('.', $name); - return isset(self::$config[$range][$name[0]][$name[1]]); - } - } - - /** - * 获取配置参数 为空则获取所有配置 - * - * @param string $name 配置参数名(支持二级配置 .号分割) - * @param string $range 作用域 - * @return mixed - */ - public static function get($name = null, $range = '') - { - $range = $range ?: self::$range; - // 无参数时获取所有 - if (empty($name) && isset(self::$config[$range])) { - return self::$config[$range]; - } - $name = strtolower($name); - if (!strpos($name, '.')) { - // 判断环境变量 - if (isset($_ENV[ENV_PREFIX . $name])) { - return $_ENV[ENV_PREFIX . $name]; - } - return isset(self::$config[$range][$name]) ? self::$config[$range][$name] : null; - } else { - // 二维数组设置和获取支持 - $name = explode('.', $name); - // 判断环境变量 - if (isset($_ENV[ENV_PREFIX . $name[0] . '_' . $name[1]])) { - return $_ENV[ENV_PREFIX . $name[0] . '_' . $name[1]]; - } - return isset(self::$config[$range][$name[0]][$name[1]]) ? self::$config[$range][$name[0]][$name[1]] : null; - } - } - - /** - * 设置配置参数 name为数组则为批量设置 - * - * @param string $name 配置参数名(支持二级配置 .号分割) - * @param mixed $value 配置值 - * @param string $range 作用域 - * @return mixed - */ - public static function set($name, $value = null, $range = '') - { - $range = $range ?: self::$range; - if (!isset(self::$config[$range])) { - self::$config[$range] = []; - } - if (is_string($name)) { - $name = strtolower($name); - if (!strpos($name, '.')) { - self::$config[$range][$name] = $value; - } else { - // 二维数组设置和获取支持 - $name = explode('.', $name); - self::$config[$range][$name[0]][$name[1]] = $value; - } - return; - } elseif (is_array($name)) { - // 批量设置 - if (!empty($value)) { - return self::$config[$range][$value] = array_change_key_case($name); - } else { - return self::$config[$range] = array_merge(self::$config[$range], array_change_key_case($name)); - } - } else { - // 为空直接返回 已有配置 - return self::$config[$range]; - } - } - - /** - * 重置配置参数 - */ - public static function reset($range = '') - { - $range = $range ?: self::$range; - true === $range ? self::$config = [] : self::$config[$range] = []; - } -} diff --git a/thinkphp/library/think/Controller.php b/thinkphp/library/think/Controller.php deleted file mode 100644 index 00019de7c..000000000 --- a/thinkphp/library/think/Controller.php +++ /dev/null @@ -1,72 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -T('controller/View'); -T('controller/Jump'); - -class Controller -{ - use \traits\controller\Jump; - use \traits\controller\View; - - /** - * 前置操作方法列表 - * @var beforeActionList - * @access protected - */ - protected $beforeActionList = []; - - /** - * 架构函数 - * @access public - */ - public function __construct() - { - // 控制器初始化 - if (method_exists($this, '_initialize')) { - $this->_initialize(); - } - // 前置操作方法 - // 支持 ['action1','action2'] 或者 ['action1'=>['only'=>'index'],'action2'=>['except'=>'login']] - if ($this->beforeActionList) { - foreach ($this->beforeActionList as $method => $options) { - is_numeric($method) ? - $this->beforeAction($options) : - $this->beforeAction($method, $options); - } - } - } - - /** - * 前置操作 - * @access protected - * @param string $method 前置操作方法名 - * @param array $options 调用参数 ['only'=>[...]] 或者['except'=>[...]] - */ - protected function beforeAction($method, $options = []) - { - if (isset($options['only'])) { - if (!in_array(ACTION_NAME, $options['only'])) { - return; - } - } elseif (isset($options['except'])) { - if (in_array(ACTION_NAME, $options['except'])) { - return; - } - } - - if (method_exists($this, $method)) { - call_user_func([$this, $method]); - } - } -} diff --git a/thinkphp/library/think/Cookie.php b/thinkphp/library/think/Cookie.php deleted file mode 100644 index e3381ee48..000000000 --- a/thinkphp/library/think/Cookie.php +++ /dev/null @@ -1,168 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -class Cookie -{ - - protected static $config = [ - // cookie 名称前缀 - 'prefix' => '', - // cookie 保存时间 - 'expire' => 0, - // cookie 保存路径 - 'path' => '/', - // cookie 有效域名 - 'domain' => '', - // cookie 启用安全传输 - 'secure' => false, - // httponly设置 - 'httponly' => '', - ]; - - /** - * Cookie初始化 - * @param array $config - * @return void - */ - public static function init(array $config = []) - { - self::$config = array_merge(self::$config, array_change_key_case($config)); - if (!empty(self::$config['httponly'])) { - ini_set('session.cookie_httponly', 1); - } - } - - /** - * 设置或者获取cookie作用域(前缀) - * @param string $prefix - * @return string|void - */ - public static function prefix($prefix = '') - { - if (empty($prefix)) { - return self::$config['prefix']; - } - self::$config['prefix'] = $prefix; - } - - /** - * Cookie 设置、获取、删除 - * - * @param string $name cookie名称 - * @param mixed $value cookie值 - * @param null $option - * - * @return mixed - * @internal param mixed $options cookie参数 - */ - public static function set($name, $value = '', $option = null) - { - // 参数设置(会覆盖黙认设置) - if (!is_null($option)) { - if (is_numeric($option)) { - $option = ['expire' => $option]; - } elseif (is_string($option)) { - parse_str($option, $option); - } - - $config = array_merge(self::$config, array_change_key_case($option)); - } else { - $config = self::$config; - } - $name = $config['prefix'] . $name; - // 设置cookie - if (is_array($value)) { - array_walk_recursive($value, 'self::jsonFormatProtect', 'encode'); - $value = 'think:' . json_encode($value); - } - $expire = !empty($config['expire']) ? time() + intval($config['expire']) : 0; - setcookie($name, $value, $expire, $config['path'], $config['domain'], $config['secure'], $config['httponly']); - $_COOKIE[$name] = $value; - } - - /** - * Cookie获取 - * @param string $name cookie名称 - * @param string $prefix cookie前缀 - * @return mixed - */ - public static function get($name, $prefix = '') - { - $prefix = $prefix ? $prefix : self::$config['prefix']; - $name = $prefix . $name; - if (isset($_COOKIE[$name])) { - $value = $_COOKIE[$name]; - if (0 === strpos($value, 'think:')) { - $value = substr($value, 6); - $value = json_decode($value, true); - array_walk_recursive($value, 'self::jsonFormatProtect', 'decode'); - } - return $value; - } else { - return null; - } - } - - /** - * Cookie删除 - * @param string $name cookie名称 - * @param string $prefix cookie前缀 - * @return mixed - */ - public static function delete($name, $prefix = '') - { - $config = self::$config; - $prefix = $prefix ? $prefix : $config['prefix']; - $name = $prefix . $name; - setcookie($name, '', time() - 3600, $config['path'], $config['domain'], $config['secure'], $config['httponly']); - // 删除指定cookie - unset($_COOKIE[$name]); - } - - /** - * Cookie清空 - * @param string $prefix cookie前缀 - * @return mixed - */ - public static function clear($prefix = '') - { - // 清除指定前缀的所有cookie - if (empty($_COOKIE)) { - return; - } - - // 要删除的cookie前缀,不指定则删除config设置的指定前缀 - $config = self::$config; - $prefix = $prefix ? $prefix : $config['prefix']; - if ($prefix) { - // 如果前缀为空字符串将不作处理直接返回 - foreach ($_COOKIE as $key => $val) { - if (0 === strpos($key, $prefix)) { - setcookie($key, '', time() - 3600, $config['path'], $config['domain'], $config['secure'], $config['httponly']); - unset($_COOKIE[$key]); - } - } - } else { - unset($_COOKIE); - } - return; - } - - private static function jsonFormatProtect(&$val, $key, $type = 'encode') - { - if (!empty($val) && true !== $val) { - $val = 'decode' == $type ? urldecode($val) : urlencode($val); - } - } - -} diff --git a/thinkphp/library/think/Db.php b/thinkphp/library/think/Db.php deleted file mode 100644 index 408a10155..000000000 --- a/thinkphp/library/think/Db.php +++ /dev/null @@ -1,120 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -/** - * ThinkPHP 数据库中间层实现类 - */ -class Db -{ - // 数据库连接实例 - private static $instances = []; - // 当前数据库连接实例 - private static $instance = null; - // 查询次数 - public static $queryTimes = 0; - // 执行次数 - public static $executeTimes = 0; - - /** - * 数据库初始化 并取得数据库类实例 - * @static - * @access public - * @param mixed $config 连接配置 - * @return Object 返回数据库驱动类 - */ - public static function connect($config = []) - { - $md5 = md5(serialize($config)); - if (!isset(self::$instances[$md5])) { - // 解析连接参数 支持数组和字符串 - $options = self::parseConfig($config); - if (empty($options['type'])) { - throw new Exception('db type error'); - } - $class = (!empty($options['namespace']) ? $options['namespace'] : '\\think\\db\\driver\\') . ucwords($options['type']); - self::$instances[$md5] = new $class($options); - // 记录初始化信息 - APP_DEBUG && Log::record('[ DB ] INIT ' . $options['type'] . ':' . var_export($options, true), 'info'); - } - self::$instance = self::$instances[$md5]; - return self::$instance; - } - - /** - * 数据库连接参数解析 - * @static - * @access private - * @param mixed $config - * @return array - */ - private static function parseConfig($config) - { - if (empty($config)) { - $config = Config::get('database'); - if (Config::get('use_db_switch')) { - $status = Config::get('app_status'); - $config = $config[$status ?: 'default']; - } - } elseif (is_string($config) && false === strpos($config, '/')) { - // 支持读取配置参数 - $config = Config::get($config); - } - if (is_string($config)) { - return self::parseDsn($config); - } else { - return $config; - } - } - - /** - * DSN解析 - * 格式: mysql://username:passwd@localhost:3306/DbName?param1=val1¶m2=val2#utf8 - * @static - * @access private - * @param string $dsnStr - * @return array - */ - private static function parseDsn($dsnStr) - { - $info = parse_url($dsnStr); - if (!$info) { - return []; - } - $dsn = [ - 'type' => $info['scheme'], - 'username' => isset($info['user']) ? $info['user'] : '', - 'password' => isset($info['pass']) ? $info['pass'] : '', - 'hostname' => isset($info['host']) ? $info['host'] : '', - 'hostport' => isset($info['port']) ? $info['port'] : '', - 'database' => !empty($info['path']) ? ltrim($info['path'], '/') : '', - 'charset' => isset($info['fragment']) ? $info['fragment'] : 'utf8', - ]; - - if (isset($info['query'])) { - parse_str($info['query'], $dsn['params']); - } else { - $dsn['params'] = []; - } - return $dsn; - } - - // 调用驱动类的方法 - public static function __callStatic($method, $params) - { - if (is_null(self::$instance)) { - // 自动初始化数据库 - self::connect(); - } - return call_user_func_array([self::$instance, $method], $params); - } -} diff --git a/thinkphp/library/think/Debug.php b/thinkphp/library/think/Debug.php deleted file mode 100644 index 04249ff67..000000000 --- a/thinkphp/library/think/Debug.php +++ /dev/null @@ -1,180 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -class Debug -{ - // 区间时间信息 - protected static $info = []; - // 区间内存信息 - protected static $mem = []; - - /** - * 记录时间(微秒)和内存使用情况 - * @param string $name 标记位置 - * @param mixed $value 标记值 留空则取当前 time 表示仅记录时间 否则同时记录时间和内存 - * @return mixed - */ - public static function remark($name, $value = '') - { - // 记录时间和内存使用 - self::$info[$name] = is_float($value) ? $value : microtime(true); - if ('time' != $value) { - self::$mem['mem'][$name] = is_float($value) ? $value : memory_get_usage(); - self::$mem['peak'][$name] = memory_get_peak_usage(); - } - } - - /** - * 统计某个区间的时间(微秒)使用情况 - * @param string $start 开始标签 - * @param string $end 结束标签 - * @param integer|string $dec 小数位 - * @return integer - */ - public static function getRangeTime($start, $end, $dec = 6) - { - if (!isset(self::$info[$end])) { - self::$info[$end] = microtime(true); - } - return number_format((self::$info[$end] - self::$info[$start]), $dec); - } - - /** - * 统计从开始到统计时的时间(微秒)使用情况 - * @param integer|string $dec 小数位 - * @return integer - */ - public static function getUseTime($dec = 6) - { - return number_format((microtime(true) - START_TIME), $dec); - } - - /** - * 获取当前访问的吞吐率情况 - * @return string - */ - public static function getThroughputRate() - { - return number_format(1 / self::getUseTime(), 2) . 'req/s'; - } - - /** - * 记录区间的内存使用情况 - * @param string $start 开始标签 - * @param string $end 结束标签 - * @param integer|string $dec 小数位 - * @return string - */ - public static function getRangeMem($start, $end, $dec = 2) - { - if (!isset(self::$mem['mem'][$end])) { - self::$mem['mem'][$end] = memory_get_usage(); - } - $size = self::$mem['mem'][$end] - self::$mem['mem'][$start]; - $a = ['B', 'KB', 'MB', 'GB', 'TB']; - $pos = 0; - while ($size >= 1024) { - $size /= 1024; - $pos++; - } - return round($size, $dec) . " " . $a[$pos]; - } - - /** - * 统计从开始到统计时的内存使用情况 - * @param integer|string $dec 小数位 - * @return string - */ - public static function getUseMem($dec = 2) - { - $size = memory_get_usage() - START_MEM; - $a = ['B', 'KB', 'MB', 'GB', 'TB']; - $pos = 0; - while ($size >= 1024) { - $size /= 1024; - $pos++; - } - return round($size, $dec) . " " . $a[$pos]; - } - - /** - * 统计区间的内存峰值情况 - * @param string $start 开始标签 - * @param string $end 结束标签 - * @param integer|string $dec 小数位 - * @return mixed - */ - public static function getMemPeak($start, $end, $dec = 2) - { - if (!isset(self::$mem['peak'][$end])) { - self::$mem['peak'][$end] = memory_get_peak_usage(); - } - $size = self::$mem['peak'][$end] - self::$mem['peak'][$start]; - $a = ['B', 'KB', 'MB', 'GB', 'TB']; - $pos = 0; - while ($size >= 1024) { - $size /= 1024; - $pos++; - } - return round($size, $dec) . " " . $a[$pos]; - } - - /** - * 获取文件加载信息 - * @param bool $detail 是否显示详细 - * @return void - */ - public static function getFile($detail = false) - { - if ($detail) { - $files = get_included_files(); - $info = []; - foreach ($files as $key => $file) { - $info[] = $file . ' ( ' . number_format(filesize($file) / 1024, 2) . ' KB )'; - } - return $info; - } - return count(get_included_files()); - } - - /** - * 浏览器友好的变量输出 - * @param mixed $var 变量 - * @param boolean $echo 是否输出 默认为true 如果为false 则返回输出字符串 - * @param string $label 标签 默认为空 - * @return void|string - */ - public static function dump($var, $echo = true, $label = null) - { - $label = (null === $label) ? '' : rtrim($label) . ':'; - ob_start(); - var_dump($var); - $output = ob_get_clean(); - $output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', $output); - if (IS_CLI) { - $output = PHP_EOL . $label . $output . PHP_EOL; - } else { - if (!extension_loaded('xdebug')) { - $output = htmlspecialchars($output, ENT_QUOTES); - } - $output = '
' . $label . $output . '
'; - } - if ($echo) { - echo ($output); - return null; - } else { - return $output; - } - } - -} diff --git a/thinkphp/library/think/Error.php b/thinkphp/library/think/Error.php deleted file mode 100644 index acee443ed..000000000 --- a/thinkphp/library/think/Error.php +++ /dev/null @@ -1,134 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -class Error -{ - /** - * 自定义异常处理 - * @access public - * @param mixed $e 异常对象 - */ - public static function appException($e) - { - $error = [ - 'message' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'trace' => $e->getTraceAsString(), - 'code' => $e->getCode(), - ]; - // 发送http状态信息 - http_response_code(Config::get('exception_http_status')); - // 输出异常页面 - self::halt($error); - } - - /** - * 自定义错误处理 - * @access public - * @param int $errno 错误类型 - * @param string $errstr 错误信息 - * @param string $errfile 错误文件 - * @param int $errline 错误行数 - * @return void - */ - public static function appError($errno, $errstr, $errfile, $errline) - { - $errorStr = "[{$errno}] {$errstr} {$errfile} 第 {$errline} 行."; - switch ($errno) { - case E_USER_ERROR: - self::halt($errorStr, $errno); - break; - case E_STRICT: - case E_USER_WARNING: - case E_USER_NOTICE: - default: - Log::record($errorStr, 'notic'); - break; - } - } - - /** - * 应用关闭处理 - * @return void - */ - public static function appShutdown() - { - // 记录日志 - Log::save(); - if ($e = error_get_last()) { - switch ($e['type']) { - case E_ERROR: - case E_PARSE: - case E_CORE_ERROR: - case E_COMPILE_ERROR: - case E_USER_ERROR: - ob_end_clean(); - self::halt($e); - break; - } - } - } - - /** - * 错误输出 - * - * @param mixed $error 错误 - * @param int $code - */ - public static function halt($error, $code = 1) - { - $message = is_array($error) ? $error['message'] : $error; - $code = isset($error['code']) ? $error['code'] : $code; - - if (APP_DEBUG) { - //调试模式下输出错误信息 - if (!is_array($error)) { - $trace = debug_backtrace(); - $e['message'] = $error; - $e['code'] = $code; - $e['file'] = $trace[0]['file']; - $e['line'] = $trace[0]['line']; - ob_start(); - debug_print_backtrace(); - $e['trace'] = ob_get_clean(); - } else { - $e = $error; - } - } elseif (!IS_API) { - //否则定向到错误页面 - $error_page = Config::get('error_page'); - if (!empty($error_page)) { - header('Location: ' . $error_page); - } else { - $e['code'] = $code; - $e['message'] = Config::get('show_error_msg') ? $message : Config::get('error_message'); - } - } else { - $e = ['message' => $message, 'code' => $code]; - } - // 记录异常日志 - Log::write('[' . $e['code'] . '] ' . $e['message'] . '[' . $e['file'] . ' : ' . $e['line'] . ']', 'error'); - - $type = Config::get('default_return_type'); - if (!IS_API && 'html' == $type) { - include Config::get('exception_tmpl'); - } else { - // 异常信息输出监听 - APP_HOOK && Hook::listen('error_output', $e); - // 输出异常内容 - Response::send($e, $type, Config::get('response_return')); - } - exit; - } -} diff --git a/thinkphp/library/think/Hook.php b/thinkphp/library/think/Hook.php deleted file mode 100644 index ade83e0bd..000000000 --- a/thinkphp/library/think/Hook.php +++ /dev/null @@ -1,130 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -class Hook -{ - - private static $tags = []; - - /** - * 动态添加行为扩展到某个标签 - * @param string $tag 标签名称 - * @param mixed $behavior 行为名称 - * @param bool $first 是否放到开头执行 - * @return void - */ - public static function add($tag, $behavior, $first = false) - { - if (!isset(self::$tags[$tag])) { - self::$tags[$tag] = []; - } - if (is_array($behavior)) { - self::$tags[$tag] = array_merge(self::$tags[$tag], $behavior); - } elseif ($first) { - array_unshift(self::$tags[$tag], $behavior); - } else { - self::$tags[$tag][] = $behavior; - } - } - - /** - * 批量导入插件 - * @param array $data 插件信息 - * @param boolean $recursive 是否递归合并 - * @return void - */ - public static function import($tags, $recursive = true) - { - if (!$recursive) { - // 覆盖导入 - self::$tags = array_merge(self::$tags, $tags); - } else { - // 合并导入 - foreach ($tags as $tag => $val) { - if (!isset(self::$tags[$tag])) { - self::$tags[$tag] = []; - } - - if (!empty($val['_overlay'])) { - // 可以针对某个标签指定覆盖模式 - unset($val['_overlay']); - self::$tags[$tag] = $val; - } else { - // 合并模式 - self::$tags[$tag] = array_merge(self::$tags[$tag], $val); - } - } - } - } - - /** - * 获取插件信息 - * @param string $tag 插件位置 留空获取全部 - * @return array - */ - public static function get($tag = '') - { - if (empty($tag)) { - // 获取全部的插件信息 - return self::$tags; - } else { - return self::$tags[$tag]; - } - } - - /** - * 监听标签的行为 - * @param string $tag 标签名称 - * @param mixed $params 传入参数 - * @return void - */ - public static function listen($tag, &$params = null) - { - if (isset(self::$tags[$tag])) { - foreach (self::$tags[$tag] as $name) { - - if (APP_DEBUG) { - Debug::remark('behavior_start', 'time'); - } - - $result = self::exec($name, $tag, $params); - - if (APP_DEBUG) { - Debug::remark('behavior_end', 'time'); - Log::record('[ BEHAVIOR ] Run ' . $name . ' @' . $tag . ' [ RunTime:' . Debug::getRangeTime('behavior_start', 'behavior_end') . 's ]', 'log'); - } - if (false === $result) { - // 如果返回false 则中断行为执行 - return; - } - } - } - return; - } - - /** - * 执行某个行为 - * @param string $class 行为类名称 - * @param string $tag 方法名(标签名) - * @param Mixed $params 传人的参数 - * @return void - */ - public static function exec($class, $tag = '', &$params = null) - { - if ($class instanceof \Closure) { - return $class($params); - } - $obj = new $class(); - return ($tag && is_callable([$obj, $tag])) ? $obj->$tag($params) : $obj->run($params); - } -} diff --git a/thinkphp/library/think/Input.php b/thinkphp/library/think/Input.php deleted file mode 100644 index 73928820b..000000000 --- a/thinkphp/library/think/Input.php +++ /dev/null @@ -1,414 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -class Input -{ - // 全局过滤规则 - public static $filters; - - /** - * 获取get变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function get($name = '', $default = null, $filter = null, $merge = false) - { - return self::data($name, $default, $filter, $merge, $_GET); - } - - /** - * 获取post变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function post($name = '', $default = null, $filter = null, $merge = false) - { - return self::data($name, $default, $filter, $merge, $_POST); - } - - /** - * 获取put变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function put($name = '', $default = null, $filter = null, $merge = false) - { - static $_PUT = null; - if (is_null($_PUT)) { - parse_str(file_get_contents('php://input'), $_PUT); - } - return self::data($name, $default, $filter, $merge, $_PUT); - } - - /** - * 根据请求方法获取变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function param($name = '', $default = null, $filter = null, $merge = false) - { - switch ($_SERVER['REQUEST_METHOD']) { - case 'POST': - $method = 'post'; - break; - case 'PUT': - $method = 'put'; - break; - default: - $method = 'get'; - } - return self::$method($name, $default, $filter, $merge); - } - - /** - * 获取request变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function request($name = '', $default = null, $filter = null, $merge = false) - { - return self::data($name, $default, $filter, $merge, $_REQUEST); - } - - /** - * 获取session变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function session($name = '', $default = null, $filter = null, $merge = false) - { - return self::data($name, $default, $filter, $merge, $_SESSION); - } - - /** - * 获取cookie变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function cookie($name = '', $default = null, $filter = null, $merge = false) - { - return self::data($name, $default, $filter, $merge, $_COOKIE); - } - - /** - * 获取post变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function server($name = '', $default = null, $filter = null, $merge = false) - { - return self::data(strtoupper($name), $default, $filter, $merge, $_SERVER); - } - - /** - * 获取GLOBALS变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function globals($name = '', $default = null, $filter = null, $merge = false) - { - return self::data($name, $default, $filter, $merge, $GLOBALS); - } - - /** - * 获取环境变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function env($name = '', $default = null, $filter = null, $merge = false) - { - return self::data(strtoupper($name), $default, $filter, $merge, $_ENV); - } - - /** - * 获取PATH_INFO - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function path($name = '', $default = null, $filter = null, $merge = false) - { - if (!empty($_SERVER['PATH_INFO'])) { - $depr = \think\Config::get('pathinfo_depr'); - $input = explode($depr, trim($_SERVER['PATH_INFO'], $depr)); - return self::data($name, $default, $filter, $merge, $input); - } else { - return $default; - } - } - - /** - * 获取$_FILES - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string $filter 过滤方法 - * @param boolean $merge 是否与默认的过虑方法合并 - * @return mixed - */ - public static function file($name = '', $default = null, $filter = null, $merge = false) - { - return self::data($name, $default, $filter, $merge, $_FILES); - } - - /** - * 获取系统变量 支持过滤和默认值 - * @param string $name 字段名 - * @param mixed $default 默认值 - * @param mixed $filter 过滤函数 - * @param boolean $merge 是否与默认的过虑方法合并 - * @param array $input 数据源 - * @return mixed - */ - public static function data($name, $default = null, $filter = null, $merge = false, $input = null) - { - if (0 === strpos($name, '?')) { - return self::has(substr($name, 1), $input); - } - if (is_null($input) && !empty($name)) { - $input = $name; - $name = ''; - } - if (!empty($input)) { - $data = $input; - $name = (string) $name; - if ('' != $name) { - // 解析name - list($name, $type) = static::parseName($name); - // 按.拆分成多维数组进行判断 - foreach (explode('.', $name) as $val) { - if (isset($data[$val])) { - $data = $data[$val]; - } else { - // 无输入数据,返回默认值 - return $default; - } - } - } - - // 解析过滤器 - $filters = static::parseFilter($filter, $merge); - // 为方便传参把默认值附加在过滤器后面 - $filters[] = $default; - if (is_array($data)) { - array_walk_recursive($data, 'self::filter', $filters); - } else { - self::filter($data, $name ?: 0, $filters); - } - if (isset($type) && $data !== $default) { - // 强制类型转换 - static::typeCast($data, $type); - } - } else { - $data = $default; - } - return $data; - } - - /** - * 判断一个变量是否设置 - * @param string $name - * @param array $data - * @return bool - */ - public static function has($name, $data) - { - foreach (explode('.', $name) as $val) { - if (!isset($data[$val])) { - return false; - } - } - return true; - } - - /** - * 设置默认的过滤函数 - * @param string|array $name - * @return array - */ - public static function setFilter($name) - { - if (is_string($name)) { - $name = explode(',', $name); - } - static::$filters = $name; - } - - /** - * 过滤表单中的表达式 - * @param string $value - * @return void - */ - public static function filterExp(&$value) - { - // TODO 其他安全过滤 - - // 过滤查询特殊字符 - if (preg_match('/^(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN)$/i', $value)) { - $value .= ' '; - } - } - - /** - * 递归过滤给定的值 - * @param mixed $value 键值 - * @param mixed $key 键名 - * @param array $filters 过滤方法+默认值 - * @return mixed - */ - private static function filter(&$value, $key, $filters) - { - // 分离出默认值 - $default = array_pop($filters); - foreach ($filters as $filter) { - if (is_callable($filter)) { - // 调用函数过滤 - $value = call_user_func($filter, $value); - } else { - $begin = substr($filter, 0, 1); - if (in_array($begin, ['/', '#', '~']) && $begin == $end = substr($filter, -1)) { - // 正则过滤 - if (!preg_match($filter, $value)) { - // 匹配不成功返回默认值 - $value = $default; - break; - } - } else { - // filter函数不存在时, 则使用filter_var进行过滤 - // filter为非整形值时, 调用filter_id取得过滤id - $value = filter_var($value, is_int($filter) ? $filter : filter_id($filter)); - if (false === $value) { - // 不通过过滤器则返回默认值 - $value = $default; - break; - } - } - } - } - self::filterExp($value); - } - - /** - * 解析name - * @param string $name - * @return array 返回name和类型 - */ - private static function parseName($name) - { - return strpos($name, '/') ? explode('/', $name, 2) : [$name, 's']; - } - - /** - * 解析过滤器 - * @param mixed $filter - * @return array - */ - private static function parseFilter($filter, $merge = false) - { - if (is_null($filter)) { - $result = self::getFilter(); - } elseif (empty($filter)) { - $result = []; - } else { - if (is_array($filter)) { - $result = $filter; - } elseif (is_string($filter) && strpos($filter, ',')) { - $result = explode(',', $filter); - } else { - $result = [$filter]; - } - if ($merge) { - // 与默认的过滤函数合并 - $result = array_merge(self::getFilter(), array_diff($result, self::getFilter())); - } - } - return $result; - } - - /** - * 获取过滤方法 - * @return array - */ - private static function getFilter() - { - if (is_null(static::$filters)) { - // 从配置项中读取 - $filters = \think\Config::get('default_filter'); - static::$filters = empty($filters) ? [] : (is_array($filters) ? $filters : explode(',', $filters)); - } - return static::$filters; - } - - /** - * 强类型转换 - * @param string $data - * @param string $type - * @return mixed - */ - private static function typeCast(&$data, $type) - { - switch (strtolower($type)) { - // 数组 - case 'a': - $data = (array) $data; - break; - // 数字 - case 'd': - $data = (int) $data; - break; - // 浮点 - case 'f': - $data = (float) $data; - break; - // 布尔 - case 'b': - $data = (boolean) $data; - break; - // 字符串 - case 's': - default: - $data = (string) $data; - } - } -} diff --git a/thinkphp/library/think/Lang.php b/thinkphp/library/think/Lang.php deleted file mode 100644 index 54db3fc80..000000000 --- a/thinkphp/library/think/Lang.php +++ /dev/null @@ -1,136 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -class Lang -{ - // 语言参数 - private static $lang = []; - // 语言作用域 - private static $range = 'zh-cn'; - - // 设定语言参数的作用域(语言) - public static function range($range = '') - { - if ('' == $range) { - return self::$range; - } else { - self::$range = $range; - } - } - - /** - * 设置语言定义(不区分大小写) - * @param string|array $name 语言变量 - * @param string $value 语言值 - * @param string $range 作用域 - * @return mixed - */ - public static function set($name, $value = null, $range = '') - { - $range = $range ?: self::$range; - // 批量定义 - if (!isset(self::$lang[$range])) { - self::$lang[$range] = []; - } - if (is_array($name)) { - return self::$lang[$range] = array_merge(self::$lang[$range], array_change_key_case($name)); - } else { - return self::$lang[$range][strtolower($name)] = $value; - } - } - - /** - * 加载语言定义(不区分大小写) - * @param string $file 语言文件 - * @param string $range 作用域 - * @return mixed - */ - public static function load($file, $range = '') - { - $range = $range ?: self::$range; - if (!isset(self::$lang[$range])) { - self::$lang[$range] = []; - } - // 批量定义 - if (is_string($file)) { - $file = [$file]; - } - $lang = []; - foreach ($file as $_file) { - // 记录加载信息 - APP_DEBUG && Log::record('[ LANG ] ' . $file, 'info'); - $_lang = is_file($_file) ? include $_file : []; - $lang = array_merge($lang, array_change_key_case($_lang)); - } - if (!empty($lang)) { - self::$lang[$range] = array_merge(self::$lang[$range], $lang); - } - return self::$lang[$range]; - } - - /** - * 获取语言定义(不区分大小写) - * @param string|null $name 语言变量 - * @param array $vars 变量替换 - * @param string $range 作用域 - * @return mixed - */ - public static function get($name = null, $vars = [], $range = '') - { - $range = $range ?: self::$range; - // 空参数返回所有定义 - if (empty($name)) { - return self::$lang[$range]; - } - $key = strtolower($name); - $value = isset(self::$lang[$range][$key]) ? self::$lang[$range][$key] : $name; - if (is_array($vars) && !empty($vars)) { - // 支持变量 - $replace = array_keys($vars); - foreach ($replace as &$v) { - $v = '{$' . $v . '}'; - } - $value = str_replace($replace, $vars, $value); - } - return $value; - } - - /** - * 自动侦测设置获取语言选择 - * @return void - */ - public static function detect() - { - // 自动侦测设置获取语言选择 - $langCookieVar = Config::get('lang_cookie_var'); - $langDetectVar = Config::get('lang_detect_var'); - $langSet = ''; - if (isset($_GET[$langDetectVar])) { - // url中设置了语言变量 - $langSet = strtolower($_GET[$langDetectVar]); - \think\Cookie::set($langCookieVar, $langSet, 3600); - } elseif (\think\Cookie::get($langCookieVar)) { - // 获取上次用户的选择 - $langSet = strtolower(\think\Cookie::get($langCookieVar)); - } elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { - // 自动侦测浏览器语言 - preg_match('/^([a-z\d\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches); - $langSet = strtolower($matches[1]); - \think\Cookie::set($langCookieVar, $langSet, 3600); - } - if (in_array($langSet, \think\Config::get('lang_list'))) { - // 合法的语言 - self::$range = $langSet; - } - } -} diff --git a/thinkphp/library/think/Loader.php b/thinkphp/library/think/Loader.php deleted file mode 100644 index fb58e6cea..000000000 --- a/thinkphp/library/think/Loader.php +++ /dev/null @@ -1,421 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -class Loader -{ - // 类名映射 - protected static $map = []; - // 加载列表 - protected static $load = []; - // 命名空间 - protected static $namespace = []; - // PSR-4 - private static $prefixLengthsPsr4 = []; - private static $prefixDirsPsr4 = []; - // PSR-0 - private static $prefixesPsr0 = []; - - // 自动加载 - public static function autoload($class) - { - // 检查是否定义类库映射 - if (isset(self::$map[$class])) { - if (is_file(self::$map[$class])) { - // 记录加载信息 - APP_DEBUG && self::$load[] = self::$map[$class]; - include self::$map[$class]; - } - } elseif ($file = self::findFileInComposer($class)) { - // Composer自动加载 - // 记录加载信息 - APP_DEBUG && self::$load[] = $file; - include $file; - } else { - // 命名空间自动加载 - list($name, $class) = explode('\\', $class, 2); - if (isset(self::$namespace[$name])) { - // 注册的命名空间 - $path = self::$namespace[$name]; - } elseif (in_array($name, ['think', 'behavior', 'traits']) || is_dir(LIB_PATH . $name)) { - // 核心类库命名空间 - $path = LIB_PATH . $name . DS; - } elseif (APP_NAMESPACE == $name) { - // 项目命名空间 - $path = APP_PATH; - } elseif (is_dir(EXTEND_PATH . $name)) { - // 扩展类库命名空间 - $path = EXTEND_PATH . $name . DS; - } else { - return; - } - $filename = $path . str_replace('\\', DS, $class) . EXT; - if (is_file($filename)) { - // 开启调试模式Win环境严格区分大小写 - if (APP_DEBUG && IS_WIN && false === strpos(realpath($filename), $class . EXT)) { - return; - } - // 记录加载信息 - APP_DEBUG && self::$load[] = $filename; - include $filename; - } else { - Log::record('autoloader error : ' . $filename, 'notic'); - } - } - } - - // 注册classmap - public static function addMap($class, $map = '') - { - if (is_array($class)) { - self::$map = array_merge(self::$map, $class); - } else { - self::$map[$class] = $map; - } - } - - // 注册命名空间 - public static function addNamespace($namespace, $path) - { - self::$namespace[$namespace] = $path; - } - - // 注册自动加载机制 - public static function register($autoload = '') - { - // 注册系统自动加载 - spl_autoload_register($autoload ? $autoload : 'think\\Loader::autoload'); - // 注册composer自动加载 - self::registerComposerLoader(); - } - - // 注册composer自动加载 - private static function registerComposerLoader() - { - if (is_file(VENDOR_PATH . 'composer/autoload_namespaces.php')) { - $map = require VENDOR_PATH . 'composer/autoload_namespaces.php'; - foreach ($map as $namespace => $path) { - self::$prefixesPsr0[$namespace[0]][$namespace] = (array) $path; - } - } - - if (is_file(VENDOR_PATH . 'composer/autoload_psr4.php')) { - $map = require VENDOR_PATH . 'composer/autoload_psr4.php'; - foreach ($map as $namespace => $path) { - $length = strlen($namespace); - if ('\\' !== $namespace[$length - 1]) { - throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); - } - self::$prefixLengthsPsr4[$namespace[0]][$namespace] = $length; - self::$prefixDirsPsr4[$namespace] = (array) $path; - } - } - - if (is_file(VENDOR_PATH . 'composer/autoload_classmap.php')) { - $classMap = require VENDOR_PATH . 'composer/autoload_classmap.php'; - if ($classMap) { - self::addMap($classMap); - } - } - - if (is_file(VENDOR_PATH . 'composer/autoload_files.php')) { - $includeFiles = require VENDOR_PATH . 'composer/autoload_files.php'; - foreach ($includeFiles as $fileIdentifier => $file) { - self::composerRequire($fileIdentifier, $file); - } - } - } - - private static function composerRequire($fileIdentifier, $file) - { - if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { - require $file; - $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; - } - } - - private static function findFileInComposer($class, $ext = '.php') - { - // PSR-4 lookup - $logicalPathPsr4 = strtr($class, '\\', DS) . $ext; - - $first = $class[0]; - if (isset(self::$prefixLengthsPsr4[$first])) { - foreach (self::$prefixLengthsPsr4[$first] as $prefix => $length) { - if (0 === strpos($class, $prefix)) { - foreach (self::$prefixDirsPsr4[$prefix] as $dir) { - if (file_exists($file = $dir . DS . substr($logicalPathPsr4, $length))) { - return $file; - } - } - } - } - } - // PSR-0 lookup - if (false !== $pos = strrpos($class, '\\')) { - // namespaced class name - $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) - . strtr(substr($logicalPathPsr4, $pos + 1), '_', DS); - } else { - // PEAR-like class name - $logicalPathPsr0 = strtr($class, '_', DS) . $ext; - } - - if (isset(self::$prefixesPsr0[$first])) { - foreach (self::$prefixesPsr0[$first] as $prefix => $dirs) { - if (0 === strpos($class, $prefix)) { - foreach ($dirs as $dir) { - if (file_exists($file = $dir . DS . $logicalPathPsr0)) { - return $file; - } - } - } - } - } - // Remember that this class does not exist. - return self::$map[$class] = false; - } - - /** - * 导入所需的类库 同java的Import 本函数有缓存功能 - * @param string $class 类库命名空间字符串 - * @param string $baseUrl 起始路径 - * @param string $ext 导入的文件扩展名 - * @return boolean - */ - public static function import($class, $baseUrl = '', $ext = EXT) - { - static $_file = []; - $class = str_replace(['.', '#'], [DS, '.'], $class); - if (isset($_file[$class . $baseUrl])) { - return true; - } else { - $_file[$class . $baseUrl] = true; - } - - if (empty($baseUrl)) { - list($name, $class) = explode(DS, $class, 2); - if (isset(self::$namespace[$name])) { - // 注册的命名空间 - $baseUrl = self::$namespace[$name]; - } elseif ('@' == $name || MODULE_NAME == $name) { - //加载当前模块应用类库 - $baseUrl = MODULE_PATH; - } elseif (in_array($name, ['traits', 'think', 'behavior']) || is_dir(LIB_PATH . $name)) { - $baseUrl = LIB_PATH; - } elseif (is_dir(EXTEND_PATH . $name)) { - $baseUrl = EXTEND_PATH; - } elseif (APP_NAMESPACE == $name) { - // 项目命名空间 - $baseUrl = APP_PATH; - } else { - // 加载其他模块应用类库 - $baseUrl = APP_PATH . $name . DS; - } - } elseif (substr($baseUrl, -1) != DS) { - $baseUrl .= DS; - } - // 如果类存在 则导入类库文件 - $filename = $baseUrl . $class . $ext; - if (is_file($filename)) { - // 开启调试模式Win环境严格区分大小写 - if (APP_DEBUG && IS_WIN && false === strpos(realpath($filename), $class . $ext)) { - return false; - } - include $filename; - return true; - } - return false; - } - - /** - * 实例化一个没有模型文件的Model(对应数据表) - * @param string $name Model名称 支持指定基础模型 例如 MongoModel:User - * @param array $options 模型参数 - * @return Model - */ - public static function table($name = '', array $options = []) - { - static $_model = []; - if (strpos($name, ':')) { - list($class, $name) = explode(':', $name); - } else { - $class = 'think\\Model'; - } - $guid = $name . '_' . $class; - if (!isset($_model[$guid])) { - $_model[$guid] = new $class($name, $options); - } - return $_model[$guid]; - } - - /** - * 实例化(分层)模型 - * @param string $name Model名称 - * @param string $layer 业务层名称 - * @return Object - */ - public static function model($name = '', $layer = MODEL_LAYER) - { - if (empty($name)) { - return new Model; - } - static $_model = []; - if (isset($_model[$name . $layer])) { - return $_model[$name . $layer]; - } - if (strpos($name, '/')) { - list($module, $name) = explode('/', $name, 2); - } else { - $module = MODULE_NAME; - } - $class = self::parseClass($module, $layer, $name); - $name = basename($name); - if (class_exists($class)) { - $model = new $class($name); - } else { - $class = str_replace('\\' . $module . '\\', '\\' . COMMON_MODULE . '\\', $class); - if (class_exists($class)) { - $model = new $class($name); - } else { - Log::record('实例化不存在的类:' . $class, 'notic'); - $model = new Model($name); - } - } - $_model[$name . $layer] = $model; - return $model; - } - - /** - * 实例化(分层)控制器 格式:[模块名/]控制器名 - * @param string $name 资源地址 - * @param string $layer 控制层名称 - * @param string $empty 空控制器名称 - * @return Object|false - */ - public static function controller($name, $layer = '', $empty = '') - { - static $_instance = []; - $layer = $layer ?: CONTROLLER_LAYER; - if (isset($_instance[$name . $layer])) { - return $_instance[$name . $layer]; - } - if (strpos($name, '/')) { - list($module, $name) = explode('/', $name); - } else { - $module = MODULE_NAME; - } - $class = self::parseClass($module, $layer, $name); - if (class_exists($class)) { - $action = new $class; - $_instance[$name . $layer] = $action; - return $action; - } elseif ($empty && class_exists($emptyClass = self::parseClass($module, $layer, $empty))) { - return new $emptyClass; - } else { - throw new Exception('class [ ' . $class . ' ] not exists', 10001); - } - } - - /** - * 实例化数据库 - * @param mixed $config 数据库配置 - * @return object - */ - public static function db($config = []) - { - return Db::connect($config); - } - - /** - * 远程调用模块的操作方法 参数格式 [模块/控制器/]操作 - * @param string $url 调用地址 - * @param string|array $vars 调用参数 支持字符串和数组 - * @param string $layer 要调用的控制层名称 - * @return mixed - */ - public static function action($url, $vars = [], $layer = CONTROLLER_LAYER) - { - $info = pathinfo($url); - $action = $info['basename']; - $module = '.' != $info['dirname'] ? $info['dirname'] : CONTROLLER_NAME; - $class = self::controller($module, $layer); - if ($class) { - if (is_string($vars)) { - parse_str($vars, $vars); - } - $method = new \ReflectionMethod($class, $action . Config::get('action_suffix')); - // 记录执行信息 - APP_DEBUG && Log::record('[ RUN ] ' . $method->getFileName(), 'info'); - return $method->invokeArgs($class, $vars); - } - } - /** - * 取得对象实例 支持调用类的静态方法 - * - * @param string $class 对象类名 - * @param string $method 类的静态方法名 - * - * @return mixed - * @throws Exception - */ - public static function instance($class, $method = '') - { - static $_instance = []; - $identify = $class . $method; - if (!isset($_instance[$identify])) { - if (class_exists($class)) { - $o = new $class(); - if (!empty($method) && method_exists($o, $method)) { - $_instance[$identify] = call_user_func_array([ & $o, $method], []); - } else { - $_instance[$identify] = $o; - } - } else { - throw new Exception('class not exist :' . $class, 10007); - } - } - return $_instance[$identify]; - } - - /** - * 字符串命名风格转换 - * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格 - * @param string $name 字符串 - * @param integer $type 转换类型 - * @return string - */ - public static function parseName($name, $type = 0) - { - if ($type) { - return ucfirst(preg_replace_callback('/_([a-zA-Z])/', function ($match) {return strtoupper($match[1]);}, $name)); - } else { - return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_")); - } - } - - /** - * 解析应用类的类名 - * @param string $module 模块名 - * @param string $layer 层名 controller model ... - * @param string $name 类名 - * @return string - */ - public static function parseClass($module, $layer, $name) - { - $name = str_replace(['/', '.'], '\\', $name); - $array = explode('\\', $name); - $class = self::parseName(array_pop($array), 1); - $path = $array ? implode('\\', $array) . '\\' : ''; - return APP_NAMESPACE . '\\' . (APP_MULTI_MODULE ? $module . '\\' : '') . $layer . '\\' . $path . $class; - } -} diff --git a/thinkphp/library/think/Log.php b/thinkphp/library/think/Log.php deleted file mode 100644 index aaecfbf23..000000000 --- a/thinkphp/library/think/Log.php +++ /dev/null @@ -1,130 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -class Log -{ - const LOG = 'log'; - const ERROR = 'error'; - const INFO = 'info'; - const SQL = 'sql'; - const NOTIC = 'notic'; - const ALERT = 'alert'; - - // 日志信息 - protected static $log = []; - // 日志类型 - protected static $type = ['log', 'error', 'info', 'sql', 'notic', 'alert']; - // 日志写入驱动 - protected static $driver = null; - // 通知发送驱动 - protected static $alarm = null; - - // 日志初始化 - public static function init($config = []) - { - $type = isset($config['type']) ? $config['type'] : 'File'; - $class = (!empty($config['namespace']) ? $config['namespace'] : '\\think\\log\\driver\\') . ucwords($type); - unset($config['type']); - self::$driver = new $class($config); - // 记录初始化信息 - APP_DEBUG && Log::record('[ LOG ] INIT ' . $type . ':' . var_export($config, true), 'info'); - } - - // 通知初始化 - public static function alarm($config = []) - { - $type = isset($config['type']) ? $config['type'] : 'Email'; - $class = (!empty($config['namespace']) ? $config['namespace'] : '\\think\\log\\alarm\\') . ucwords($type); - unset($config['type']); - self::$alarm = new $class($config['alarm']); - // 记录初始化信息 - APP_DEBUG && Log::record('[ CACHE ] ALARM ' . $type . ':' . var_export($config, true), 'info'); - } - - /** - * 获取全部日志信息 - * @return array - */ - public static function getLog() - { - return self::$log; - } - - /** - * 记录调试信息 - * @param mixed $msg 调试信息 - * @param string $type 信息类型 - * @return void - */ - public static function record($msg, $type = 'log') - { - if (!is_string($msg)) { - $msg = var_export($msg, true); - } - self::$log[] = ['type' => $type, 'msg' => $msg]; - } - - /** - * 保存调试信息 - * @return void - */ - public static function save() - { - if (is_null(self::$driver)) { - self::init(Config::get('log')); - } - self::$driver->save(self::$log); - } - - /** - * 实时写入日志信息 并支持行为 - * @param mixed $msg 调试信息 - * @param string $type 信息类型 - * @return void - */ - public static function write($msg, $type = 'log') - { - if (!is_string($msg)) { - $msg = var_export($msg, true); - } - // 封装日志信息 - $log[] = ['type' => $type, 'msg' => $msg]; - - // 监听log_write - APP_HOOK && Hook::listen('log_write', $log); - if (is_null(self::$driver)) { - self::init(Config::get('log')); - } - // 写入日志 - self::$driver->save($log); - } - - /** - * 发送预警通知 - * @return void - */ - public static function send($msg) - { - self::$alarm && self::$alarm->send($msg); - } - - // 静态调用 - public static function __callStatic($method, $args) - { - if (in_array($method, self::$type)) { - array_push($args, $method); - return call_user_func_array('\\think\\Log::record', $args); - } - } - -} diff --git a/thinkphp/library/think/Model.php b/thinkphp/library/think/Model.php deleted file mode 100644 index 4da6c8db9..000000000 --- a/thinkphp/library/think/Model.php +++ /dev/null @@ -1,1727 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -class Model -{ - // 操作状态 - const MODEL_INSERT = 1; // 新增 - const MODEL_UPDATE = 2; // 更新 - const MODEL_BOTH = 3; // 全部 - const EXISTS_VALIDATE = 0; // 存在就验证 - const MUST_VALIDATE = 1; // 必须验证 - const VALUE_VALIDATE = 2; // 有值就验证 - // 当前数据库操作对象 - protected $db = null; - // 数据库对象池 - private $links = []; - // 主键名称 - protected $pk = 'id'; - // 数据表前缀 - protected $tablePrefix = null; - // 模型名称 - protected $name = ''; - // 数据库名称 - protected $dbName = ''; - //数据库配置 - protected $connection = []; - // 数据表名(不包含表前缀) - protected $tableName = ''; - // 实际数据表名(包含表前缀) - protected $trueTableName = ''; - // 最近错误信息 - protected $error = ''; - // 字段信息 - protected $fields = []; - // 数据信息 - protected $data = []; - // 数据副本 - protected $duplicate = []; - // 查询表达式参数 - protected $options = []; - // 命名范围定义 - protected $scope = []; - // 字段映射定义 - protected $map = []; - - /** - * 架构函数 - * @access public - * @param string $name 模型名称 - * @param array $config 模型配置 - */ - public function __construct($name = '', array $config = []) - { - // 模型初始化 - $this->_initialize(); - // 传入模型参数 - if (!empty($name)) { - $this->name = $name; - } elseif (empty($this->name)) { - $this->name = $this->getModelName(); - } - if (strpos($this->name, '.')) { - // 支持 数据库名.模型名的 定义 - list($this->dbName, $this->name) = explode('.', $this->name); - } - - if (!empty($config['prefix'])) { - $this->tablePrefix = $config['prefix']; - } elseif (is_null($this->tablePrefix)) { - $this->tablePrefix = Config::get('database.prefix'); - } - if (!empty($config['connection'])) { - $this->connection = $config['connection']; - } - if (!empty($config['table_name'])) { - $this->tableName = $config['table_name']; - } - if (!empty($config['true_table_name'])) { - $this->trueTableName = $config['true_table_name']; - } - if (!empty($config['db_name'])) { - $this->dbName = $config['db_name']; - } - - // 数据库初始化操作 - // 获取数据库操作对象 - // 当前模型有独立的数据库连接信息 - $this->db(0, $this->connection); - } - - /** - * 设置数据对象的值 - * @access public - * @param string $name 名称 - * @param mixed $value 值 - * @return void - */ - public function __set($name, $value) - { - // 设置数据对象属性 - $this->data[$name] = $value; - } - - /** - * 获取数据对象的值 - * @access public - * @param string $name 名称 - * @return mixed - */ - public function __get($name) - { - return isset($this->data[$name]) ? $this->data[$name] : null; - } - - /** - * 检测数据对象的值 - * @access public - * @param string $name 名称 - * @return boolean - */ - public function __isset($name) - { - return isset($this->data[$name]); - } - - /** - * 销毁数据对象的值 - * @access public - * @param string $name 名称 - * @return void - */ - public function __unset($name) - { - unset($this->data[$name]); - } - - /** - * 利用__call方法实现一些特殊的Model方法 - * @access public - * @param string $method 方法名称 - * @param array $args 调用参数 - * @return mixed - */ - public function __call($method, $args) - { - if (in_array(strtolower($method), ['count', 'sum', 'min', 'max', 'avg'], true)) { - // 统计查询的实现 - $field = isset($args[0]) ? $args[0] : '*'; - return $this->getField(strtoupper($method) . '(' . $field . ') AS tp_' . $method); - } elseif (strtolower(substr($method, 0, 5)) == 'getby') { - // 根据某个字段获取记录 - $field = Loader::parseName(substr($method, 5)); - $where[$field] = $args[0]; - return $this->where($where)->find(); - } elseif (strtolower(substr($method, 0, 10)) == 'getfieldby') { - // 根据某个字段获取记录的某个值 - $name = Loader::parseName(substr($method, 10)); - $where[$name] = $args[0]; - return $this->where($where)->getField($args[1]); - } elseif (isset($this->scope[$method])) { - // 命名范围的单独调用支持 - return $this->scope($method, $args[0]); - } else { - throw new Exception(__CLASS__ . ':' . $method . ' method not exist'); - } - } - - // 回调方法 初始化模型 - protected function _initialize() - {} - - /** - * 对写入到数据库的数据进行处理 - * @access protected - * @param mixed $data 要操作的数据 - * @param string $type insert 或者 update - * @return array - */ - protected function _write_data($data, $type) - { - if (!empty($this->duplicate)) { - // 存在数据副本 - $data = array_diff_assoc($data, $this->duplicate); - if (empty($data)) { - // 没有数据变化 - return []; - } - - if ('update' == $type) { - // 保留主键信息 - $pk = $this->getPk(); - if (is_array($pk)) { - foreach ($pk as $key) { - if (isset($this->duplicate[$key])) { - $data[$key] = $this->duplicate[$key]; - } - } - } elseif (isset($this->duplicate[$pk])) { - $data[$pk] = $this->duplicate[$pk]; - } - } - // 重置副本 - $this->duplicate = []; - } - // 检查字段映射 - if (!empty($this->map)) { - foreach ($this->map as $key => $val) { - if (isset($data[$key])) { - $data[$val] = $data[$key]; - unset($data[$key]); - } - } - } - $fields = $this->getDbFields(); - // 检查非数据字段 - if (!empty($fields)) { - foreach ($data as $key => $val) { - if (!in_array($key, $fields, true)) { - if (Config::get('db_fields_strict')) { - throw new Exception(' fields not exists :[' . $key . '=>' . $val . ']'); - } - unset($data[$key]); - } elseif (is_scalar($val) && empty($this->options['bind'][$key])) { - // 字段类型检查 - $this->_parseType($data, $key, $this->options['bind']); - } - } - } - // 安全过滤 - if (!empty($this->options['filter'])) { - $data = array_map($this->options['filter'], $data); - unset($this->options['filter']); - } - // 回调方法 - $this->_before_write($data); - return $data; - } - // 写入数据前的回调方法 包括新增和更新 - protected function _before_write(&$data) - {} - - /** - * 新增数据 - * @access public - * @param mixed $data 数据 - * @param boolean $replace 是否replace - * @return mixed - */ - public function add($data = '', $replace = false) - { - if (empty($data)) { - // 没有传递数据,获取当前数据对象的值 - if (!empty($this->data)) { - $data = $this->data; - // 重置数据 - $this->data = []; - } else { - $this->error = Lang::get('_DATA_TYPE_INVALID_'); - return false; - } - } - // 数据处理 - $data = $this->_write_data($data, 'insert'); - // 分析表达式 - $options = $this->_parseOptions(); - if (false === $this->_before_insert($data, $options)) { - return false; - } - // 写入数据到数据库 - $result = $this->db->insert($data, $options, $replace); - if (false !== $result && is_numeric($result)) { - $pk = $this->getPk(); - // 增加复合主键支持 - if (is_array($pk)) { - return $result; - } - $insertId = $this->getLastInsID(); - if ($insertId) { - // 自增主键返回插入ID - $data[$pk] = $insertId; - if (false === $this->_after_insert($data, $options)) { - return false; - } - return $insertId; - } - if (false === $this->_after_insert($data, $options)) { - return false; - } - } - return $result; - } - // 插入数据前的回调方法 - protected function _before_insert(&$data, $options = []) - {} - // 插入成功后的回调方法 - protected function _after_insert($data, $options = []) - {} - - public function addAll($dataList, $options = [], $replace = false) - { - if (empty($dataList)) { - $this->error = Lang::get('_DATA_TYPE_INVALID_'); - return false; - } - // 数据处理 - foreach ($dataList as $key => $data) { - $dataList[$key] = $this->_write_data($data, 'insert'); - } - // 分析表达式 - $options = $this->_parseOptions($options); - // 写入数据到数据库 - $result = $this->db->insertAll($dataList, $options, $replace); - if (false !== $result) { - $insertId = $this->getLastInsID(); - if ($insertId) { - return $insertId; - } - } - return $result; - } - - /** - * 保存数据 - * @access public - * @param mixed $data 数据 - * @return boolean - */ - public function save($data = '') - { - if (empty($data)) { - // 没有传递数据,获取当前数据对象的值 - if (!empty($this->data)) { - $data = $this->data; - // 重置数据 - $this->data = []; - } else { - $this->error = Lang::get('_DATA_TYPE_INVALID_'); - return false; - } - } - // 数据处理 - $data = $this->_write_data($data, 'update'); - if (empty($data)) { - // 没有数据则不执行 - $this->error = Lang::get('_DATA_TYPE_INVALID_'); - return false; - } - // 分析表达式 - $options = $this->_parseOptions(); - $pk = $this->getPk(); - if (!isset($options['where'])) { - // 如果存在主键数据 则自动作为更新条件 - if (is_string($pk) && isset($data[$pk])) { - $where[$pk] = $data[$pk]; - unset($data[$pk]); - } elseif (is_array($pk)) { - // 增加复合主键支持 - foreach ($pk as $field) { - if (isset($data[$field])) { - $where[$field] = $data[$field]; - } else { - // 如果缺少复合主键数据则不执行 - $this->error = Lang::get('_OPERATION_WRONG_'); - return false; - } - unset($data[$field]); - } - } - if (!isset($where)) { - // 如果没有任何更新条件则不执行 - $this->error = Lang::get('_OPERATION_WRONG_'); - return false; - } else { - $options['where'] = $where; - } - } - if (isset($options['where'][$pk])) { - $pkValue = $options['where'][$pk]; - } - if (false === $this->_before_update($data, $options)) { - return false; - } - $result = $this->db->update($data, $options); - if (false !== $result && is_numeric($result)) { - if (isset($pkValue)) { - $data[$pk] = $pkValue; - } - - $this->_after_update($data, $options); - } - return $result; - } - // 更新数据前的回调方法 - protected function _before_update(&$data, $options = []) - {} - // 更新成功后的回调方法 - protected function _after_update($data, $options = []) - {} - - /** - * 删除数据 - * @access public - * @param mixed $options 表达式 - * @return mixed - */ - public function delete($options = []) - { - $pk = $this->getPk(); - if (empty($options) && empty($this->options['where'])) { - // 如果删除条件为空 则删除当前数据对象所对应的记录 - if (!empty($this->data) && isset($this->data[$pk])) { - return $this->delete($this->data[$pk]); - } else { - return false; - } - } - if (is_numeric($options) || is_string($options)) { - // 根据主键删除记录 - if (strpos($options, ',')) { - $where[$pk] = ['IN', $options]; - } else { - $where[$pk] = $options; - } - $options = []; - $options['where'] = $where; - } - // 根据复合主键删除记录 - if (is_array($options) && (count($options) > 0) && is_array($pk)) { - $count = 0; - foreach (array_keys($options) as $key) { - if (is_int($key)) { - $count++; - } - } - if (count($pk) == $count) { - $i = 0; - foreach ($pk as $field) { - $where[$field] = $options[$i]; - unset($options[$i++]); - } - $options['where'] = $where; - } else { - return false; - } - } - // 分析表达式 - $options = $this->_parseOptions($options); - if (empty($options['where'])) { - // 如果条件为空 不进行删除操作 除非设置 1=1 - return false; - } - if (isset($options['where'][$pk])) { - $pkValue = $options['where'][$pk]; - } - $result = $this->db->delete($options); - if (false !== $result && is_numeric($result)) { - $data = []; - if (isset($pkValue)) { - $data[$pk] = $pkValue; - } - $this->_after_delete($data, $options); - } - // 返回删除记录个数 - return $result; - } - // 删除成功后的回调方法 - protected function _after_delete($data, $options = []) - {} - - /** - * 查询数据集 - * @access public - * @param mixed $options 表达式参数 - * @return mixed - */ - public function select($options = []) - { - $pk = $this->getPk(); - if (is_string($options) || is_numeric($options)) { - // 根据主键查询 - if (strpos($options, ',')) { - $where[$pk] = ['IN', $options]; - } else { - $where[$pk] = $options; - } - $options = []; - $options['where'] = $where; - } elseif (is_array($options) && (count($options) > 0) && is_array($pk)) { - // 根据复合主键查询 - $count = 0; - foreach (array_keys($options) as $key) { - if (is_int($key)) { - $count++; - } - } - if (count($pk) == $count) { - $i = 0; - foreach ($pk as $field) { - $where[$field] = $options[$i]; - unset($options[$i++]); - } - $options['where'] = $where; - } else { - return false; - } - } elseif (false === $options) { - // 用于子查询 不查询只返回SQL - $options['fetch_sql'] = true; - } - - // 分析表达式 - $options = $this->_parseOptions($options); - // 判断查询缓存 - if (isset($options['cache'])) { - $cache = $options['cache']; - $key = is_string($cache['key']) ? $cache['key'] : md5(serialize($options)); - $data = Cache::get($key); - if (false !== $data) { - return $data; - } - } - $resultSet = $this->db->select($options); - - if (!empty($resultSet)) { - // 有查询结果 - if (is_string($resultSet)) { - return $resultSet; - } - - // 数据列表读取后的处理 - $resultSet = $this->_read_datalist($resultSet, $options); - // 回调 - $this->_after_select($resultSet, $options); - if (isset($options['index'])) { - // 对数据集进行索引 - $index = explode(',', $options['index']); - foreach ($resultSet as $result) { - $_key = $result[$index[0]]; - if (isset($index[1]) && isset($result[$index[1]])) { - $cols[$_key] = $result[$index[1]]; - } else { - $cols[$_key] = $result; - } - } - $resultSet = $cols; - } - } - - if (isset($cache)) { - Cache::set($key, $resultSet, $cache['expire']); - } - return $resultSet; - } - - /** - * 数据列表读取后的处理 - * @access protected - * @param array $data 当前数据 - * @return array - */ - protected function _read_datalist($resultSet, $options) - { - $resultSet = array_map([$this, '_read_data'], $resultSet); - return $resultSet; - } - // 查询成功后的回调方法 - protected function _after_select(&$resultSet, $options = []) - {} - - /** - * 获取一条记录的某个字段值 - * @access public - * @param string $field 字段名 - * @param string $spea 字段数据间隔符号 NULL返回数组 - * @return mixed - */ - public function getField($field, $sepa = null) - { - $options['field'] = $field; - $options = $this->_parseOptions($options); - $field = trim($field); - // 判断查询缓存 - if (isset($options['cache'])) { - $cache = $options['cache']; - $key = is_string($cache['key']) ? $cache['key'] : md5($sepa . serialize($options)); - $data = Cache::get($key); - if (false !== $data) { - return $data; - } - } - if (strpos($field, ',')) { - // 多字段 - if (!isset($options['limit'])) { - $options['limit'] = is_numeric($sepa) ? $sepa : ''; - } - $resultSet = $this->db->select($options); - if (!empty($resultSet)) { - if (is_string($resultSet)) { - return $resultSet; - } - $_field = explode(',', $field); - $field = array_keys($resultSet[0]); - $key1 = array_shift($field); - $key2 = array_shift($field); - $cols = array(); - $count = count($_field); - foreach ($resultSet as $result) { - $name = $result[$key1]; - if (2 == $count) { - $cols[$name] = $result[$key2]; - } else { - $cols[$name] = is_string($sepa) ? implode($sepa, array_slice($result, 1)) : $result; - } - } - if (isset($cache)) { - Cache::set($key, $cols, $cache['expire']); - } - return $cols; - } - } else { - // 查找一条记录 - // 返回数据个数 - if (true !== $sepa) { - // 当sepa指定为true的时候 返回所有数据 - $options['limit'] = is_numeric($sepa) ? $sepa : 1; - } - $result = $this->db->select($options); - if (!empty($result)) { - if (is_string($result)) { - return $result; - } - if (true !== $sepa && 1 == $options['limit']) { - $data = reset($result[0]); - if (isset($cache)) { - Cache::set($key, $data, $cache['expire']); - } - return $data; - } - foreach ($result as $val) { - $array[] = $val[$field]; - } - if (isset($cache)) { - Cache::set($key, $array, $cache['expire']); - } - return $array; - } - } - return null; - } - - /** - * 设置记录的某个字段值 - * 支持使用数据库字段和方法 - * @access public - * @param string|array $field 字段名 - * @param string $value 字段值 - * @return boolean - */ - public function setField($field, $value = '') - { - if (is_array($field)) { - $data = $field; - } else { - $data[$field] = $value; - } - return $this->save($data); - } - - /** - * 字段值(延迟)增长 - * @access public - * @param string $field 字段名 - * @param integer $step 增长值 - * @param integer $lazyTime 延时时间(s) - * @return boolean - */ - public function setInc($field, $step = 1, $lazyTime = 0) - { - $condition = $this->options['where']; - if (empty($condition)) { - // 没有条件不做任何更新 - return false; - } - if ($lazyTime > 0) { - // 延迟写入 - $guid = md5($this->name . '_' . $field . '_' . serialize($condition)); - $step = $this->lazyWrite($guid, $step, $lazyTime); - if (empty($step)) { - return true; // 等待下次写入 - } elseif ($step < 0) { - $step = '-' . $step; - } - } - return $this->setField($field, ['exp', $field . '+' . $step]); - } - - /** - * 字段值(延迟)减少 - * @access public - * @param string $field 字段名 - * @param integer $step 减少值 - * @param integer $lazyTime 延时时间(s) - * @return boolean - */ - public function setDec($field, $step = 1, $lazyTime = 0) - { - $condition = $this->options['where']; - if (empty($condition)) { - // 没有条件不做任何更新 - return false; - } - if ($lazyTime > 0) { - // 延迟写入 - $guid = md5($this->name . '_' . $field . '_' . serialize($condition)); - $step = $this->lazyWrite($guid, -$step, $lazyTime); - if (empty($step)) { - return true; // 等待下次写入 - } elseif ($step > 0) { - $step = '-' . $step; - } - } - return $this->setField($field, ['exp', $field . '-' . $step]); - } - - /** - * 延时更新检查 返回false表示需要延时 - * 否则返回实际写入的数值 - * @access public - * @param string $guid 写入标识 - * @param integer $step 写入步进值 - * @param integer $lazyTime 延时时间(s) - * @return false|integer - */ - protected function lazyWrite($guid, $step, $lazyTime) - { - if (false !== ($value = Cache::get($guid))) { - // 存在缓存写入数据 - if (NOW_TIME > Cache::get($guid . '_time') + $lazyTime) { - // 延时更新时间到了,删除缓存数据 并实际写入数据库 - Cache::rm($guid); - Cache::rm($guid . '_time'); - return $value + $step; - } else { - // 追加数据到缓存 - Cache::set($guid, $value + $step, 0); - return false; - } - } else { - // 没有缓存数据 - Cache::set($guid, $step, 0); - // 计时开始 - Cache::set($guid . '_time', NOW_TIME, 0); - return false; - } - } - - /** - * 生成查询SQL 可用于子查询 - * @access public - * @return string - */ - public function buildSql() - { - return '( ' . $this->fetchSql(true)->select() . ' )'; - } - - /** - * 分析表达式(可用于查询或者写入操作) - * @access protected - * @param array $options 表达式参数 - * @return array - */ - protected function _parseOptions($options = []) - { - if (is_array($options)) { - $options = array_merge($this->options, $options); - } - - // 记录操作的模型名称 - $options['model'] = $this->name; - - if (isset($options['table'])) { - // 动态指定表名 - $fields = $this->db->getFields($options['table']); - $fields = $fields ? array_keys($fields) : false; - } else { - $options['table'] = $this->getTableName(); - $fields = $this->getDbFields(); - } - if (!empty($options['alias'])) { - $options['table'] .= ' ' . $options['alias']; - } - // 字段类型验证 - if (isset($options['where']) && is_array($options['where']) && !empty($fields)) { - // 对数组查询条件进行字段类型检查 - foreach ($options['where'] as $key => $val) { - $key = trim($key); - if (in_array($key, $fields, true)) { - if (is_scalar($val) && empty($options['bind'][$key])) { - $this->_parseType($options['where'], $key, $options['bind']); - } - } - } - } - // 查询过后清空sql表达式组装 避免影响下次查询 - $this->options = []; - // 表达式过滤 - $this->_options_filter($options); - return $options; - } - // 表达式过滤回调方法 - protected function _options_filter(&$options) - {} - - /** - * 数据类型检测 - * @access protected - * @param array $data 数据 - * @param string $key 字段名 - * @param array $bind 参数绑定列表 - * @return void - */ - protected function _parseType(&$data, $key, &$bind) - { - if (!isset($bind[$key]) && isset($this->fields['_type'][$key])) { - $fieldType = strtolower($this->fields['_type'][$key]); - if (false === strpos($fieldType, 'bigint') && false !== strpos($fieldType, 'int')) { - $bind[$key] = [$data[$key], \PDO::PARAM_INT]; - $data[$key] = ':' . $key; - } elseif (false !== strpos($fieldType, 'float') || false !== strpos($fieldType, 'double')) { - $bind[$key] = [$data[$key], \PDO::PARAM_INT]; - $data[$key] = ':' . $key; - } elseif (false !== strpos($fieldType, 'bool')) { - $bind[$key] = [$data[$key], \PDO::PARAM_BOOL]; - $data[$key] = ':' . $key; - } else { - $bind[$key] = [$data[$key], \PDO::PARAM_STR]; - $data[$key] = ':' . $key; - } - } - } - - /** - * 查询数据 - * @access public - * @param mixed $options 表达式参数 - * @return mixed - */ - public function find($options = []) - { - $pk = $this->getPk(); - if (is_numeric($options) || is_string($options)) { - $where[$pk] = $options; - $options = []; - $options['where'] = $where; - } - // 根据复合主键查找记录 - if (is_array($options) && is_array($pk) && (count($options) > 0)) { - // 根据复合主键查询 - $count = 0; - foreach (array_keys($options) as $key) { - if (is_int($key)) { - $count++; - } - } - if (count($pk) == $count) { - $i = 0; - foreach ($pk as $field) { - $where[$field] = $options[$i]; - unset($options[$i++]); - } - $options['where'] = $where; - } else { - return false; - } - } - // 总是查找一条记录 - $options['limit'] = 1; - // 分析表达式 - $options = $this->_parseOptions($options); - // 判断查询缓存 - if (isset($options['cache'])) { - $cache = $options['cache']; - $key = is_string($cache['key']) ? $cache['key'] : md5(serialize($options)); - $data = Cache::get($key); - if (false !== $data) { - $this->data = $data; - return $data; - } - } - $resultSet = $this->db->select($options); - - if (empty($resultSet)) { - // 查询结果为空 - return null; - } - if (is_string($resultSet)) { - return $resultSet; - } - // 数据处理 - $data = $this->_read_data($resultSet[0], $options); - // 回调 - $this->_after_find($data, $options); - if (isset($cache)) { - Cache::set($key, $data, $cache['expire']); - } - // 数据对象赋值 - $this->data = $data; - // 数据副本 - $this->duplicate = $data; - return $this->data; - } - - /** - * 数据读取后的处理 - * @access protected - * @param array $data 当前数据 - * @return array - */ - protected function _read_data($data, $options = []) - { - // 检查字段映射 - if (!empty($this->map)) { - foreach ($this->map as $key => $val) { - if (isset($data[$val])) { - $data[$key] = $data[$val]; - unset($data[$val]); - } - } - } - return $data; - } - // 数据读取成功后的回调方法 - protected function _after_find(&$result, $options = []) - {} - - /** - * 创建数据对象 但不保存到数据库 - * @access public - * @param mixed $data 创建数据 - * @param string $type 状态 - * @return mixed - */ - public function create($data = '', $type = '') - { - // 如果没有传值默认取POST数据 - if (empty($data)) { - $data = $_POST; - } elseif (is_object($data)) { - $data = get_object_vars($data); - } - // 验证数据 - if (empty($data) || !is_array($data)) { - $this->error = Lang::get('_DATA_TYPE_INVALID_'); - return false; - } - - // 状态 - $type = $type ? $type : (!empty($data[$this->getPk()]) ? self::MODEL_UPDATE : self::MODEL_INSERT); - - // 检测提交字段的合法性 - if (isset($this->options['field'])) { - // $this->field('field1,field2...')->create() - $fields = $this->options['field']; - unset($this->options['field']); - } elseif (self::MODEL_INSERT == $type && isset($this->insertFields)) { - $fields = $this->insertFields; - } elseif (self::MODEL_UPDATE == $type && isset($this->updateFields)) { - $fields = $this->updateFields; - } - if (isset($fields)) { - if (is_string($fields)) { - $fields = explode(',', $fields); - } - foreach ($data as $key => $val) { - if (!in_array($key, $fields)) { - unset($data[$key]); - } - } - } - // 过滤创建的数据 - $this->_create_filter($data); - // 赋值当前数据对象 - $this->data = $data; - // 返回创建的数据以供其他调用 - return $data; - } - // 数据对象创建后的回调方法 - protected function _create_filter(&$data) - {} - - /** - * 切换当前的数据库连接 - * @access public - * @param mixed $linkId 连接标识 - * @param mixed $config 数据库连接信息 - * @return Model - */ - public function db($linkId = '', $config = '') - { - if ('' === $linkId && $this->db) { - return $this->db; - } - - if (!isset($this->links[$linkId])) { - // 创建一个新的实例 - if (is_string($linkId) && '' == $config) { - $config = Config::get($linkId); - } - $this->links[$linkId] = Db::connect($config); - } elseif (null === $config) { - $this->links[$linkId]->close(); // 关闭数据库连接 - unset($this->links[$linkId]); - return; - } - - // 切换数据库连接 - $this->db = $this->links[$linkId]; - $this->_after_db(); - return $this; - } - // 数据库切换后回调方法 - protected function _after_db() - {} - - /** - * 得到当前的数据对象名称 - * @access public - * @return string - */ - public function getModelName() - { - if (empty($this->name)) { - $this->name = basename(get_class($this)); - } - return $this->name; - } - - /** - * 得到完整的数据表名 - * @access public - * @return string - */ - public function getTableName() - { - if (empty($this->trueTableName)) { - $tableName = !empty($this->tablePrefix) ? $this->tablePrefix : ''; - if (!empty($this->tableName)) { - $tableName .= $this->tableName; - } else { - $tableName .= Loader::parseName($this->name); - } - $this->trueTableName = strtolower($tableName); - } - return (!empty($this->dbName) ? $this->dbName . '.' : '') . $this->trueTableName; - } - - /** - * 返回模型的错误信息 - * @access public - * @return string - */ - public function getError() - { - return $this->error; - } - - /** - * 返回数据库的错误信息 - * @access public - * @return string - */ - public function getDbError() - { - return $this->db->getError(); - } - - /** - * 返回最后插入的ID - * @access public - * @return string - */ - public function getLastInsID() - { - return $this->db->getLastInsID(); - } - - /** - * 返回最后执行的sql语句 - * @access public - * @return string - */ - public function getLastSql() - { - return $this->db->getLastSql($this->name); - } - - /** - * 获取主键名称 - * @access public - * @return string - */ - public function getPk() - { - return $this->pk; - } - - /** - * 获取数据表字段信息 - * @access public - * @return array - */ - public function getDbFields() - { - if ($this->fields) { - $fields = $this->fields; - unset($fields['_type'], $fields['_pk']); - return $fields; - } else { - $tableName = $this->getTableName(); - $guid = md5($tableName); - $fields = Cache::get($guid); - if (!$fields) { - $fields = $this->db->getFields($tableName); - $this->fields = array_keys($fields); - foreach ($fields as $key => $val) { - // 记录字段类型 - $type[$key] = $val['type']; - if (!empty($val['primary'])) { - $pk[] = $key; - } - } - if (isset($pk)) { - // 设置主键 - $this->pk = count($pk) > 1 ? $pk : $pk[0]; - } else { - $this->pk = null; - } - // 记录字段类型信息 - $this->fields['_type'] = $type; - $this->fields['_pk'] = $this->pk; - APP_DEBUG && Cache::set($guid, $this->fields); - $fields = $this->fields; - } else { - $this->fields = $fields; - $this->pk = $fields['_pk']; - } - unset($fields['_type'], $fields['_pk']); - return $fields; - } - } - - /** - * SQL查询 - * @access public - * @param string $sql SQL指令 - * @param array $bind 参数绑定 - * @return mixed - */ - public function query($sql, $bind = []) - { - $sql = $this->parseSql($sql); - return $this->db->query($sql, $bind); - } - - /** - * 执行SQL语句 - * @access public - * @param string $sql SQL指令 - * @param array $bind 参数绑定 - * @return false | integer - */ - public function execute($sql, $bind = []) - { - $sql = $this->parseSql($sql); - return $this->db->execute($sql, $bind); - } - - /** - * 解析SQL语句 - * @access public - * @param string $sql SQL指令 - * @return string - */ - protected function parseSql($sql) - { - // 分析表达式 - $sql = strtr($sql, ['__TABLE__' => $this->getTableName(), '__PREFIX__' => $this->tablePrefix]); - $sql = $this->parseSqlTable($sql); - $this->db->setModel($this->name); - return $sql; - } - - /** - * 设置数据对象值 - * @access public - * @param mixed $data 数据 - * @return Model - */ - public function data($data = '') - { - if ('' === $data && !empty($this->data)) { - return $this->data; - } - if (is_object($data)) { - $data = get_object_vars($data); - } elseif (is_string($data)) { - parse_str($data, $data); - } elseif (!is_array($data)) { - throw new Exception('data type invalid', 10300); - } - $this->data = $data; - return $this; - } - - /** - * 查询SQL组装 join - * @access public - * @param mixed $join - * @param string $type JOIN类型 - * @return Model - */ - public function _join($join, $type = 'INNER') - { - if (is_array($join)) { - foreach ($join as $key => &$_join) { - $_join = $this->parseSqlTable($_join); - $_join = false !== stripos($_join, 'JOIN') ? $_join : $type . ' JOIN ' . $_join; - } - $this->options['join'] = $join; - } elseif (!empty($join)) { - $join = $this->parseSqlTable($join); - $this->options['join'][] = false !== stripos($join, 'JOIN') ? $join : $type . ' JOIN ' . $join; - } - return $this; - } - - /** - * 查询SQL组装 join - * @access public - * @param mixed $join 关联的表名 - * @param mixed $condition 条件 - * @param string $type JOIN类型 - * @return Model - */ - public function join($join, $condition = null, $type = 'INNER') - { - if (empty($join)) { - return $this; - } - - if (empty($condition)) { - if (is_array($join) && is_array($join[0])) { - // 如果为组数,则循环调用join - foreach ($join as $key => $value) { - if (is_array($value) && 2 <= count($value)) { - $this->join($value[0], $value[1], isset($value[2]) ? $value[2] : $type); - } - } - } else { - $this->_join($join, $condition); // 兼容原来的join写法 - } - } elseif (in_array(strtoupper($condition), array('INNER', 'LEFT', 'RIGHT', 'ALL'))) { - $this->_join($join, $condition); // 兼容原来的join写法 - } else { - $prefix = $this->tablePrefix; - // 传入的表名为数组 - if (is_array($join)) { - if (0 !== key($join)) { - // 键名为表名,键值作为表的别名 - $table = key($join) . ' ' . current($join); - } else { - $table = current($join); - } - if (isset($join[1])) { - // 第二个元素为字符串则把第二元素作为表前缀 - if (is_string($join[1])) { - $table = $join[1] . $table; - } - } else { - // 加上默认的表前缀 - $table = $prefix . $table; - } - } else { - $join = trim($join); - if (0 === strpos($join, '__')) { - $table = $this->parseSqlTable($join); - } elseif (false === strpos($join, '(') && !empty($prefix) && 0 !== strpos($join, $prefix)) { - // 传入的表名中不带有'('并且不以默认的表前缀开头时加上默认的表前缀 - $table = $prefix . $join; - } else { - $table = $join; - } - } - if (is_array($condition)) { - $condition = implode(' AND ', $condition); - } - $this->options['join'][] = strtoupper($type) . ' JOIN ' . $table . ' ON ' . $condition; - } - return $this; - } - - /** - * 查询SQL组装 union - * @access public - * @param mixed $union - * @param boolean $all - * @return Model - */ - public function union($union, $all = false) - { - if (empty($union)) { - return $this; - } - - if ($all) { - $this->options['union']['_all'] = true; - } - if (is_object($union)) { - $union = get_object_vars($union); - } - // 转换union表达式 - if (is_string($union)) { - $options = $this->parseSqlTable($union); - } elseif (is_array($union)) { - if (isset($union[0])) { - $this->options['union'] = array_merge($this->options['union'], $union); - return $this; - } else { - $options = $union; - } - } else { - throw new Exception('data type invalid', 10300); - } - $this->options['union'][] = $options; - return $this; - } - - /** - * 查询缓存 - * @access public - * @param mixed $key - * @param integer $expire - * @param string $type - * @return Model - */ - public function cache($key = true, $expire = null, $type = '') - { - // 增加快捷调用方式 cache(10) 等同于 cache(true, 10) - if (is_numeric($key) && is_null($expire)) { - $expire = $key; - $key = true; - } - if (false !== $key) { - $this->options['cache'] = ['key' => $key, 'expire' => $expire, 'type' => $type]; - } - return $this; - } - - /** - * 指定查询字段 支持字段排除 - * @access public - * @param mixed $field - * @param boolean $except 是否排除 - * @return Model - */ - public function field($field, $except = false) - { - if (true === $field) { - // 获取全部字段 - $fields = $this->getDbFields(); - $field = $fields ?: '*'; - } elseif ($except) { - // 字段排除 - if (is_string($field)) { - $field = explode(',', $field); - } - $fields = $this->getDbFields(); - $field = $fields ? array_diff($fields, $field) : $field; - } - $this->options['field'] = $field; - return $this; - } - - /** - * 调用命名范围 - * @access public - * @param mixed $scope 命名范围名称 支持多个 和直接定义 - * @param array $args 参数 - * @return Model - */ - public function scope($scope = '', $args = null) - { - if ('' === $scope) { - if (isset($this->scope['default'])) { - // 默认的命名范围 - $options = $this->scope['default']; - } else { - return $this; - } - } elseif (is_string($scope)) { - // 支持多个命名范围调用 用逗号分割 - $scopes = explode(',', $scope); - $options = []; - foreach ($scopes as $name) { - if (!isset($this->scope[$name])) { - continue; - } - $options = array_merge($options, $this->scope[$name]); - } - if (!empty($args) && is_array($args)) { - $options = array_merge($options, $args); - } - } elseif (is_array($scope)) { - // 直接传入命名范围定义 - $options = $scope; - } - - if (is_array($options) && !empty($options)) { - $this->options = array_merge($this->options, array_change_key_case($options)); - } - return $this; - } - - /** - * 指定查询条件 - * @access public - * @param mixed $where 条件表达式 - * @return Model - */ - public function where($where) - { - if (is_string($where) && '' != $where) { - $map = []; - $map['_string'] = $where; - $where = $map; - } - if (isset($this->options['where'])) { - $this->options['where'] = array_merge($this->options['where'], $where); - } else { - $this->options['where'] = $where; - } - return $this; - } - - /** - * 指定查询数量 - * @access public - * @param mixed $offset 起始位置 - * @param mixed $length 查询数量 - * @return Model - */ - public function limit($offset, $length = null) - { - if (is_null($length) && strpos($offset, ',')) { - list($offset, $length) = explode(',', $offset); - } - $this->options['limit'] = intval($offset) . ($length ? ',' . intval($length) : ''); - return $this; - } - - /** - * 指定分页 - * @access public - * @param mixed $page 页数 - * @param mixed $listRows 每页数量 - * @return Model - */ - public function page($page, $listRows = null) - { - if (is_null($listRows) && strpos($page, ',')) { - list($page, $listRows) = explode(',', $page); - } - $this->options['page'] = [intval($page), intval($listRows)]; - return $this; - } - - /** - * 指定数据表 - * @access public - * @param string $table 表名 - * @return Model - */ - public function table($table) - { - if (is_array($table)) { - $this->options['table'] = $table; - } elseif (!empty($table)) { - $this->options['table'] = $this->parseSqlTable($table); - } - return $this; - } - - /** - * USING支持 用于多表删除 - * @access public - * @param mixed $using - * @return Model - */ - public function using($using) - { - if (is_array($using)) { - $this->options['using'] = $using; - } elseif (!empty($using)) { - $this->options['using'] = $this->parseSqlTable($using); - } - return $this; - } - - /** - * 指定排序 order('id','desc') 或者 order(['id'=>'desc','create_time'=>'desc']) - * @access public - * @param string|array $field 排序字段 - * @param string $order 排序 - * @return Model - */ - public function order($field, $order = null) - { - if (is_string($field) && !empty($field) && is_null($order)) { - $this->options['order'][] = $field; - } elseif (is_string($field) && !empty($field) && is_string($order)) { - $this->options['order'][$field] = $order; - } elseif (is_array($field) && !empty($field)) { - $this->options['order'] = $field; - } - return $this; - } - - /** - * 指定group查询 - * @access public - * @param string $group GROUP - * @return Model - */ - public function group($group) - { - $this->options['group'] = $group; - return $this; - } - - /** - * 指定having查询 - * @access public - * @param string $having having - * @return Model - */ - public function having($having) - { - $this->options['having'] = $having; - return $this; - } - - /** - * 指定查询lock - * @access public - * @param boolean $lock 是否lock - * @return Model - */ - public function lock($lock = false) - { - $this->options['lock'] = $lock; - return $this; - } - - /** - * 指定distinct查询 - * @access public - * @param string $distinct 是否唯一 - * @return Model - */ - public function distinct($distinct) - { - $this->options['distinct'] = $distinct; - return $this; - } - - /** - * 指定数据表别名 - * @access public - * @param string $alias 数据表别名 - * @return Model - */ - public function alias($alias) - { - $this->options['alias'] = $alias; - return $this; - } - - /** - * 指定写入过滤方法 - * @access public - * @param string $filter 指定过滤方法 - * @return Model - */ - public function filter($filter) - { - $this->options['filter'] = $filter; - return $this; - } - - /** - * 对数据集进行索引 - * @access public - * @param string $index 索引名称 - * @return Model - */ - public function index($index) - { - $this->options['index'] = $index; - return $this; - } - - /** - * 指定强制索引 - * @access public - * @param string $force 索引名称 - * @return Model - */ - public function force($force) - { - $this->options['force'] = $force; - return $this; - } - - /** - * 参数绑定 - * @access public - * @param mixed $key 参数名 - * @param mixed $value 绑定的变量及绑定参数 - * @return Model - */ - public function bind($key, $value = false) - { - if (is_array($key)) { - $this->options['bind'] = $key; - } else { - $num = func_num_args(); - if ($num > 2) { - $params = func_get_args(); - array_shift($params); - $this->options['bind'][$key] = $params; - } else { - $this->options['bind'][$key] = $value; - } - } - return $this; - } - - /** - * 查询注释 - * @access public - * @param string $comment 注释 - * @return Model - */ - public function comment($comment) - { - $this->options['comment'] = $comment; - return $this; - } - - /** - * 获取执行的SQL语句 - * @access public - * @param boolean $fetch 是否返回sql - * @return Model - */ - public function fetchSql($fetch = true) - { - $this->options['fetch_sql'] = $fetch; - return $this; - } - - /** - * 设置字段映射 - * @access public - * @param mixed $map 映射名称或者映射数据 - * @param string $name 映射的字段 - * @return Model - */ - public function map($map, $name = '') - { - if (is_array($map)) { - $this->map = array_merge($this->map, $map); - } else { - $this->map[$map] = $name; - } - return $this; - } - - /** - * 设置从主服务器读取数据 - * @access public - * @return Model - */ - public function master() - { - $this->options['master'] = true; - return $this; - } - - /** - * 将SQL语句中的__TABLE_NAME__字符串替换成带前缀的表名(小写) - * @access protected - * @param string $sql sql语句 - * @return string - */ - protected function parseSqlTable($sql) - { - if (false !== strpos($sql, '__')) { - $prefix = $this->tablePrefix; - $sql = preg_replace_callback("/__([A-Z0-9_-]+)__/sU", function ($match) use ($prefix) { - return $prefix . strtolower($match[1]); - }, $sql); - } - return $sql; - } -} diff --git a/thinkphp/library/think/ORM.php b/thinkphp/library/think/ORM.php deleted file mode 100644 index 755ffff97..000000000 --- a/thinkphp/library/think/ORM.php +++ /dev/null @@ -1,78 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -class ORM -{ - protected static $instance = []; - protected static $config = []; - - /** - * 设置数据对象的值 - * @access public - * @param string $name 名称 - * @param mixed $value 值 - * @return void - */ - public function __set($name, $value) - { - self::__callStatic('__set', [$name, $value]); - } - - /** - * 获取数据对象的值 - * @access public - * @param string $name 名称 - * @return mixed - */ - public function __get($name) - { - return self::__callStatic('__get', [$name]); - } - - /** - * 检测数据对象的值 - * @access public - * @param string $name 名称 - * @return boolean - */ - public function __isset($name) - { - return self::__callStatic('__isset', [$name]); - } - - /** - * 销毁数据对象的值 - * @access public - * @param string $name 名称 - * @return void - */ - public function __unset($name) - { - self::__callStatic('__unset', [$name]); - } - - public function __call($method, $params) - { - return self::__callStatic($method, $params); - } - - public static function __callStatic($method, $params) - { - $name = basename(get_called_class()); - if (!isset(self::$instance[$name])) { - // 自动实例化模型类 - self::$instance[$name] = new \think\Model($name, static::$config); - } - return call_user_func_array([self::$instance[$name], $method], $params); - } -} diff --git a/thinkphp/library/think/Response.php b/thinkphp/library/think/Response.php deleted file mode 100644 index 4fd76d599..000000000 --- a/thinkphp/library/think/Response.php +++ /dev/null @@ -1,253 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -class Response -{ - // 输出数据的转换方法 - protected static $tramsform = null; - // 输出数据的类型 - protected static $type = ''; - // 输出数据 - protected static $data = ''; - // 是否exit - protected static $isExit = false; - - /** - * 发送数据到客户端 - * @access protected - * @param mixed $data 要返回的数据 - * @param String $type 返回数据格式 - * @param bool $return 是否返回数据 - * @return void - */ - public static function send($data = '', $type = '', $return = false) - { - $type = strtolower($type ?: self::$type); - - $headers = [ - 'json' => 'application/json', - 'xml' => 'text/xml', - 'html' => 'text/html', - 'jsonp' => 'application/javascript', - 'script' => 'application/javascript', - 'text' => 'text/plain', - ]; - - if (!headers_sent() && isset($headers[$type])) { - header('Content-Type:' . $headers[$type] . '; charset=utf-8'); - } - - $data = $data ?: self::$data; - if (is_callable(self::$tramsform)) { - $data = call_user_func_array(self::$tramsform, [$data]); - } else { - switch ($type) { - case 'json': - // 返回JSON数据格式到客户端 包含状态信息 - $data = json_encode($data, JSON_UNESCAPED_UNICODE); - break; - case 'jsonp': - // 返回JSON数据格式到客户端 包含状态信息 - $handler = !empty($_GET[Config::get('var_jsonp_handler')]) ? $_GET[Config::get('var_jsonp_handler')] : Config::get('default_jsonp_handler'); - $data = $handler . '(' . json_encode($data, JSON_UNESCAPED_UNICODE) . ');'; - break; - case '': - case 'html': - case 'text': - // 不做处理 - break; - default: - // 用于扩展其他返回格式数据 - APP_HOOK && Hook::listen('return_data', $data); - } - } - - if ($return) { - return $data; - } - - echo $data; - self::isExit() && exit(); - } - - /** - * 转换控制器输出的数据 - * @access public - * @param mixed $callback 调用的转换方法 - * @return void - */ - public static function tramsform($callback) - { - self::$tramsform = $callback; - } - - /** - * 输出类型设置 - * @access public - * @param string $type 输出内容的格式类型 - * @return void - */ - public static function type($type = null) - { - if (is_null($type)) { - return self::$type ?: Config::get('default_return_type'); - } - self::$type = $type; - } - - /** - * 输出数据设置 - * @access public - * @param mixed $data 输出数据 - * @return void - */ - public static function data($data) - { - self::$data = $data; - } - - /** - * 输出是否exit设置 - * @access public - * @param bool $exit 是否退出 - * @return void - */ - public static function isExit($exit = null) - { - if (is_null($exit)) { - return self::$isExit; - } - self::$isExit = (boolean) $exit; - } - - /** - * 返回封装后的API数据到客户端 - * @access public - * @param mixed $data 要返回的数据 - * @param integer $code 返回的code - * @param mixed $msg 提示信息 - * @param string $type 返回数据格式 - * @return void - */ - public static function result($data, $code = 0, $msg = '', $type = '') - { - $result = [ - 'code' => $code, - 'msg' => $msg, - 'time' => NOW_TIME, - 'data' => $data, - ]; - if ($type) { - self::type($type); - } - - return $result; - } - - /** - * 操作成功跳转的快捷方法 - * @access public - * @param mixed $msg 提示信息 - * @param mixed $data 返回的数据 - * @param mixed $url 跳转的URL地址 - * @param mixed $wait 跳转等待时间 - * @return void - */ - public static function success($msg = '', $data = '', $url = '', $wait = 3) - { - $code = 1; - if (is_numeric($msg)) { - $code = $msg; - $msg = ''; - } - $result = [ - 'code' => $code, - 'msg' => $msg, - 'data' => $data, - 'url' => $url ?: $_SERVER["HTTP_REFERER"], - 'wait' => $wait, - ]; - - $type = IS_AJAX ? Config::get('default_ajax_return') : Config::get('default_return_type'); - - if ('html' == $type) { - $result = \think\View::instance()->fetch(Config::get('dispatch_jump_tmpl'), $result); - } - self::type($type); - return $result; - } - - /** - * 操作错误跳转的快捷方法 - * @access public - * @param mixed $msg 提示信息 - * @param mixed $data 返回的数据 - * @param mixed $url 跳转的URL地址 - * @param mixed $wait 跳转等待时间 - * @return void - */ - public static function error($msg = '', $data = '', $url = '', $wait = 3) - { - $code = 0; - if (is_numeric($msg)) { - $code = $msg; - $msg = ''; - } - $result = [ - 'code' => $code, - 'msg' => $msg, - 'data' => $data, - 'url' => $url ?: 'javascript:history.back(-1);', - 'wait' => $wait, - ]; - - $type = IS_AJAX ? Config::get('default_ajax_return') : Config::get('default_return_type'); - - if ('html' == $type) { - $result = \think\View::instance()->fetch(Config::get('dispatch_jump_tmpl'), $result); - } - self::type($type); - return $result; - } - - /** - * URL重定向 - * @access protected - * @param string $url 跳转的URL表达式 - * @param array|int $params 其它URL参数或http code - * @return void - */ - public static function redirect($url, $params = []) - { - $http_response_code = 301; - if (in_array($params, [301, 302])) { - $http_response_code = $params; - $params = []; - } - $url = preg_match('/^(https?:|\/)/', $url) ? $url : Url::build($url, $params); - header('Location: ' . $url, true, $http_response_code); - } - - /** - * 设置响应头 - * @access protected - * @param string $name 参数名 - * @param string $value 参数值 - * @return void - */ - public static function header($name, $value) - { - header($name . ':' . $value); - } - -} diff --git a/thinkphp/library/think/Route.php b/thinkphp/library/think/Route.php deleted file mode 100644 index 693a9fc08..000000000 --- a/thinkphp/library/think/Route.php +++ /dev/null @@ -1,683 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -class Route -{ - // 路由规则 - private static $rules = [ - 'GET' => [], - 'POST' => [], - 'PUT' => [], - 'DELETE' => [], - 'HEAD' => [], - '*' => [], - ]; - - // REST路由操作方法定义 - private static $rest = [ - 'index' => ['GET', '', 'index'], - 'create' => ['GET', '/create', 'create'], - 'read' => ['GET', '/:id', 'read'], - 'edit' => ['GET', '/:id/edit', 'edit'], - 'save' => ['POST', '', 'save'], - 'update' => ['PUT', '/:id', 'update'], - 'delete' => ['DELETE', '/:id', 'delete'], - ]; - - // URL映射规则 - private static $map = []; - // 子域名部署规则 - private static $domain = []; - // 子域名 - private static $subDomain = ''; - // 变量规则 - private static $pattern = []; - // 域名绑定 - private static $bind = []; - - // 添加URL映射规则 - public static function map($map = '', $route = '') - { - return self::setting('map', $map, $route); - } - - // 添加变量规则 - public static function pattern($name = '', $rule = '') - { - return self::setting('pattern', $name, $rule); - } - - // 添加子域名部署规则 - public static function domain($domain = '', $rule = '') - { - return self::setting('domain', $domain, $rule); - } - - // 属性设置 - private static function setting($var, $name = '', $value = '') - { - if (is_array($name)) { - self::${$var} = self::${$var}+$name; - } elseif (empty($name)) { - return self::${$var}; - } else { - self::${$var}[$name] = $value; - } - } - - // 对路由进行绑定和获取绑定信息 - public static function bind($type, $bind = '') - { - if ('' == $bind) { - return isset(self::$bind[$type]) ? self::$bind[$type] : null; - } else { - self::$bind = ['type' => $type, $type => $bind]; - } - } - - // 注册路由规则 - public static function register($rule, $route = '', $type = '*', $option = [], $pattern = []) - { - if (strpos($type, '|')) { - foreach (explode('|', $type) as $val) { - self::register($rule, $route, $val, $option); - } - } else { - if (is_array($rule)) { - // 检查域名部署 - if (isset($rule['__domain__'])) { - self::domain($rule['__domain__']); - unset($rule['__domain__']); - } - // 检查变量规则 - if (isset($rule['__pattern__'])) { - self::pattern($rule['__pattern__']); - unset($rule['__pattern__']); - } - // 检查路由映射 - if (isset($rule['__map__'])) { - self::map($rule['__map__']); - unset($rule['__map__']); - } - // 检查资源路由 - if (isset($rule['__rest__'])) { - self::resource($rule['__rest__']); - unset($rule['__rest__']); - } - - foreach ($rule as $key => $val) { - if (is_numeric($key)) { - $key = array_shift($val); - } - if (0 === strpos($key, '[')) { - if (empty($val)) { - break; - } - $key = substr($key, 1, -1); - $result = ['routes' => $val, 'option' => $option, 'pattern' => $pattern]; - } elseif (is_array($val)) { - $result = ['route' => $val[0], 'option' => $val[1], 'pattern' => $val[2]]; - } else { - $result = ['route' => $val, 'option' => $option, 'pattern' => $pattern]; - } - self::$rules[$type][$key] = $result; - } - } else { - if (0 === strpos($rule, '[')) { - $rule = substr($rule, 1, -1); - $result = ['routes' => $route, 'option' => $option, 'pattern' => $pattern]; - } elseif (is_array($route)) { - $result = ['route' => !empty($route[0]) ? $route[0] : '', 'option' => !empty($route[1]) ? $route[1] : '', 'pattern' => !empty($route[2]) ? $route[2] : '']; - } else { - $result = ['route' => $route, 'option' => $option, 'pattern' => $pattern]; - } - self::$rules[$type][$rule] = $result; - } - } - } - - // 路由分组 - public static function group($name, $routes = [], $type = '*', $option = [], $pattern = []) - { - self::$rules[$type][$name] = ['routes' => $routes, 'option' => $option, 'pattern' => $pattern]; - } - - // 注册任意请求的路由规则 - public static function any($rule, $route = '', $option = [], $pattern = []) - { - self::register($rule, $route, '*', $option, $pattern); - } - - // 注册get请求的路由规则 - public static function get($rule, $route = '', $option = [], $pattern = []) - { - self::register($rule, $route, 'GET', $option, $pattern); - } - - // 注册post请求的路由规则 - public static function post($rule, $route = '', $option = [], $pattern = []) - { - self::register($rule, $route, 'POST', $option, $pattern); - } - - // 注册put请求的路由规则 - public static function put($rule, $route = '', $option = [], $pattern = []) - { - self::register($rule, $route, 'PUT', $option, $pattern); - } - - // 注册delete请求的路由规则 - public static function delete($rule, $route = '', $option = [], $pattern = []) - { - self::register($rule, $route, 'DELETE', $option, $pattern); - } - - // 注册资源路由 - public static function resource($rule, $route = '', $option = [], $pattern = []) - { - if (is_array($rule)) { - foreach ($rule as $key => $val) { - if (is_array($val)) { - list($val, $option, $pattern) = array_pad($val, 3, []); - } - self::resource($key, $val, $option, $pattern); - } - } else { - if (strpos($rule, '.')) { - // 注册嵌套资源路由 - $array = explode('.', $rule); - $last = array_pop($array); - $item = []; - foreach ($array as $val) { - $item[] = $val . '/:' . (isset($option['var'][$val]) ? $option['var'][$val] : $val . '_id'); - } - $rule = implode('/', $item) . '/' . $last; - } - // 注册资源路由 - foreach (self::$rest as $key => $val) { - if ((isset($option['only']) && !in_array($key, $option['only'])) - || (isset($option['except']) && in_array($key, $option['except']))) { - continue; - } - if (strpos($val[1], ':id') && isset($option['var'][$rule])) { - $val[1] = str_replace(':id', ':' . $option['var'][$rule], $val[1]); - } - self::register($rule . $val[1] . '$', $route . '/' . $val[2], $val[0], $option, $pattern); - } - } - } - - // rest方法定义和修改 - public static function rest($name, $resource = []) - { - if (is_array($name)) { - self::$rest = array_merge(self::$rest, $name); - } else { - self::$rest[$name] = $resource; - } - } - - // 获取路由定义 - public static function getRules($method = '') - { - if ($method) { - return self::$rules[$method]; - } else { - return self::$rules['*'] + self::$rules['GET'] + self::$rules['POST'] + self::$rules['PUT'] + self::$rules['DELETE']; - } - } - - // 检测子域名部署 - public static function checkDomain() - { - // 域名规则 - $rules = self::$domain; - // 开启子域名部署 支持二级和三级域名 - if (!empty($rules)) { - if (isset($rules[$_SERVER['HTTP_HOST']])) { - // 完整域名或者IP配置 - $rule = $rules[$_SERVER['HTTP_HOST']]; - } else { - $rootDomain = Config::get('url_domain_root'); - if ($rootDomain) { - // 配置域名根 例如 thinkphp.cn 163.com.cn 如果是国家级域名 com.cn net.cn 之类的域名需要配置 - $domain = explode('.', rtrim(stristr($_SERVER['HTTP_HOST'], $rootDomain, true), '.')); - } else { - $domain = explode('.', $_SERVER['HTTP_HOST'], -2); - } - // 子域名配置 - if (!empty($domain)) { - // 当前子域名 - $subDomain = implode('.', $domain); - self::$subDomain = $subDomain; - $domain2 = array_pop($domain); - if ($domain) { - // 存在三级域名 - $domain3 = array_pop($domain); - } - if ($subDomain && isset($rules[$subDomain])) { - // 子域名配置 - $rule = $rules[$subDomain]; - } elseif (isset($rules['*.' . $domain2]) && !empty($domain3)) { - // 泛三级域名 - $rule = $rules['*.' . $domain2]; - $panDomain = $domain3; - } elseif (isset($rules['*']) && !empty($domain2)) { - // 泛二级域名 - if ('www' != $domain2) { - $rule = $rules['*']; - $panDomain = $domain2; - } - } - } - } - if (!empty($rule)) { - // 子域名部署规则 - if ($rule instanceof \Closure) { - // 执行闭包 - $reflect = new \ReflectionFunction($rule); - self::$bind = $reflect->invokeArgs([]); - return; - } - - if (strpos($rule, '?')) { - // 传入其它参数 - $array = parse_url($rule); - $result = $array['path']; - parse_str($array['query'], $params); - if (isset($panDomain)) { - $pos = array_search('*', $params); - if (false !== $pos) { - // 泛域名作为参数 - $params[$pos] = $panDomain; - } - } - $_GET = array_merge($_GET, $params); - } else { - $result = $rule; - } - - if (0 === strpos($result, '\\')) { - // 绑定到命名空间 例如 \app\index\behavior - self::$bind = ['type' => 'namespace', 'namespace' => $result]; - } elseif (0 === strpos($result, '@')) { - // 绑定到类 例如 \app\index\controller\User - self::$bind = ['type' => 'class', 'class' => substr($result, 1)]; - } elseif (0 === strpos($result, '[')) { - // 绑定到分组 例如 [user] - self::$bind = ['type' => 'group', 'group' => substr($result, 1, -1)]; - } else { - // 绑定到模块/控制器 例如 index/user - self::$bind = ['type' => 'module', 'module' => $result]; - } - } - } - } - - // 检测URL路由 - public static function check($url, $depr = '/', $checkDomain = false) - { - // 分隔符替换 确保路由定义使用统一的分隔符 - if ('/' != $depr) { - $url = str_replace($depr, '/', $url); - } - - // 优先检测是否存在PATH_INFO - if (empty($url)) { - $url = '/'; - } - - if (isset(self::$map[$url])) { - // URL映射 - return self::parseUrl(self::$map[$url], $depr); - } - - // 获取当前请求类型的路由规则 - $rules = self::$rules[REQUEST_METHOD]; - - if (!empty(self::$rules['*'])) { - // 合并任意请求的路由规则 - $rules = array_merge(self::$rules['*'], $rules); - } - - // 检测域名部署 - if ($checkDomain) { - self::checkDomain(); - } - - // 检测URL绑定 - $return = self::checkUrlBind($url, $rules); - if ($return) { - return $return; - } - - // 路由规则检测 - if (!empty($rules)) { - foreach ($rules as $rule => $val) { - $option = $val['option']; - $pattern = $val['pattern']; - - // 参数有效性检查 - if (!self::checkOption($option, $url)) { - continue; - } - - if (!empty($val['routes'])) { - // 分组路由 - if (0 !== strpos($url, $rule)) { - continue; - } - // 匹配到路由分组 - foreach ($val['routes'] as $key => $route) { - if (is_numeric($key)) { - $key = array_shift($route); - } - $url1 = substr($url, strlen($rule) + 1); - // 检查规则路由 - if (is_array($route)) { - $option1 = $route[1]; - // 检查参数有效性 - if (!self::checkOption($option1, $url)) { - continue; - } - $pattern = array_merge($pattern, isset($route[2]) ? $route[2] : []); - $route = $route[0]; - } - $result = self::checkRule($key, $route, $url1, $pattern, $option1); - if (false !== $result) { - return $result; - } - } - } else { - if (is_numeric($rule)) { - $rule = array_shift($val); - } - // 单项路由 - $route = !empty($val['route']) ? $val['route'] : ''; - // 规则路由 - $result = self::checkRule($rule, $route, $url, $pattern, $option); - if (false !== $result) { - return $result; - } - } - } - } - return false; - } - - // 检测URL绑定 - private static function checkUrlBind(&$url, &$rules) - { - if (!empty(self::$bind['type'])) { - // 记录绑定信息 - APP_DEBUG && Log::record('[ BIND ] ' . var_export(self::$bind, true), 'info'); - // 如果有URL绑定 则进行绑定检测 - switch (self::$bind['type']) { - case 'class': - // 绑定到类 - $array = explode('/', $url, 2); - if (!empty($array[1])) { - self::parseUrlParams($array[1]); - } - return ['type' => 'method', 'method' => [self::$bind['class'], $array[0] ?: Config::get('default_action')], 'params' => []]; - case 'namespace': - // 绑定到命名空间 - $array = explode('/', $url, 3); - $class = !empty($array[0]) ? $array[0] : Config::get('default_controller'); - $method = !empty($array[1]) ? $array[1] : Config::get('default_action'); - if (!empty($array[2])) { - self::parseUrlParams($array[2]); - } - return ['type' => 'method', 'method' => [self::$bind['namespace'] . '\\' . $class, $method], 'params' => []]; - case 'module': - // 如果有模块/控制器绑定 针对路由到 模块/控制器 有效 - $url = self::$bind['module'] . '/' . $url; - break; - case 'group': - // 绑定到路由分组 - $key = self::$bind['group']; - if (array_key_exists($key, $rules)) { - $rules = [$key => $rules[self::$bind['group']]]; - } - } - } - return false; - } - - // 路由参数有效性检查 - private static function checkOption($option, $url) - { - // 请求类型检测 - if ((isset($option['method']) && false === stripos($option['method'], REQUEST_METHOD)) - || (isset($option['ext']) && false === stripos($option['ext'], __EXT__)) // 伪静态后缀检测 - || (isset($option['domain']) && !in_array($option['domain'], [$_SERVER['HTTP_HOST'], self::$subDomain])) // 域名检测 - || (!empty($option['https']) && !self::isSsl()) // https检测 - || (!empty($option['before_behavior']) && false === Hook::exec($option['before_behavior'], $url)) // 行为检测 - || (!empty($option['callback']) && is_callable($option['callback']) && false === call_user_func($option['callback'])) // 自定义检测 - ) { - return false; - } - return true; - } - - /** - * 检查规则路由 - */ - private static function checkRule($rule, $route, $url, $pattern, $option) - { - // 检查完整规则定义 - if (isset($pattern['__url__']) && !preg_match('/^' . $pattern['__url__'] . '/', $url)) { - return false; - } - // 检测是否设置了参数分隔符 - if ($depr = Config::get('url_params_depr')) { - $url = str_replace($depr, '/', $url); - $rule = str_replace($depr, '/', $rule); - } - $len1 = substr_count($url, '/'); - $len2 = substr_count($rule, '/'); - if ($len1 >= $len2 || strpos($rule, '[')) { - if ('$' == substr($rule, -1, 1)) { - // 完整匹配 - if ($len1 != $len2) { - return false; - } else { - $rule = substr($rule, 0, -1); - } - } - $pattern = array_merge(self::$pattern, $pattern); - if (false !== $match = self::match($url, $rule, $pattern)) { - // 匹配到路由规则 - // 检测是否定义路由 - if ($option['after_behavior']) { - Hook::exec($option['after_behavior'], $route); - } - if ($route instanceof \Closure) { - // 执行闭包 - return ['type' => 'function', 'function' => $route, 'params' => $match]; - } - return self::parseRule($rule, $route, $url); - } - } - return false; - } - - /** - * 判断是否SSL协议 - * @return boolean - */ - public static function isSsl() - { - if (isset($_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))) { - return true; - } elseif (isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'])) { - return true; - } else { - return false; - } - } - - // 解析模块的URL地址 [模块/控制器/操作?]参数1=值1&参数2=值2... - public static function parseUrl($url, $depr = '/') - { - if (isset(self::$bind['module'])) { - // 如果有模块/控制器绑定 - $url = self::$bind['module'] . '/' . $url; - } - // 分隔符替换 确保路由定义使用统一的分隔符 - if ('/' != $depr) { - $url = str_replace($depr, '/', $url); - } - $result = self::parseRoute($url, true); - if (!empty($result['var'])) { - $_GET = array_merge($result['var'], $_GET); - } - return ['type' => 'module', 'module' => $result['route']]; - } - - // 解析规范的路由地址 - // 地址格式 [模块/控制器/操作?]参数1=值1&参数2=值2... - private static function parseRoute($url, $reverse = false) - { - $var = []; - if (false !== strpos($url, '?')) { - // [模块/控制器/操作?]参数1=值1&参数2=值2... - $info = parse_url($url); - $path = explode('/', $info['path'], 4); - parse_str($info['query'], $var); - } elseif (strpos($url, '/')) { - // [模块/控制器/操作] - $path = explode('/', $url, 4); - } elseif (false !== strpos($url, '=')) { - // 参数1=值1&参数2=值2... - parse_str($url, $var); - } else { - $path = [$url]; - } - $route = [null, null, null]; - if (isset($path)) { - // 解析path额外的参数 - if (!empty($path[3])) { - preg_replace_callback('/([^\/]+)\/([^\/]+)/', function ($match) use (&$var) { - $var[strtolower($match[1])] = strip_tags($match[2]); - }, array_pop($path)); - } - // 解析[模块/控制器/操作] - if ($reverse) { - $module = APP_MULTI_MODULE ? array_shift($path) : null; - $controller = !empty($path) ? array_shift($path) : null; - $action = !empty($path) ? array_shift($path) : null; - } else { - $action = array_pop($path); - $controller = !empty($path) ? array_pop($path) : null; - $module = APP_MULTI_MODULE && !empty($path) ? array_pop($path) : null; - // REST 操作方法支持 - if ('[rest]' == $action) { - $action = REQUEST_METHOD; - } - } - $route = [$module, $controller, $action]; - } - return ['route' => $route, 'var' => $var]; - } - - // 检测URL和规则路由是否匹配 - private static function match($url, $rule, $pattern) - { - $m1 = explode('/', $url); - $m2 = explode('/', $rule); - $var = []; - foreach ($m2 as $key => $val) { - if (0 === strpos($val, '[:')) { - // 可选参数 - $val = substr($val, 1, -1); - } - if (0 === strpos($val, ':')) { - // URL变量 - $name = substr($val, 1); - if (isset($m1[$key]) && isset($pattern[$name]) && !preg_match('/^' . $pattern[$name] . '$/', $m1[$key])) { - // 检查变量规则 - return false; - } - $var[$name] = $m1[$key]; - } elseif (0 !== strcasecmp($val, $m1[$key])) { - return false; - } - } - // 成功匹配后返回URL中的动态变量数组 - return $var; - } - - // 解析规则路由 - private static function parseRule($rule, $route, $pathinfo) - { - // 获取URL地址中的参数 - $paths = explode('/', $pathinfo); - // 获取路由地址规则 - $url = is_array($route) ? $route[0] : $route; - // 解析路由规则 - $matches = []; - $rule = explode('/', $rule); - foreach ($rule as $item) { - $fun = ''; - if (0 === strpos($item, '[:')) { - $item = substr($item, 1, -1); - } - if (0 === strpos($item, ':')) { - $var = substr($item, 1); - $matches[$var] = array_shift($paths); - } else { - // 过滤URL中的静态变量 - array_shift($paths); - } - } - // 替换路由地址中的变量 - foreach ($matches as $key => $val) { - if (false !== strpos($url, ':' . $key)) { - $url = str_replace(':' . $key, $val, $url); - unset($matches[$key]); - } - } - if (0 === strpos($url, '/') || 0 === strpos($url, 'http')) { - // 路由到重定向地址 - $result = ['type' => 'redirect', 'url' => $url, 'status' => (is_array($route) && isset($route[1])) ? $route[1] : 301]; - } elseif (0 === strpos($url, '\\')) { - // 路由到方法 - $result = ['type' => 'method', 'method' => is_array($route) ? [$url, $route[1]] : $url, 'params' => $matches]; - } elseif (0 === strpos($url, '@')) { - // 路由到控制器 - $result = ['type' => 'controller', 'controller' => substr($url, 1), 'params' => $matches]; - } else { - // 解析路由地址 - $result = self::parseRoute($url); - $var = array_merge($matches, $result['var']); - // 解析剩余的URL参数 - self::parseUrlParams(implode('/', $paths), $var); - // 路由到模块/控制器/操作 - $result = ['type' => 'module', 'module' => $result['route']]; - } - return $result; - } - - // 解析URL地址中的参数到$_GET - private static function parseUrlParams($url, $var) - { - if ($url) { - preg_replace_callback('/(\w+)\/([^\/]+)/', function ($match) use (&$var) { - $var[strtolower($match[1])] = strip_tags($match[2]); - }, $url); - } - $_GET = array_merge($var, $_GET); - } - -} diff --git a/thinkphp/library/think/Session.php b/thinkphp/library/think/Session.php deleted file mode 100644 index df620e904..000000000 --- a/thinkphp/library/think/Session.php +++ /dev/null @@ -1,271 +0,0 @@ - -// +---------------------------------------------------------------------- -namespace think; - -class Session -{ - - protected static $prefix = ''; - - /** - * 设置或者获取session作用域(前缀) - * - * @param string $prefix - * @return string|void - */ - public static function prefix($prefix = '') - { - if (empty($prefix) && null !== $prefix) { - return self::$prefix; - } else { - self::$prefix = $prefix; - } - } - - /** - * session初始化 - * - * @param array $config - * @return void - */ - public static function init(array $config = []) - { - // 记录初始化信息 - APP_DEBUG && Log::record('[ SESSION ] INIT ' . var_export($config, true), 'info'); - $isDoStart = false; - if (isset($config['use_trans_sid'])) { - ini_set('session.use_trans_sid', $config['use_trans_sid'] ? 1 : 0); - } - - // 启动session - if (!empty($config['auto_start']) && PHP_SESSION_ACTIVE != session_status()) { - ini_set('session.auto_start', 0); - $isDoStart = true; - } - - if (isset($config['prefix'])) { - self::$prefix = $config['prefix']; - } - if (isset($config['var_session_id']) && isset($_REQUEST[$config['var_session_id']])) { - session_id($_REQUEST[$config['var_session_id']]); - } elseif (isset($config['id']) && !empty($config['id'])) { - session_id($config['id']); - } - if (isset($config['name'])) { - session_name($config['name']); - } - if (isset($config['path'])) { - session_save_path($config['path']); - } - if (isset($config['domain'])) { - ini_set('session.cookie_domain', $config['domain']); - } - if (isset($config['expire'])) { - ini_set('session.gc_maxlifetime', $config['expire']); - ini_set('session.cookie_lifetime', $config['expire']); - } - - if (isset($config['use_cookies'])) { - ini_set('session.use_cookies', $config['use_cookies'] ? 1 : 0); - } - if (isset($config['cache_limiter'])) { - session_cache_limiter($config['cache_limiter']); - } - if (isset($config['cache_expire'])) { - session_cache_expire($config['cache_expire']); - } - if (!empty($config['type'])) { - // 读取session驱动 - $class = (!empty($config['namespace']) ? $config['namespace'] : '\\think\\session\\driver\\') . ucwords($config['type']); - - // 检查驱动类 - if (!class_exists($class) || !session_set_save_handler(new $class($config))) { - throw new \think\Exception('error session handler', 11700); - } - } - if ($isDoStart) { - session_start(); - } - } - - /** - * session设置 - * - * @param string $name - * session名称 - * @param mixed $value - * session值 - * @param string $prefix - * 作用域(前缀) - * @return void - */ - public static function set($name, $value = '', $prefix = '') - { - $prefix = $prefix ? $prefix : self::$prefix; - if (strpos($name, '.')) { - // 二维数组赋值 - list($name1, $name2) = explode('.', $name); - if ($prefix) { - $_SESSION[$prefix][$name1][$name2] = $value; - } else { - $_SESSION[$name1][$name2] = $value; - } - } elseif ($prefix) { - $_SESSION[$prefix][$name] = $value; - } else { - $_SESSION[$name] = $value; - } - } - - /** - * session获取 - * - * @param string $name - * session名称 - * @param string $prefix - * 作用域(前缀) - * @return mixed - */ - public static function get($name = '', $prefix = '') - { - $prefix = $prefix ? $prefix : self::$prefix; - if ('' == $name) { - // 获取全部的session - $value = $prefix ? $_SESSION[$prefix] : $_SESSION; - } elseif ($prefix) { - // 获取session - if (strpos($name, '.')) { - list($name1, $name2) = explode('.', $name); - $value = isset($_SESSION[$prefix][$name1][$name2]) ? $_SESSION[$prefix][$name1][$name2] : null; - } else { - $value = isset($_SESSION[$prefix][$name]) ? $_SESSION[$prefix][$name] : null; - } - } else { - if (strpos($name, '.')) { - list($name1, $name2) = explode('.', $name); - $value = isset($_SESSION[$name1][$name2]) ? $_SESSION[$name1][$name2] : null; - } else { - $value = isset($_SESSION[$name]) ? $_SESSION[$name] : null; - } - } - return $value; - } - - /** - * 删除session数据 - * - * @param string $name - * session名称 - * @param string $prefix - * 作用域(前缀) - * @return void - */ - public static function delete($name, $prefix = '') - { - $prefix = $prefix ? $prefix : self::$prefix; - if (strpos($name, '.')) { - list($name1, $name2) = explode('.', $name); - if ($prefix) { - unset($_SESSION[$prefix][$name1][$name2]); - } else { - unset($_SESSION[$name1][$name2]); - } - } else { - if ($prefix) { - unset($_SESSION[$prefix][$name]); - } else { - unset($_SESSION[$name]); - } - } - } - - /** - * 清空session数据 - * - * @param string $prefix - * 作用域(前缀) - * @return void - */ - public static function clear($prefix = '') - { - $prefix = $prefix ? $prefix : self::$prefix; - if ($prefix) { - unset($_SESSION[$prefix]); - } else { - $_SESSION = []; - } - } - - /** - * 判断session数据 - * - * @param string $name - * session名称 - * @param string $prefix - * - * @return bool - * @internal param mixed $value session值 - */ - public static function has($name, $prefix = '') - { - $prefix = $prefix ? $prefix : self::$prefix; - if (strpos($name, '.')) { - // 支持数组 - list($name1, $name2) = explode('.', $name); - return $prefix ? isset($_SESSION[$prefix][$name1][$name2]) : isset($_SESSION[$name1][$name2]); - } else { - return $prefix ? isset($_SESSION[$prefix][$name]) : isset($_SESSION[$name]); - } - } - - /** - * 暂停session - * - * @return void - */ - public static function pause() - { - // 暂停session - session_write_close(); - } - - /** - * 启动session - * - * @return void - */ - public static function start() - { - session_start(); - } - - /** - * 销毁session - * - * @return void - */ - public static function destroy() - { - $_SESSION = []; - session_unset(); - session_destroy(); - } - - /** - * 重新生成session_id - * - * @return void - */ - private static function regenerate() - { - session_regenerate_id(); - } -} diff --git a/thinkphp/library/think/Template.php b/thinkphp/library/think/Template.php deleted file mode 100644 index ffc263b95..000000000 --- a/thinkphp/library/think/Template.php +++ /dev/null @@ -1,982 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -/** - * ThinkPHP分离出来的模板引擎 - * 支持XML标签和普通标签的模板解析 - * 编译型模板引擎 支持动态缓存 - */ -class Template -{ - // 模板变量 - protected $data = []; - // 引擎配置 - protected $config = [ - 'tpl_path' => VIEW_PATH, // 模板路径 - 'tpl_suffix' => '.html', // 默认模板文件后缀 - 'cache_suffix' => '.php', // 默认模板缓存后缀 - 'tpl_deny_func_list' => 'echo,exit', // 模板引擎禁用函数 - 'tpl_deny_php' => false, // 默认模板引擎是否禁用PHP原生代码 - 'tpl_begin' => '{', // 模板引擎普通标签开始标记 - 'tpl_end' => '}', // 模板引擎普通标签结束标记 - 'strip_space' => false, // 是否去除模板文件里面的html空格与换行 - 'tpl_cache' => true, // 是否开启模板编译缓存,设为false则每次都会重新编译 - 'compile_type' => 'file', // 模板编译类型 - 'cache_prefix' => '', // 模板缓存前缀标识,可以动态改变 - 'cache_time' => 0, // 模板缓存有效期 0 为永久,(以数字为值,单位:秒) - 'layout_item' => '{__CONTENT__}', // 布局模板的内容替换标识 - 'taglib_begin' => '{', // 标签库标签开始标记 - 'taglib_end' => '}', // 标签库标签结束标记 - 'taglib_load' => true, // 是否使用内置标签库之外的其它标签库,默认自动检测 - 'taglib_build_in' => 'cx', // 内置标签库名称(标签使用不必指定标签库名称),以逗号分隔 注意解析顺序 - 'taglib_pre_load' => '', // 需要额外加载的标签库(须指定标签库名称),多个以逗号分隔 - 'display_cache' => false, // 模板渲染缓存 - 'cache_id' => '', // 模板缓存ID - 'tpl_replace_string' => [], - 'tpl_var_identify' => 'array', // .语法变量识别,array|object|'', 为空时自动识别 - 'namespace' => '\\think\\template\\driver\\', - ]; - - private $literal = []; - protected $storage = null; - - /** - * 架构函数 - * @access public - */ - public function __construct(array $config = []) - { - $this->config['cache_path'] = RUNTIME_PATH . 'template' . DS; - $this->config = array_merge($this->config, empty($config) ? (array) Config::get('template') : $config); - $this->config['taglib_begin'] = $this->stripPreg($this->config['taglib_begin']); - $this->config['taglib_end'] = $this->stripPreg($this->config['taglib_end']); - $this->config['tpl_begin'] = $this->stripPreg($this->config['tpl_begin']); - $this->config['tpl_end'] = $this->stripPreg($this->config['tpl_end']); - - // 初始化模板编译存储器 - $type = $this->config['compile_type'] ? $this->config['compile_type'] : 'File'; - $class = $this->config['namespace'] . ucwords($type); - $this->storage = new $class(); - } - - /** - * 字符串替换 避免正则混淆 - * @access private - * @param string $str - * @return string - */ - private function stripPreg($str) - { - return str_replace( - ['{', '}', '(', ')', '|', '[', ']', '-', '+', '*', '.', '^', '?'], - ['\{', '\}', '\(', '\)', '\|', '\[', '\]', '\-', '\+', '\*', '\.', '\^', '\?'], - $str); - } - - /** - * 模板变量赋值 - * @access public - * @param mixed $name - * @param mixed $value - * @return void - */ - public function assign($name, $value = '') - { - if (is_array($name)) { - $this->data = array_merge($this->data, $name); - } else { - $this->data[$name] = $value; - } - } - - /** - * 模板引擎参数赋值 - * @access public - * @param mixed $name - * @param mixed $value - */ - public function __set($name, $value) - { - $this->config[$name] = $value; - } - - /** - * 模板引擎配置项 - * @access public - * @param array $config - * @return void|array - */ - public function config($config) - { - if (is_array($config)) { - $this->config = array_merge($this->config, $config); - } elseif (isset($this->config[$config])) { - return $this->config[$config]; - } - } - - /** - * 模板变量获取 - * @access public - * @param string $name 变量名 - * @return string|false - */ - public function get($name) - { - return isset($this->data[$name]) ? $this->data[$name] : false; - } - - /** - * 渲染模板文件 - * @access public - * @param string $template 模板文件 - * @param array $vars 模板变量 - * @param array $config 模板参数 - * @return void - */ - public function display($template, $vars = [], $config = []) - { - if ($vars) { - $this->data = $vars; - } - if ($config) { - $this->config($config); - } - $template = $this->parseTemplateFile($template); - $cacheFile = $this->config['cache_path'] . $this->config['cache_prefix'] . md5($template) . $this->config['cache_suffix']; - if (!$this->checkCache($template, $cacheFile)) { - // 缓存无效 重新模板编译 - $content = file_get_contents($template); - $this->compiler($content, $cacheFile); - } - // 页面缓存 - ob_start(); - ob_implicit_flush(0); - // 读取编译存储 - $this->storage->read($cacheFile, $this->data); - // 获取并清空缓存 - $content = ob_get_clean(); - if (!empty($this->config['cache_id']) && $this->config['display_cache']) { - // 缓存页面输出 - Cache::set($this->config['cache_id'], $content, $this->config['cache_time']); - } - echo $content; - } - - /** - * 渲染模板内容 - * @access public - * @param string $content 模板内容 - * @param array $vars 模板变量 - * @return void - */ - public function fetch($content, $vars = []) - { - if ($vars) { - $this->data = $vars; - } - $cacheFile = $this->config['cache_path'] . $this->config['cache_prefix'] . md5($content) . $this->config['cache_suffix']; - if (!$this->checkCache($content, $cacheFile)) { - // 缓存无效 模板编译 - $this->compiler($content, $cacheFile); - } - // 读取编译存储 - $this->storage->read($cacheFile, $this->data); - } - - /** - * 检查编译缓存是否有效 - * 如果无效则需要重新编译 - * @access private - * @param string $template 模板文件名 - * @param string $cacheFile 缓存文件名 - * @return boolean - */ - private function checkCache($template, $cacheFile) - { - if (!$this->config['tpl_cache']) { - // 优先对配置设定检测 - return false; - } - // 检查编译存储是否有效 - return $this->storage->check($template, $cacheFile, $this->config['cache_time']); - } - - /** - * 检查编译缓存是否存在 - * @access public - * @param string $cacheId 缓存的id - * @return boolean - */ - public function isCache($cacheId) - { - if ($cacheId && $this->config['display_cache']) { - // 缓存页面输出 - return Cache::get($cacheId) ? true : false; - } - return false; - } - - /** - * 编译模板文件内容 - * @access private - * @param string $content 模板内容 - * @param string $cacheFile 缓存文件名 - * @return void - */ - private function compiler(&$content, $cacheFile) - { - // 模板解析 - $this->parse($content); - // 添加安全代码 - $content = '' . $content; - if ($this->config['strip_space']) { - /* 去除html空格与换行 */ - $find = ['~>\s+<~', '~>(\s+\n|\r)~']; - $replace = ['><', '>']; - $content = preg_replace($find, $replace, $content); - } - // 优化生成的php代码 - $content = preg_replace('/\?>\s*<\?php\s?/is', '', $content); - // 模板过滤输出 - $replace = $this->config['tpl_replace_string']; - $content = str_replace(array_keys($replace), array_values($replace), $content); - // 编译存储 - $this->storage->write($cacheFile, $content); - return; - } - - /** - * 模板解析入口 - * 支持普通标签和TagLib解析 支持自定义标签库 - * @access public - * @param string $content 要解析的模板内容 - * @return void - */ - public function parse(&$content) - { - // 内容为空不解析 - if (empty($content)) { - return; - } - // 替换literal标签内容 - $this->parseLiteral($content); - // 解析继承 - $this->parseExtend($content); - // 解析布局 - $this->parseLayout($content); - // 检查include语法 - $this->parseInclude($content); - // 替换包含文件中literal标签内容 - $this->parseLiteral($content); - // 检查PHP语法 - $this->parsePhp($content); - - // 获取需要引入的标签库列表 - // 标签库只需要定义一次,允许引入多个一次 - // 一般放在文件的最前面 - // 格式: - // 当TAGLIB_LOAD配置为true时才会进行检测 - if ($this->config['taglib_load']) { - $tagLibs = $this->getIncludeTagLib($content); - if (!empty($tagLibs)) { - // 对导入的TagLib进行解析 - foreach ($tagLibs as $tagLibName) { - $this->parseTagLib($tagLibName, $content); - } - } - } - // 预先加载的标签库 无需在每个模板中使用taglib标签加载 但必须使用标签库XML前缀 - if ($this->config['taglib_pre_load']) { - $tagLibs = explode(',', $this->config['taglib_pre_load']); - foreach ($tagLibs as $tag) { - $this->parseTagLib($tag, $content); - } - } - // 内置标签库 无需使用taglib标签导入就可以使用 并且不需使用标签库XML前缀 - $tagLibs = explode(',', $this->config['taglib_build_in']); - foreach ($tagLibs as $tag) { - $this->parseTagLib($tag, $content, true); - } - // 解析普通模板标签 {$tagName} - $this->parseTag($content); - - // 还原被替换的Literal标签 - $this->parseLiteral($content, true); - return; - } - - /** - * 检查PHP语法 - * @access private - * @param string $content 要解析的模板内容 - * @return void - */ - private function parsePhp(&$content) - { - if (ini_get('short_open_tag')) { - // 开启短标签的情况要将' . "\n", $content); - } - // PHP语法检查 - if ($this->config['tpl_deny_php'] && false !== strpos($content, 'getRegex('layout'), $content, $matches)) { - // 替换Layout标签 - $content = str_replace($matches[0], '', $content); - // 解析Layout标签 - $array = $this->parseAttr($matches[0]); - //if (!C('LAYOUT_ON') || C('LAYOUT_NAME') != $array['name']) { - // 读取布局模板 - $layoutFile = (defined('THEME_PATH') && substr_count($array['name'], '/') < 2 ? THEME_PATH : $this->config['tpl_path']) . $array['name'] . $this->config['tpl_suffix']; - if (is_file($layoutFile)) { - $replace = isset($array['replace']) ? $array['replace'] : $this->config['layout_item']; - // 替换布局的主体内容 - $content = str_replace($replace, $content, file_get_contents($layoutFile)); - } - //} - } else { - $content = str_replace('{__NOLAYOUT__}', '', $content); - } - return; - } - - /** - * 解析模板中的include标签 - * @access private - * @param string $content 要解析的模板内容 - * @return void - */ - private function parseInclude(&$content) - { - $regex = $this->getRegex('include'); - $funReplace = function ($template) use (&$funReplace, &$regex, &$content) { - if (preg_match_all($regex, $template, $matches, PREG_SET_ORDER)) { - foreach ($matches as $match) { - $array = $this->parseAttr($match[0]); - $file = $array['file']; - unset($array['file']); - // 分析模板文件名并读取内容 - $parseStr = $this->parseTemplateName($file); - // 替换变量 - foreach ($array as $k => $v) { - $parseStr = str_replace('[' . $k . ']', $v, $parseStr); - } - // 再次对包含文件进行模板分析 - $funReplace($parseStr); - $content = str_replace($match[0], $parseStr, $content); - } - unset($matches); - } - }; - // 替换模板中的include标签 - $funReplace($content); - return; - } - - /** - * 解析模板中的extend标签 - * @access private - * @param string $content 要解析的模板内容 - * @return void - */ - private function parseExtend(&$content) - { - $regex = $this->getRegex('extend'); - $array = $blocks = $extBlocks = []; - $extend = ''; - $fun = function ($template) use (&$fun, &$regex, &$array, &$extend, &$blocks, &$extBlocks) { - if (preg_match($regex, $template, $matches)) { - if (!isset($array[$matches['name']])) { - $array[$matches['name']] = 1; - // 读取继承模板 - $extend = $this->parseTemplateName($matches['name']); - // 递归检查继承 - $fun($extend); - // 取得block标签内容 - $blocks = array_merge($blocks, $this->parseBlock($template)); - return; - } - } else { - // 取得顶层模板block标签内容 - $extBlocks = $this->parseBlock($template); - if (empty($extend)) { - // 无extend标签但有block标签的情况 - $extend = $template; - } - } - }; - - $fun($content); - if (!empty($extend)) { - if ($extBlocks) { - foreach ($extBlocks as $name => $v) { - $replace = isset($blocks[$name]) ? $blocks[$name]['content'] : $v['content']; - $extend = str_replace($v['begin']['tag'] . $v['content'] . $v['end']['tag'], $replace, $extend); - } - } - $content = $extend; - } - return; - } - - /** - * 替换页面中的literal标签 - * @access private - * @param string $content 模板内容 - * @param boolean $restore 是否为还原 - * @return void - */ - private function parseLiteral(&$content, $restore = false) - { - $regex = $this->getRegex($restore ? 'restoreliteral' : 'literal'); - if (preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) { - if (!$restore) { - // 替换literal标签 - foreach ($matches as $i => $match) { - $this->literal[] = substr($match[0], strlen($match[1]), -strlen($match[2])); - $content = str_replace($match[0], "", $content); - } - } else { - // 还原literal标签 - foreach ($matches as $i => $match) { - $content = str_replace($match[0], $this->literal[$i], $content); - } - // 销毁literal记录 - unset($this->literal); - } - unset($matches); - } - return; - } - - /** - * 获取模板中的block标签 - * @access private - * @param string $content 模板内容 - * @return array - */ - private function parseBlock(&$content) - { - $regex = $this->getRegex('block'); - $array = []; - if (preg_match_all($regex, $content, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { - $right = []; - foreach ($matches as $match) { - if (empty($match['name'][0])) { - if (!empty($right)) { - $begin = array_pop($right); - $end = ['offset' => $match[0][1], 'tag' => $match[0][0]]; - $start = $begin['offset'] + strlen($begin['tag']); - $len = $end['offset'] - $start; - $array[$begin['name']] = [ - 'begin' => $begin, - 'content' => substr($content, $start, $len), - 'end' => $end, - ]; - } else { - continue; - } - } else { - $right[] = [ - 'name' => $match[2][0], - 'offset' => $match[0][1], - 'tag' => $match[0][0], - ]; - } - } - unset($right, $matches); - } - return $array; - } - - /** - * 搜索模板页面中包含的TagLib库 - * 并返回列表 - * @access private - * @param string $content 模板内容 - * @return array|null - */ - private function getIncludeTagLib(&$content) - { - // 搜索是否有TagLib标签 - if (preg_match($this->getRegex('taglib'), $content, $matches)) { - // 替换TagLib标签 - $content = str_replace($matches[0], '', $content); - return explode(',', $matches['name']); - } - return null; - } - - /** - * TagLib库解析 - * @access public - * @param string $tagLib 要解析的标签库 - * @param string $content 要解析的模板内容 - * @param boolean $hide 是否隐藏标签库前缀 - * @return void - */ - public function parseTagLib($tagLib, &$content, $hide = false) - { - if (strpos($tagLib, '\\')) { - // 支持指定标签库的命名空间 - $className = $tagLib; - $tagLib = substr($tagLib, strrpos($tagLib, '\\') + 1); - } else { - $className = '\\think\\template\\taglib\\' . ucwords($tagLib); - } - $tLib = new $className($this); - $tLib->parseTag($content, $hide ? '' : $tagLib); - return; - } - - /** - * 分析标签属性 - * @access public - * @param string $str 属性字符串 - * @param string $name 不为空时返回指定的属性名 - * @return array - */ - public function parseAttr($str, $name = null) - { - $regex = '/\s+(?>(?\w+)\s*)=(?>\s*)([\"\'])(?(?:(?!\\2).)*)\\2/is'; - $array = []; - if (preg_match_all($regex, $str, $matches, PREG_SET_ORDER)) { - foreach ($matches as $match) { - $array[$match['name']] = $match['value']; - } - unset($matches); - } - if (!empty($name) && isset($array[$name])) { - return $array[$name]; - } else { - return $array; - } - } - - /** - * 模板标签解析 - * 格式: {TagName:args [|content] } - * @access private - * @param string $content 要解析的模板内容 - * @return void - */ - private function parseTag(&$content) - { - $regex = $this->getRegex('tag'); - if (preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) { - foreach ($matches as $match) { - $str = stripslashes($match[1]); - $flag = substr($str, 0, 1); - switch ($flag) { - case '$': // 解析模板变量 格式 {$varName} - // 是否带有?号 - if (false !== $pos = strpos($str, '?')) { - $array = preg_split('/([!=]={1,2}|(?<]={0,1})/', substr($str, 0, $pos), 2, PREG_SPLIT_DELIM_CAPTURE); - $name = $array[0]; - $this->parseVar($name); - $this->parseVarFunction($name); - - $str = trim(substr($str, $pos + 1)); - $this->parseVar($str); - $first = substr($str, 0, 1); - if (isset($array[1])) { - $this->parseVar($array[2]); - $name .= $array[1] . $array[2]; - if ('=' == $first) { - // {$varname?='xxx'} $varname为真时才输出xxx - $str = ''; - } else { - $str = ''; - } - } elseif (')' == substr($name, -1, 1)) { - // $name为对象或是自动识别,或者含有函数 - switch ($first) { - case '?': - $str = ''; - break; - case '=': - $str = ''; - break; - default: - $str = ''; - } - } else { - // $name为数组 - switch ($first) { - case '?': - // {$varname??'xxx'} $varname有定义则输出$varname,否则输出xxx - $str = ''; - break; - case '=': - // {$varname?='xxx'} $varname为真时才输出xxx - $str = ''; - break; - case ':': - // {$varname?:'xxx'} $varname为真时输出$varname,否则输出xxx - $str = ''; - break; - default: - if (strpos($str, ':')) { - // {$varname ? 'a' : 'b'} $varname为真时输出a,否则输出b - $str = ''; - } else { - $str = ''; - } - } - } - } else { - $this->parseVar($str); - $this->parseVarFunction($str); - $str = ''; - } - break; - case ':': // 输出某个函数的结果 - $str = substr($str, 1); - $this->parseVar($str); - $str = ''; - break; - case '~': // 执行某个函数 - $str = substr($str, 1); - $this->parseVar($str); - $str = ''; - break; - case '-': - case '+': // 输出计算 - $str = substr($str, 1); - $this->parseVar($str); - $str = ''; - break; - case '/': // 注释标签 - $flag2 = substr($str, 1, 1); - if ('/' == $flag2 || ('*' == $flag2 && substr(rtrim($str), -2) == '*/')) { - $str = ''; - } - break; - default: - // 未识别的标签直接返回 - $str = $this->config['tpl_begin'] . $str . $this->config['tpl_end']; - break; - } - $content = str_replace($match[0], $str, $content); - } - unset($matches); - } - return; - } - - /** - * 模板变量解析,支持使用函数 - * 格式: {$varname|function1|function2=arg1,arg2} - * @access public - * @param string $varStr 变量数据 - * @return void - */ - public function parseVar(&$varStr) - { - $varStr = trim($varStr); - if (preg_match_all('/\$[a-zA-Z_](?>\w*)(?:[:\.][a-zA-Z_](?>\w*))+/', $varStr, $matches, PREG_OFFSET_CAPTURE)) { - static $_varParseList = []; - while ($matches[0]) { - $match = array_pop($matches[0]); - //如果已经解析过该变量字串,则直接返回变量值 - if (isset($_varParseList[$match[0]])) { - $parseStr = $_varParseList[$match[0]]; - } else { - if (strpos($match[0], '.')) { - $vars = explode('.', $match[0]); - $first = array_shift($vars); - if ('$Think' == $first) { - // 所有以Think.打头的以特殊变量对待 无需模板赋值就可以输出 - $parseStr = $this->parseThinkVar($vars); - } else { - switch ($this->config['tpl_var_identify']) { - case 'array': // 识别为数组 - $parseStr = $first . '[\'' . implode('\'][\'', $vars) . '\']'; - break; - case 'obj': // 识别为对象 - $parseStr = $first . '->' . implode('->', $vars); - break; - default: // 自动判断数组或对象 - $parseStr = '(is_array(' . $first . ')?' . $first . '[\'' . implode('\'][\'', $vars) . '\']:' . $first . '->' . implode('->', $vars) . ')'; - } - } - } else { - $parseStr = str_replace(':', '->', $match[0]); - } - $_varParseList[$match[0]] = $parseStr; - } - $varStr = substr_replace($varStr, $parseStr, $match[1], strlen($match[0])); - } - unset($matches); - } - return; - } - - /** - * 对模板中使用了函数的变量进行解析 - * 格式 {$varname|function1|function2=arg1,arg2} - * @access public - * @param string $varStr 变量字符串 - * @return void - */ - public function parseVarFunction(&$varStr) - { - if (false == strpos($varStr, '|')) { - return; - } - static $_varFunctionList = []; - //如果已经解析过该变量字串,则直接返回变量值 - if (isset($_varFunctionList[$varStr])) { - $varStr = $_varFunctionList[$varStr]; - } else { - $varArray = explode('|', $varStr); - // 取得变量名称 - $name = array_shift($varArray); - // 对变量使用函数 - $length = count($varArray); - // 取得模板禁止使用函数列表 - $template_deny_funs = explode(',', $this->config['tpl_deny_func_list']); - for ($i = 0; $i < $length; $i++) { - $args = explode('=', $varArray[$i], 2); - // 模板函数过滤 - $fun = trim($args[0]); - switch ($fun) { - case 'default': // 特殊模板函数 - if (false === strpos($name, '(')) { - $name = '(isset(' . $name . ') && (' . $name . ' !== \'\')?' . $name . ':' . $args[1] . ')'; - } else { - $name = '(' . $name . ' !== \'\'?' . $name . ':' . $args[1] . ')'; - } - break; - default: // 通用模板函数 - if (!in_array($fun, $template_deny_funs)) { - if (isset($args[1])) { - if (strstr($args[1], '###')) { - $args[1] = str_replace('###', $name, $args[1]); - $name = "$fun($args[1])"; - } else { - $name = "$fun($name,$args[1])"; - } - } else { - if (!empty($args[0])) { - $name = "$fun($name)"; - } - } - } - } - } - $varStr = $name; - } - return; - } - - /** - * 特殊模板变量解析 - * 格式 以 $Think. 打头的变量属于特殊模板变量 - * @access public - * @param array $vars 变量数组 - * @return string - */ - public function parseThinkVar(&$vars) - { - $vars[0] = strtoupper(trim($vars[0])); - $parseStr = ''; - if (count($vars) >= 2) { - $vars[1] = trim($vars[1]); - switch ($vars[0]) { - case 'SERVER': - $parseStr = '$_SERVER[\'' . strtoupper($vars[1]) . '\']'; - break; - case 'GET': - $parseStr = '$_GET[\'' . $vars[1] . '\']'; - break; - case 'POST': - $parseStr = '$_POST[\'' . $vars[1] . '\']'; - break; - case 'COOKIE': - if (isset($vars[2])) { - $parseStr = '$_COOKIE[\'' . $vars[1] . '\'][\'' . $vars[2] . '\']'; - } else { - $parseStr = '\\think\\cookie::get(\'' . $vars[1] . '\')'; - } - break; - case 'SESSION': - if (isset($vars[2])) { - $parseStr = '$_SESSION[\'' . $vars[1] . '\'][\'' . $vars[2] . '\']'; - } else { - $parseStr = '\\think\\session::get(\'' . $vars[1] . '\')'; - } - break; - case 'ENV': - $parseStr = '$_ENV[\'' . strtoupper($vars[1]) . '\']'; - break; - case 'REQUEST': - $parseStr = '$_REQUEST[\'' . $vars[1] . '\']'; - break; - case 'CONST': - $parseStr = strtoupper($vars[1]); - break; - case 'LANG': - $parseStr = '\\think\\lang::get(\'' . $vars[1] . '\')'; - break; - case 'CONFIG': - if (isset($vars[2])) { - $vars[1] .= '.' . $vars[2]; - } - $parseStr = '\\think\\config::get(\'' . $vars[1] . '\')'; - break; - default: - break; - } - } else { - if (count($vars) == 1) { - switch ($vars[0]) { - case 'NOW': - $parseStr = "date('Y-m-d g:i a',time())"; - break; - case 'VERSION': - $parseStr = 'THINK_VERSION'; - break; - case 'LDELIM': - $parseStr = $this->config['tpl_begin']; - break; - case 'RDELIM': - $parseStr = $this->config['tpl_end']; - break; - default: - if (defined($vars[0])) { - $parseStr = $vars[0]; - } - } - } - } - return $parseStr; - } - - /** - * 分析加载的模板文件并读取内容 支持多个模板文件读取 - * @access private - * @param string $templateName 模板文件名 - * @return string - */ - private function parseTemplateName($templateName) - { - if ('$' == substr($templateName, 0, 1)) { - //支持加载变量文件名 - $templateName = $this->get(substr($templateName, 1)); - } - $array = explode(',', $templateName); - $parseStr = ''; - foreach ($array as $templateName) { - if (empty($templateName)) { - continue; - } - $template = $this->parseTemplateFile($templateName); - // 获取模板文件内容 - $parseStr .= file_get_contents($template); - } - return $parseStr; - } - - /** - * 解析模板文件名 - * @access private - * @param string $template 文件名 - * @return string - */ - private function parseTemplateFile($template) - { - if (false === strpos($template, '.')) { - // 跨模块支持 - $template = strpos($template, '@') ? - APP_PATH . str_replace('@', '/' . basename($this->config['tpl_path']) . '/', $template) . $this->config['tpl_suffix'] : - (defined('THEME_PATH') && substr_count($template, '/') < 2 ? THEME_PATH : $this->config['tpl_path']) . $template . $this->config['tpl_suffix']; - } - return $template; - } - - /** - * 按标签生成正则 - * @access private - * @param string $tagName 标签名 - * @return string - */ - private function getRegex($tagName) - { - $begin = $this->config['taglib_begin']; - $end = $this->config['taglib_end']; - $single = strlen(ltrim($begin, '\\')) == 1 && strlen(ltrim($end, '\\')) == 1 ? true : false; - $regex = ''; - switch ($tagName) { - case 'block': - if ($single) { - $regex = $begin . '(?:' . $tagName . '\b(?>(?:(?!name=).)*)\bname=([\'\"])(?[\w\/\:@,]+)\\1(?>[^' . $end . ']*)|\/' . $tagName . ')' . $end; - } else { - $regex = $begin . '(?:' . $tagName . '\b(?>(?:(?!name=).)*)\bname=([\'\"])(?[\w\/\:@,]+)\\1(?>(?:(?!' . $end . ').)*)|\/' . $tagName . ')' . $end; - } - break; - case 'literal': - if ($single) { - $regex = '(' . $begin . $tagName . '\b(?>[^' . $end . ']*)' . $end . ')'; - $regex .= '(?:(?>[^' . $begin . ']*)(?>(?!' . $begin . '(?>' . $tagName . '\b[^' . $end . ']*|\/' . $tagName . ')' . $end . ')' . $begin . '[^' . $begin . ']*)*)'; - $regex .= '(' . $begin . '\/' . $tagName . $end . ')'; - } else { - $regex = '(' . $begin . $tagName . '\b(?>(?:(?!' . $end . ').)*)' . $end . ')'; - $regex .= '(?:(?>(?:(?!' . $begin . ').)*)(?>(?!' . $begin . '(?>' . $tagName . '\b(?>(?:(?!' . $end . ').)*)|\/' . $tagName . ')' . $end . ')' . $begin . '(?>(?:(?!' . $begin . ').)*))*)'; - $regex .= '(' . $begin . '\/' . $tagName . $end . ')'; - } - break; - case 'restoreliteral': - $regex = ''; - break; - case 'include': - $name = 'file'; - case 'taglib': - case 'layout': - case 'extend': - if (empty($name)) { - $name = 'name'; - } - if ($single) { - $regex = $begin . $tagName . '\b(?>(?:(?!' . $name . '=).)*)\b' . $name . '=([\'\"])(?[\w\/\.\:@,\\\\]+)\\1(?>[^' . $end . ']*)' . $end; - } else { - $regex = $begin . $tagName . '\b(?>(?:(?!' . $name . '=).)*)\b' . $name . '=([\'\"])(?[\w\/\.\:@,\\\\]+)\\1(?>(?:(?!' . $end . ').)*)' . $end; - } - break; - case 'tag': - $begin = $this->config['tpl_begin']; - $end = $this->config['tpl_end']; - if (strlen(ltrim($begin, '\\')) == 1 && strlen(ltrim($end, '\\')) == 1) { - $regex = $begin . '((?:[\$\:\-\+~][\$a-wA-w_][\w\.\:\[\(\*\/\-\+\%_]|\/[\*\/])(?>[^' . $end . ']*))' . $end; - } else { - $regex = $begin . '((?:[\$\:\-\+~][\$a-wA-w_][\w\.\:\[\(\*\/\-\+\%_]|\/[\*\/])(?>(?:(?!' . $end . ').)*))' . $end; - } - break; - } - return '/' . $regex . '/is'; - } -} diff --git a/thinkphp/library/think/Url.php b/thinkphp/library/think/Url.php deleted file mode 100644 index 2fc5069a8..000000000 --- a/thinkphp/library/think/Url.php +++ /dev/null @@ -1,306 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -class Url -{ - /** - * URL生成 支持路由反射 - * @param string $url URL表达式, - * 格式:'[模块/控制器/操作]?参数1=值1&参数2=值2...' - * @控制器/操作?参数1=值1&参数2=值2... - * \\命名空间类\\方法?参数1=值1&参数2=值2... - * @param string|array $vars 传入的参数,支持数组和字符串 - * @param string $suffix 伪静态后缀,默认为true表示获取配置值 - * @param boolean|string $domain 是否显示域名 或者直接传入域名 - * @return string - */ - public static function build($url = '', $vars = '', $suffix = true, $domain = false) - { - // 解析URL - $info = parse_url($url); - $url = !empty($info['path']) ? $info['path'] : ''; - if (isset($info['fragment'])) { - // 解析锚点 - $anchor = $info['fragment']; - if (false !== strpos($anchor, '?')) { - // 解析参数 - list($anchor, $info['query']) = explode('?', $anchor, 2); - } - if (false !== strpos($anchor, '@')) { - // 解析域名 - list($anchor, $domain) = explode('@', $anchor, 2); - } - } elseif (false !== strpos($url, '@')) { - // 解析域名 - list($url, $domain) = explode('@', $info['path'], 2); - } - - // 解析参数 - if (is_string($vars)) { - // aaa=1&bbb=2 转换成数组 - parse_str($vars, $vars); - } - - if (isset($info['query'])) { - // 解析地址里面参数 合并到vars - parse_str($info['query'], $params); - $vars = array_merge($params, $vars); - } - - // 获取路由别名 - $alias = self::getRouteAlias(); - // 检测路由 - if (0 !== strpos($url, '/') && isset($alias[$url]) && $match = self::getRouteUrl($alias[$url], $vars)) { - // 处理路由规则中的特殊字符 - $url = str_replace('[--think--]', '', $match); - } else { - // 路由不存在 直接解析 - $url = self::parseUrl($url); - } - - // 检测URL绑定 - $type = Route::bind('type'); - if ($type) { - $bind = Route::bind($type); - if (0 === strpos($url, $bind)) { - $url = substr($url, strlen($bind) + 1); - } - } - // 还原URL分隔符 - $depr = Config::get('pathinfo_depr'); - $url = str_replace('/', $depr, $url); - - // URL后缀 - $suffix = self::parseSuffix($suffix); - // 锚点 - $anchor = !empty($anchor) ? '#' . $anchor : ''; - // 参数组装 - if (!empty($vars)) { - // 添加参数 - if (Config::get('url_common_param')) { - $vars = urldecode(http_build_query($vars)); - $url .= $suffix . $anchor . '?' . $vars; - } else { - foreach ($vars as $var => $val) { - if ('' !== trim($val)) { - $url .= $depr . $var . $depr . urlencode($val); - } - } - $url .= $suffix . $anchor; - } - } else { - $url .= $suffix . $anchor; - } - - // 检测域名 - $domain = self::parseDomain($url, $domain); - - // URL组装 - $url = $domain . Config::get('base_url') . '/' . $url; - return $url; - } - - // 直接解析URL地址 - protected static function parseUrl($url) - { - if (0 === strpos($url, '/')) { - // 直接作为路由地址解析 - $url = substr($url, 1); - } elseif (false !== strpos($url, '\\')) { - // 解析到类 - $url = ltrim(str_replace('\\', '/', $url), '/'); - } elseif (0 === strpos($url, '@')) { - // 解析到控制器 - $url = substr($url, 1); - } else { - // 解析到 模块/控制器/操作 - $module = MODULE_NAME ? MODULE_NAME . '/' : ''; - if ('' == $url) { - // 空字符串输出当前的 模块/控制器/操作 - $url = $module . CONTROLLER_NAME . '/' . ACTION_NAME; - } else { - $path = explode('/', $url); - $len = count($path); - if ($len < 3) { - $url = $module . (1 == $len ? CONTROLLER_NAME . '/' : '') . $url; - } - } - } - return $url; - } - - // 检测域名 - protected static function parseDomain($url, $domain) - { - if ($domain) { - if (true === $domain) { - // 自动判断域名 - $domain = $_SERVER['HTTP_HOST']; - if (Config::get('url_domain_deploy')) { - // 开启子域名部署 - $domain = $_SERVER['HTTP_HOST']; - foreach (Route::domain() as $key => $rule) { - $rule = is_array($rule) ? $rule[0] : $rule; - if (false === strpos($key, '*') && 0 === strpos($url, $rule)) { - $domain = $key . strstr($domain, '.'); // 生成对应子域名 - break; - } - } - } - } else { - $domain = $domain . (strpos($domain, '.') ? '' : strstr($_SERVER['HTTP_HOST'], '.')); - } - $domain = (self::isSsl() ? 'https://' : 'http://') . $domain; - } else { - $domain = ''; - } - return $domain; - } - - // 检测路由规则中的变量是否有传入 - protected static function pattern($pattern, $vars) - { - foreach ($pattern as $key => $type) { - if (1 == $type && !isset($vars[$key])) { - // 变量未设置 - return false; - } - } - return true; - } - - // 解析URL后缀 - protected static function parseSuffix($suffix) - { - if ($suffix) { - $suffix = true === $suffix ? Config::get('url_html_suffix') : $suffix; - if ($pos = strpos($suffix, '|')) { - $suffix = substr($suffix, 0, $pos); - } - } - return (empty($suffix) || 0 === strpos($suffix, '.')) ? $suffix : '.' . $suffix; - } - - /** - * 判断是否SSL协议 - * @return boolean - */ - public static function isSsl() - { - if (isset($_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))) { - return true; - } elseif (isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'])) { - return true; - } - return false; - } - - // 匹配路由地址 - public static function getRouteUrl($alias, &$vars = []) - { - foreach ($alias as $key => $val) { - list($url, $pattern) = $val; - // 解析安全替换 - if (strpos($url, '$')) { - $url = str_replace('$', '[--think--]', $url); - } - // 检查变量匹配 - if (self::pattern($pattern, $vars)) { - foreach ($vars as $key => $val) { - if (false !== strpos($url, '[:' . $key . ']')) { - $url = str_replace('[:' . $key . ']', $val, $url); - unset($vars[$key]); - } elseif (false !== strpos($url, ':' . $key)) { - $url = str_replace(':' . $key, $val, $url); - unset($vars[$key]); - } - } - return $url; - } - } - return false; - } - - // 生成路由别名并缓存 - private static function getRouteAlias() - { - if ($alias = Cache::get('think_route_alias')) { - return $alias; - } - // 获取路由定义 - $rules = Route::getRules(); - if (empty($rules)) { - return []; - } - foreach ($rules as $rule => $val) { - if (!empty($val['routes'])) { - foreach ($val['routes'] as $key => $route) { - if (is_numeric($key)) { - $key = array_shift($route); - } - $route = $route[0]; - if (is_array($route)) { - $route = implode('\\', $route); - } elseif (strpos($route, '?')) { - $route = strstr($route, '?', true); - } - $var = self::parseVar($rule . '/' . $key); - $alias[$route][] = [$rule . '/' . $key, $var]; - } - } else { - $route = $val['route']; - if (is_array($route)) { - $route = implode('\\', $route); - } elseif (strpos($route, '?')) { - $route = strstr($route, '?', true); - } - $var = self::parseVar($rule); - $alias[$route][] = [$rule, $var]; - } - } - Cache::set('think_route_alias', $alias); - return $alias; - } - - // 分析路由规则中的变量 - private static function parseVar($rule) - { - // 检测是否设置了参数分隔符 - if ($depr = Config::get('url_params_depr')) { - $rule = str_replace($depr, '/', $rule); - } - // 提取路由规则中的变量 - $var = []; - foreach (explode('/', $rule) as $val) { - $optional = false; - if (0 === strpos($val, '[:')) { - // 可选参数 - $optional = true; - $val = substr($val, 1, -1); - } - if (0 === strpos($val, ':')) { - // URL变量 - $name = substr($val, 1); - $type = $optional ? 2 : 1; - $var[$name] = $type; - } - } - return $var; - } - - // 清空路由别名缓存 - public static function clearAliasCache() - { - Cache::rm('think_route_alias'); - } -} diff --git a/thinkphp/library/think/View.php b/thinkphp/library/think/View.php deleted file mode 100644 index 76be55b49..000000000 --- a/thinkphp/library/think/View.php +++ /dev/null @@ -1,314 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -class View -{ - // 视图实例 - protected static $instance = null; - // 模板引擎实例 - protected $engine = null; - // 模板主题名称 - protected $theme = ''; - // 模板变量 - protected $data = []; - // 视图参数 - protected $config = [ - 'theme_on' => false, - 'auto_detect_theme' => false, - 'var_theme' => 't', - 'default_theme' => 'default', - 'http_cache_id' => null, - 'view_path' => '', - 'view_suffix' => '.html', - 'view_depr' => DS, - 'view_layer' => VIEW_LAYER, - 'parse_str' => [], - 'engine_type' => 'think', - 'namespace' => '\\think\\view\\driver\\', - ]; - - public function __construct(array $config = []) - { - $this->config($config); - $this->engine($this->config['engine_type']); - } - - /** - * 初始化视图 - * @access public - * @param array $config 配置参数 - */ - public static function instance(array $config = []) - { - if (is_null(self::$instance)) { - self::$instance = new self($config); - } - return self::$instance; - } - - /** - * 模板变量赋值 - * @access public - * @param mixed $name 变量名 - * @param mixed $value 变量值 - */ - public function assign($name, $value = '') - { - if (is_array($name)) { - $this->data = array_merge($this->data, $name); - return $this; - } else { - $this->data[$name] = $value; - } - return $this; - } - - /** - * 设置视图参数 - * @access public - * @param mixed $config 视图参数或者数组 - * @param string $value 值 - * @return View - */ - public function config($config = '', $value = '') - { - if (is_array($config)) { - foreach ($this->config as $key => $val) { - if (isset($config[$key])) { - $this->config[$key] = $config[$key]; - } - } - } else { - $this->config[$config] = $value; - } - return $this; - } - - /** - * 设置当前模板解析的引擎 - * @access public - * @param string $engine 引擎名称 - * @param array $config 引擎参数 - * @return View - */ - public function engine($engine, array $config = []) - { - if ('php' == $engine) { - $this->engine = 'php'; - } else { - $class = $this->config['namespace'] . ucwords($engine); - $this->engine = new $class($config); - } - return $this; - } - - /** - * 设置当前输出的模板主题 - * @access public - * @param mixed $theme 主题名称 - * @return View - */ - public function theme($theme) - { - if (true === $theme) { - // 自动侦测 - $this->config['theme_on'] = true; - $this->config['auto_detect_theme'] = true; - } elseif (false === $theme) { - // 关闭主题 - $this->config['theme_on'] = false; - } else { - // 指定模板主题 - $this->config['theme_on'] = true; - $this->theme = $theme; - } - return $this; - } - - /** - * 解析和获取模板内容 用于输出 - * @access public - * - * @param string $template 模板文件名或者内容 - * @param array $vars 模板输出变量 - * @param array $cache 模板缓存参数 - * @param bool $renderContent 是否渲染内容 - * - * @return string - * @throws Exception - */ - public function fetch($template = '', $vars = [], $cache = [], $renderContent = false) - { - // 模板变量 - $vars = $vars ? $vars : $this->data; - if (!$renderContent) { - // 获取模板文件名 - $template = $this->parseTemplate($template); - // 开启调试模式Win环境严格区分大小写 - // 模板不存在 抛出异常 - if (!is_file($template) || (APP_DEBUG && IS_WIN && realpath($template) != $template)) { - throw new Exception('template file not exists:' . $template, 10700); - } - // 记录视图信息 - APP_DEBUG && Log::record('[ VIEW ] ' . $template . ' [ ' . var_export($vars, true) . ' ]', 'info'); - } - // 页面缓存 - ob_start(); - ob_implicit_flush(0); - if ('php' == $this->engine || empty($this->engine)) { - // 原生PHP解析 - extract($vars, EXTR_OVERWRITE); - is_file($template) ? include $template : eval('?>' . $template); - } else { - // 指定模板引擎 - $this->engine->fetch($template, $vars, $cache); - } - // 获取并清空缓存 - $content = ob_get_clean(); - // 允许用户自定义模板的字符串替换 - if (!empty($this->config['parse_str'])) { - $replace = $this->config['parse_str']; - $content = str_replace(array_keys($replace), array_values($replace), $content); - } - return $content; - } - - /** - * 渲染内容输出 - * @access public - * @param string $content 内容 - * @param array $vars 模板输出变量 - * @return mixed - */ - public function show($content, $vars = []) - { - return $this->fetch($content, $vars, '', true); - } - - /** - * 自动定位模板文件 - * @access private - * @param string $template 模板文件规则 - * @return string - */ - private function parseTemplate($template) - { - if (is_file($template)) { - return realpath($template); - } - $depr = $this->config['view_depr']; - $template = str_replace(['/', ':'], $depr, $template); - - // 获取当前模块 - $module = MODULE_NAME; - if (strpos($template, '@')) { - // 跨模块调用模版文件 - list($module, $template) = explode('@', $template); - } - // 获取当前主题的模版路径 - defined('THEME_PATH') || define('THEME_PATH', $this->getThemePath($module)); - - // 分析模板文件规则 - if ('' == $template) { - // 如果模板文件名为空 按照默认规则定位 - $template = CONTROLLER_NAME . $depr . ACTION_NAME; - } elseif (false === strpos($template, $depr)) { - $template = CONTROLLER_NAME . $depr . $template; - } - return THEME_PATH . $template . $this->config['view_suffix']; - } - - /** - * 获取当前的模板主题 - * @access private - * @param string $module 模块名 - * @return string - */ - private function getTemplateTheme($module) - { - if ($this->config['theme_on']) { - if ($this->theme) { - // 指定模板主题 - $theme = $this->theme; - } elseif ($this->config['auto_detect_theme']) { - // 自动侦测模板主题 - $t = $this->config['var_theme']; - if (isset($_GET[$t])) { - $theme = $_GET[$t]; - } elseif (Cookie::get('think_theme')) { - $theme = Cookie::get('think_theme'); - } - if (!isset($theme) || !is_dir(APP_PATH . (APP_MULTI_MODULE ? $module . DS : '') . $this->config['view_layer'] . DS . $theme)) { - $theme = $this->config['default_theme']; - } - Cookie::set('think_theme', $theme, 864000); - } else { - $theme = $this->config['default_theme']; - } - return $theme . DS; - } - return ''; - } - - /** - * 获取当前的模板路径 - * @access protected - * @param string $module 模块名 - * @return string - */ - protected function getThemePath($module = MODULE_NAME) - { - // 获取当前主题名称 - $theme = $this->getTemplateTheme($module); - // 获取当前主题的模版路径 - $tmplPath = $this->config['view_path']; // 模块设置独立的视图目录 - if (!$tmplPath) { - // 定义TMPL_PATH 则改变全局的视图目录到模块之外 - $tmplPath = defined('TMPL_PATH') ? TMPL_PATH . $module . DS : APP_PATH . (APP_MULTI_MODULE ? $module . DS : '') . $this->config['view_layer'] . DS; - } - return realpath($tmplPath) . DS . $theme; - } - - /** - * 模板变量赋值 - * @access public - * @param string $name 变量名 - * @param mixed $value 变量值 - */ - public function __set($name, $value) - { - $this->data[$name] = $value; - } - - /** - * 取得模板显示变量的值 - * @access protected - * @param string $name 模板变量 - * @return mixed - */ - public function __get($name) - { - return $this->data[$name]; - } - - /** - * 检测模板变量是否设置 - * @access public - * @param string $name 模板变量名 - * @return bool - */ - public function __isset($name) - { - return isset($this->data[$name]); - } -} diff --git a/thinkphp/library/think/cache/driver/Apc.php b/thinkphp/library/think/cache/driver/Apc.php deleted file mode 100644 index cc97bd09c..000000000 --- a/thinkphp/library/think/cache/driver/Apc.php +++ /dev/null @@ -1,121 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\cache\driver; - -use think\Cache; -use think\Exception; - -/** - * Apc缓存驱动 - * @author liu21st - */ -class Apc -{ - - protected $options = [ - 'expire' => 0, - 'prefix' => '', - 'length' => 0, - ]; - /***************************** - 需要支持apc_cli模式 - ******************************/ - /** - * 架构函数 - * - * @param array $options 缓存参数 - * - * @throws Exception - * @access public - */ - public function __construct($options = []) - { - if (!function_exists('apc_cache_info')) { - throw new Exception('_NOT_SUPPERT_:Apc'); - } - if (!empty($options)) { - $this->options = array_merge($this->options, $options); - } - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) - { - Cache::$readTimes++; - return apc_fetch($this->options['prefix'] . $name); - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return bool - */ - public function set($name, $value, $expire = null) - { - Cache::$writeTimes++; - if (is_null($expire)) { - $expire = $this->options['expire']; - } - $name = $this->options['prefix'] . $name; - if ($result = apc_store($name, $value, $expire)) { - if ($this->options['length'] > 0) { - // 记录缓存队列 - $queue = apc_fetch('__info__'); - if (!$queue) { - $queue = []; - } - if (false === array_search($name, $queue)) { - array_push($queue, $name); - } - - if (count($queue) > $this->options['length']) { - // 出列 - $key = array_shift($queue); - // 删除缓存 - apc_delete($key); - } - apc_store('__info__', $queue); - } - } - return $result; - } - - /**删除缓存 - * @access public - * - * @param string $name 缓存变量名 - * - * @return bool|\string[] - */ - public function rm($name) - { - return apc_delete($this->options['prefix'] . $name); - } - - /** - * 清除缓存 - * @access public - * @return bool - */ - public function clear() - { - return apc_clear_cache('user'); - } -} diff --git a/thinkphp/library/think/cache/driver/Db.php b/thinkphp/library/think/cache/driver/Db.php deleted file mode 100644 index 7a3504974..000000000 --- a/thinkphp/library/think/cache/driver/Db.php +++ /dev/null @@ -1,165 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\cache\driver; - -use think\Cache; - -/** - * 数据库方式缓存驱动 - * CREATE TABLE think_cache ( - * cachekey varchar(255) NOT NULL, - * expire int(11) NOT NULL, - * data blob, - * datacrc int(32), - * UNIQUE KEY `cachekey` (`cachekey`) - * ); - * @author liu21st - */ -class Db -{ - - protected $handler = null; - protected $options = [ - 'type' => '', - 'dsn' => '', - 'hostname' => '', - 'hostport' => '', - 'username' => '', - 'password' => '', - 'database' => '', - 'charset' => '', - 'table' => '', - 'prefix' => '', - 'expire' => 0, - 'length' => 0, - ]; - - /** - * 架构函数 - * @param array $options 缓存参数 - * @access public - */ - public function __construct($options = []) - { - if (!empty($options)) { - $this->options = array_merge($this->options, $options); - } - $this->handler = \think\Db::connect((!empty($this->options['hostname']) || !empty($this->options['dsn'])) ? $this->options : []); - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) - { - Cache::$readTimes++; - $name = $this->options['prefix'] . addslashes($name); - $result = $this->handler->query('SELECT `data`,`datacrc` FROM `' . $this->options['table'] . '` WHERE `cachekey`=\'' . $name . '\' AND (`expire` =0 OR `expire`>' . time() . ') LIMIT 0,1'); - if (false !== $result) { - $result = $result[0]; - $content = $result['data']; - if (function_exists('gzcompress')) { - //启用数据压缩 - $content = gzuncompress($content); - } - $content = unserialize($content); - return $content; - } else { - return false; - } - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return boolen - */ - public function set($name, $value, $expire = null) - { - Cache::$writeTimes++; - $data = serialize($value); - $name = $this->options['prefix'] . addslashes($name); - if (function_exists('gzcompress')) { - //数据压缩 - $data = gzcompress($data, 3); - } - if (is_null($expire)) { - $expire = $this->options['expire']; - } - $expire = (0 == $expire) ? 0 : (time() + $expire); //缓存有效期为0表示永久缓存 - $result = $this->handler->query('select `cachekey` from `' . $this->options['table'] . '` where `cachekey`=\'' . $name . '\' limit 0,1'); - if (!empty($result)) { - //更新记录 - $result = $this->handler->execute('UPDATE ' . $this->options['table'] . ' SET data=\'' . $data . '\' ,expire=' . $expire . ' WHERE `cachekey`=\'' . $name . '\''); - } else { - //新增记录 - $result = $this->handler->execute('INSERT INTO ' . $this->options['table'] . ' (`cachekey`,`data`,`expire`) VALUES (\'' . $name . '\',\'' . $data . '\',' . $expire . ')'); - } - if ($result) { - if ($this->options['length'] > 0) { - // 记录缓存队列 - $result = $this->handler->query('SELECT `data`,`datacrc` FROM `' . $this->options['table'] . '` WHERE `cachekey`=\'__info__\' AND `expire` =0 LIMIT 0,1'); - $queue = xcache_get('__info__'); - if (!$result) { - $this->handler->execute('INSERT INTO ' . $this->options['table'] . ' (`cachekey`,`data`,`expire`) VALUES (\'__info__\',\'\',0)'); - $queue = []; - } else { - $queue = unserialize($result[0]['data']); - } - if (false === array_search($name, $queue)) { - array_push($queue, $name); - } - - if (count($queue) > $this->options['length']) { - // 出列 - $key = array_shift($queue); - // 删除缓存 - $this->handler->execute('DELETE FROM `' . $this->options['table'] . '` WHERE `cachekey`=\'' . $key . '\''); - } - $this->handler->execute('UPDATE ' . $this->options['table'] . ' SET data=\'' . serialize($queue) . '\' ,expire=0 WHERE `cachekey`=\'__info__\''); - xcache_set('__info__', $queue); - } - return true; - } else { - return false; - } - } - - /** - * 删除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolen - */ - public function rm($name) - { - $name = $this->options['prefix'] . addslashes($name); - return $this->handler->execute('DELETE FROM `' . $this->options['table'] . '` WHERE `cachekey`=\'' . $name . '\''); - } - - /** - * 清除缓存 - * @access public - * @return boolen - */ - public function clear() - { - return $this->handler->execute('TRUNCATE TABLE `' . $this->options['table'] . '`'); - } - -} \ No newline at end of file diff --git a/thinkphp/library/think/cache/driver/File.php b/thinkphp/library/think/cache/driver/File.php deleted file mode 100644 index 367db0f28..000000000 --- a/thinkphp/library/think/cache/driver/File.php +++ /dev/null @@ -1,203 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\cache\driver; - -use think\Cache; - -/** - * 文件类型缓存类 - * @author liu21st - */ -class File -{ - - protected $options = [ - 'expire' => 0, - 'cache_subdir' => false, - 'path_level' => 1, - 'prefix' => '', - 'length' => 0, - 'path' => LOG_PATH, - 'data_compress' => false, - ]; - - /** - * 架构函数 - * @access public - */ - public function __construct($options = []) - { - if (!empty($options)) { - $this->options = array_merge($this->options, $options); - } - if (substr($this->options['path'], -1) != '/') { - $this->options['path'] .= '/'; - } - $this->init(); - } - - /** - * 初始化检查 - * @access private - * @return boolen - */ - private function init() - { - // 创建项目缓存目录 - if (!is_dir($this->options['path'])) { - if (!mkdir($this->options['path'], 0755, true)) { - return false; - } - } - } - - /** - * 取得变量的存储文件名 - * @access private - * @param string $name 缓存变量名 - * @return string - */ - private function filename($name) - { - $name = md5($name); - if ($this->options['cache_subdir']) { - // 使用子目录 - $dir = ''; - $len = $this->options['path_level']; - for ($i = 0; $i < $len; $i++) { - $dir .= $name{$i} . '/'; - } - if (!is_dir($this->options['path'] . $dir)) { - mkdir($this->options['path'] . $dir, 0755, true); - } - $filename = $dir . $this->options['prefix'] . $name . '.php'; - } else { - $filename = $this->options['prefix'] . $name . '.php'; - } - return $this->options['path'] . $filename; - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) - { - $filename = $this->filename($name); - if (!is_file($filename)) { - return false; - } - Cache::$readTimes++; - $content = file_get_contents($filename); - if (false !== $content) { - $expire = (int) substr($content, 8, 12); - if (0 != $expire && time() > filemtime($filename) + $expire) { - //缓存过期删除缓存文件 - unlink($filename); - return false; - } - $content = substr($content, 20, -3); - if ($this->options['data_compress'] && function_exists('gzcompress')) { - //启用数据压缩 - $content = gzuncompress($content); - } - $content = unserialize($content); - return $content; - } else { - return false; - } - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param int $expire 有效时间 0为永久 - * @return boolen - */ - public function set($name, $value, $expire = null) - { - Cache::$writeTimes++; - if (is_null($expire)) { - $expire = $this->options['expire']; - } - $filename = $this->filename($name); - $data = serialize($value); - if ($this->options['data_compress'] && function_exists('gzcompress')) { - //数据压缩 - $data = gzcompress($data, 3); - } - $data = ""; - $result = file_put_contents($filename, $data); - if ($result) { - if ($this->options['length'] > 0) { - // 记录缓存队列 - $queue_file = dirname($filename) . '/__info__.php'; - $queue = unserialize(file_get_contents($queue_file)); - if (!$queue) { - $queue = []; - } - if (false === array_search($name, $queue)) { - array_push($queue, $name); - } - - if (count($queue) > $this->options['length']) { - // 出列 - $key = array_shift($queue); - // 删除缓存 - unlink($this->filename($key)); - } - file_put_contents($queue_file, serialize($queue)); - } - clearstatcache(); - return true; - } else { - return false; - } - } - - /** - * 删除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolen - */ - public function rm($name) - { - return unlink($this->filename($name)); - } - - /** - * 清除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolen - */ - public function clear() - { - $path = $this->options['temp']; - if ($dir = opendir($path)) { - while ($file = readdir($dir)) { - $check = is_dir($file); - if (!$check) { - unlink($path . $file); - } - - } - closedir($dir); - return true; - } - } -} diff --git a/thinkphp/library/think/cache/driver/Lite.php b/thinkphp/library/think/cache/driver/Lite.php deleted file mode 100644 index 6d52b9517..000000000 --- a/thinkphp/library/think/cache/driver/Lite.php +++ /dev/null @@ -1,138 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\cache\driver; - -use think\Cache; - -/** - * 文件类型缓存类 - * @author liu21st - */ -class Lite -{ - protected $options = [ - 'prefix' => '', - 'path' => '', - 'expire' => 0, // 等于 10*365*24*3600(10年) - ]; - - /** - * 架构函数 - * @access public - * - * @param array $options - */ - public function __construct($options = []) - { - if (!empty($options)) { - $this->options = array_merge($this->options, $options); - } - if (substr($this->options['path'], -1) != '/') { - $this->options['path'] .= '/'; - } - - } - - /** - * 取得变量的存储文件名 - * @access private - * @param string $name 缓存变量名 - * @return string - */ - private function filename($name) - { - return $this->options['path'] . $this->options['prefix'] . md5($name) . '.php'; - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) - { - Cache::$readTimes++; - $filename = $this->filename($name); - if (is_file($filename)) { - // 判断是否过期 - $mtime = filemtime($filename); - if ($mtimeoptions['expire']; - } - // 模拟永久 - if (0===$expire) { - $expire = 10*365*24*3600; - } - $filename = $this->filename($name); - // 缓存数据 - /* - $dir = dirname($filename); - // 目录不存在则创建 - if (!is_dir($dir)) - mkdir($dir,0755,true); - */ - $ret = file_put_contents($filename, ("filename($name)); - } - - /** - * 清除缓存 - * @access public - * @return bool - * @internal param string $name 缓存变量名 - */ - public function clear() - { - $filename = $this->filename('*'); - array_map("unlink", glob($filename)); - } -} diff --git a/thinkphp/library/think/cache/driver/Memcached.php b/thinkphp/library/think/cache/driver/Memcached.php deleted file mode 100644 index ea4778d99..000000000 --- a/thinkphp/library/think/cache/driver/Memcached.php +++ /dev/null @@ -1,136 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\cache\driver; - -use think\Cache; -use think\Exception; - -class Memcached -{ - protected $handler = null; - protected $options = [ - 'host' => '127.0.0.1', - 'port' => 11211, - 'expire' => 0, - 'timeout' => 0, // 超时时间(单位:毫秒) - 'length' => 0, - ]; - - /** - * 架构函数 - * @param array $options 缓存参数 - * @access public - */ - public function __construct($options = []) - { - if (!extension_loaded('memcached')) { - throw new Exception('_NOT_SUPPERT_:memcached'); - } - if (!empty($options)) { - $this->options = array_merge($this->options, $options); - } - $this->handler = new \Memcached; - // 设置连接超时时间(单位:毫秒) - if ($this->options['timeout'] > 0) { - $this->handler->setOption(\Memcached::OPT_CONNECT_TIMEOUT, $this->options['timeout']); - } - // 支持集群 - $hosts = explode(',', $this->options['host']); - $ports = explode(',', $this->options['port']); - if (empty($ports[0])) { - $ports[0] = 11211; - } - // 建立连接 - $servers = []; - foreach ((array) $hosts as $i => $host) { - $servers[] = [$host, (isset($ports[$i]) ? $ports[$i] : $ports[0]), 1]; - } - $this->handler->addServers($servers); - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) - { - Cache::$readTimes++; - return $this->handler->get($this->options['prefix'] . $name); - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return bool - */ - public function set($name, $value, $expire = null) - { - Cache::$writeTimes++; - if (is_null($expire)) { - $expire = $this->options['expire']; - } - $name = $this->options['prefix'] . $name; - if ($this->handler->set($name, $value, $expire)) { - if ($this->options['length'] > 0) { - // 记录缓存队列 - $queue = $this->handler->get('__info__'); - if (!$queue) { - $queue = []; - } - if (false === array_search($name, $queue)) { - array_push($queue, $name); - } - - if (count($queue) > $this->options['length']) { - // 出列 - $key = array_shift($queue); - // 删除缓存 - $this->handler->delete($key); - } - $this->handler->set('__info__', $queue); - } - return true; - } - return false; - } - - /** - * 删除缓存 - * - * @param string $name 缓存变量名 - * @param bool|false $ttl - * - * @return bool - */ - public function rm($name, $ttl = false) - { - $name = $this->options['prefix'] . $name; - return false === $ttl ? - $this->handler->delete($name) : - $this->handler->delete($name, $ttl); - } - - /** - * 清除缓存 - * @access public - * @return bool - */ - public function clear() - { - return $this->handler->flush(); - } -} diff --git a/thinkphp/library/think/cache/driver/Redis.php b/thinkphp/library/think/cache/driver/Redis.php deleted file mode 100644 index 9450aa700..000000000 --- a/thinkphp/library/think/cache/driver/Redis.php +++ /dev/null @@ -1,134 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\cache\driver; - -use think\Cache; -use think\Exception; - -/** - * Redis缓存驱动 - * 要求安装phpredis扩展:https://github.com/nicolasff/phpredis - * @author 尘缘 <130775@qq.com> - */ -class Redis -{ - protected $handler = null; - protected $options = [ - 'host' => '127.0.0.1', - 'port' => 6379, - 'password' => '', - 'timeout' => false, - 'expire' => 0, - 'persistent' => false, - 'length' => 0, - ]; - - /** - * 架构函数 - * @param array $options 缓存参数 - * @access public - */ - public function __construct($options = []) - { - if (!extension_loaded('redis')) { - throw new Exception('_NOT_SUPPERT_:redis'); - } - if (!empty($options)) { - $this->options = array_merge($this->options, $options); - } - $func = $this->options['persistent'] ? 'pconnect' : 'connect'; - $this->handler = new \Redis; - false === $this->options['timeout'] ? - $this->handler->$func($this->options['host'], $this->options['port']) : - $this->handler->$func($this->options['host'], $this->options['port'], $this->options['timeout']); - if ('' != $this->options['password']) { - $this->handler->auth($this->options['password']); - } - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) - { - Cache::$readTimes++; - return $this->handler->get($this->options['prefix'] . $name); - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return boolean - */ - public function set($name, $value, $expire = null) - { - Cache::$writeTimes++; - if (is_null($expire)) { - $expire = $this->options['expire']; - } - $name = $this->options['prefix'] . $name; - if (is_int($expire)) { - $result = $this->handler->setex($name, $expire, $value); - } else { - $result = $this->handler->set($name, $value); - } - if ($result && $this->options['length'] > 0) { - if ($this->options['length'] > 0) { - // 记录缓存队列 - $queue = $this->handler->get('__info__'); - if (!$queue) { - $queue = []; - } - if (false === array_search($name, $queue)) { - array_push($queue, $name); - } - - if (count($queue) > $this->options['length']) { - // 出列 - $key = array_shift($queue); - // 删除缓存 - $this->handler->delete($key); - } - $this->handler->set('__info__', $queue); - } - } - return $result; - } - - /** - * 删除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolean - */ - public function rm($name) - { - return $this->handler->delete($this->options['prefix'] . $name); - } - - /** - * 清除缓存 - * @access public - * @return boolean - */ - public function clear() - { - return $this->handler->flushDB(); - } - -} diff --git a/thinkphp/library/think/cache/driver/Sae.php b/thinkphp/library/think/cache/driver/Sae.php deleted file mode 100644 index 57163785b..000000000 --- a/thinkphp/library/think/cache/driver/Sae.php +++ /dev/null @@ -1,158 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\cache\driver; - -use think\Cache; -use think\Exception; - -/** - * SAE Memcache缓存驱动 - * @author liu21st - */ -class Sae -{ - protected $handler = null; - protected $options = [ - 'host' => '127.0.0.1', - 'port' => 11211, - 'expire' => 0, - 'timeout' => false, - 'persistent' => false, - 'length' => 0, - ]; - - /** - * 架构函数 - * @param array $options 缓存参数 - * @access public - */ - public function __construct($options = []) - { - if (!function_exists('memcache_init')) { - throw new Exception('请在SAE平台上运行代码。'); - } - $this->handler = memcache_init(); - if (!$this->handler) { - throw new Exception('您未开通Memcache服务,请在SAE管理平台初始化Memcache服务'); - } - if (!empty($options)) { - $this->options = array_merge($this->options, $options); - } - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) - { - Cache::$readTimes++; - return $this->handler->get($_SERVER['HTTP_APPVERSION'] . '/' . $this->options['prefix'] . $name); - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return bool - */ - public function set($name, $value, $expire = null) - { - Cache::$writeTimes++; - if (is_null($expire)) { - $expire = $this->options['expire']; - } - $name = $this->options['prefix'] . $name; - if ($this->handler->set($_SERVER['HTTP_APPVERSION'] . '/' . $name, $value, 0, $expire)) { - if ($this->options['length'] > 0) { - // 记录缓存队列 - $this->queue($name); - } - return true; - } - return false; - } - - /** - * 删除缓存 - * - * @param string $name 缓存变量名 - * @param bool|false $ttl - * - * @return bool - */ - public function rm($name, $ttl = false) - { - $name = $_SERVER['HTTP_APPVERSION'] . '/' . $this->options['prefix'] . $name; - return false === $ttl ? - $this->handler->delete($name) : - $this->handler->delete($name, $ttl); - } - - /** - * 清除缓存 - * @access public - * @return bool - */ - public function clear() - { - return $this->handler->flush(); - } - - /** - * 获得SaeKv对象 - */ - private function getKv() - { - static $kv; - if (!$kv) { - $kv = new \SaeKV(); - if (!$kv->init()) { - throw new Exception('您没有初始化KVDB,请在SAE管理平台初始化KVDB服务'); - } - } - return $kv; - } - - /** - * 队列缓存 - * @access protected - * @param string $key 队列名 - * @return mixed - */ - //[sae] 下重写queque队列缓存方法 - protected function queue($key) - { - $queue_name = isset($this->options['queue_name']) ? $this->options['queue_name'] : 'think_queue'; - $kv = $this->getKv(); - $value = $kv->get($queue_name); - if (!$value) { - $value = []; - } - // 进列 - if (false === array_search($key, $value)) { - array_push($value, $key); - } - - if (count($value) > $this->options['length']) { - // 出列 - $key = array_shift($value); - // 删除缓存 - $this->rm($key); - } - return $kv->set($queue_name, $value); - } -} diff --git a/thinkphp/library/think/cache/driver/Secache.php b/thinkphp/library/think/cache/driver/Secache.php deleted file mode 100644 index 13ac9ccd1..000000000 --- a/thinkphp/library/think/cache/driver/Secache.php +++ /dev/null @@ -1,787 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\cache\driver; - -use think\Cache; - -/** - * Secache缓存驱动 - * @author liu21st - */ -class Secache -{ - - protected $handler = null; - protected $options = [ - 'project' => '', - 'path' => '', - 'expire' => 0, - 'prefix' => '', - 'length' => 0, - ]; - - /** - * 架构函数 - * @param array $options 缓存参数 - * @access public - */ - public function __construct($options = []) - { - if (!empty($options)) { - $this->options = array_merge($this->options, $options); - } - if (substr($this->options['path'], -1) != '/') { - $this->options['path'] .= '/'; - } - - $this->handler = new SecacheClient; - $this->handler->workat($this->options['path'] . $this->options['project']); - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) - { - Cache::$readTimes++; - $name = $this->options['prefix'] . $name; - $key = md5($name); - $this->handler->fetch($key, $return); - return $return; - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return boolean - */ - public function set($name, $value) - { - Cache::$writeTimes++; - $name = $this->options['prefix'] . $name; - $key = md5($name); - if ($result = $this->handler->store($key, $value)) { - if ($this->options['length'] > 0) { - // 记录缓存队列 - $queue = $this->handler->fetch(md5('__info__')); - if (!$queue) { - $queue = []; - } - if (false === array_search($key, $queue)) { - array_push($queue, $key); - } - - if (count($queue) > $this->options['length']) { - // 出列 - $key = array_shift($queue); - // 删除缓存 - $this->handler->delete($key); - } - $this->handler->store(md5('__info__'), $queue); - } - } - return $result; - } - - /** - * 删除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolen - */ - public function rm($name) - { - $name = $this->options['prefix'] . $name; - $key = md5($name); - return $this->handler->delete($key); - } - - /** - * 清除缓存 - * @access public - * @return boolen - */ - public function clear() - { - return $this->handler->_format(true); - } - -} - -if (!defined('SECACHE_SIZE')) { - define('SECACHE_SIZE', '15M'); -} -class SecacheClient -{ - - public $idx_node_size = 40; - public $data_base_pos = 262588; //40+20+24*16+16*16*16*16*4; - public $schema_item_size = 24; - public $header_padding = 20; //保留空间 放置php标记防止下载 - public $info_size = 20; //保留空间 4+16 maxsize|ver - - //40起 添加20字节保留区域 - public $idx_seq_pos = 40; //id 计数器节点地址 - public $dfile_cur_pos = 44; //id 计数器节点地址 - public $idx_free_pos = 48; //id 空闲链表入口地址 - - public $idx_base_pos = 444; //40+20+24*16 - public $min_size = 10240; //10M最小值 - public $schema_struct = array('size', 'free', 'lru_head', 'lru_tail', 'hits', 'miss'); - public $ver = '$Rev: 3 $'; - public $name = '系统默认缓存(文件型)'; - - public function workat($file) - { - - $this->_file = $file . '.php'; - $this->_bsize_list = array( - 512 => 10, - 3 << 10 => 10, - 8 << 10 => 10, - 20 << 10 => 4, - 30 << 10 => 2, - 50 << 10 => 2, - 80 << 10 => 2, - 96 << 10 => 2, - 128 << 10 => 2, - 224 << 10 => 2, - 256 << 10 => 2, - 512 << 10 => 1, - 1024 << 10 => 1, - ); - - $this->_node_struct = array( - 'next' => array(0, 'V'), - 'prev' => array(4, 'V'), - 'data' => array(8, 'V'), - 'size' => array(12, 'V'), - 'lru_right' => array(16, 'V'), - 'lru_left' => array(20, 'V'), - 'key' => array(24, 'H*'), - ); - - if (!file_exists($this->_file)) { - $this->create(); - } else { - $this->_rs = fopen($this->_file, 'rb+') || $this->triggerError('Can\'t open the cachefile: ' . realpath($this->_file), E_USER_ERROR); - $this->_seek($this->header_padding); - $info = unpack('V1max_size/a*ver', fread($this->_rs, $this->info_size)); - if ($info['ver'] != $this->ver) { - $this->_format(true); - } else { - $this->max_size = $info['max_size']; - } - } - - $this->idx_node_base = $this->data_base_pos + $this->max_size; - $this->_block_size_list = array_keys($this->_bsize_list); - sort($this->_block_size_list); - return true; - } - - public function create() - { - $this->_rs = fopen($this->_file, 'wb+') || $this->triggerError('Can\'t open the cachefile: ' . realpath($this->_file), E_USER_ERROR); - fseek($this->_rs, 0); - fputs($this->_rs, '<' . '?php exit()?' . '>'); - return $this->_format(); - } - - public function _puts($offset, $data) - { - if ($offset < $this->max_size * 1.5) { - $this->_seek($offset); - return fputs($this->_rs, $data); - } else { - $this->triggerError('Offset over quota:' . $offset, E_USER_ERROR); - } - } - - public function _seek($offset) - { - return fseek($this->_rs, $offset); - } - - public function clear() - { - return $this->_format(true); - } - - public function fetch($key, &$return) - { - - if ($this->lock(false)) { - $locked = true; - } - - if ($this->search($key, $offset)) { - $info = $this->_get_node($offset); - $schema_id = $this->_get_size_schema_id($info['size']); - if (false === $schema_id) { - if ($locked) { - $this->unlock(); - } - - return false; - } - - $this->_seek($info['data']); - $data = fread($this->_rs, $info['size']); - $return = unserialize($data); - - if (false === $return) { - if ($locked) { - $this->unlock(); - } - - return false; - } - - if ($locked) { - $this->_lru_push($schema_id, $info['offset']); - $this->_set_schema($schema_id, 'hits', $this->_get_schema($schema_id, 'hits') + 1); - return $this->unlock(); - } else { - return true; - } - } else { - if ($locked) { - $this->unlock(); - } - - return false; - } - } - - /** - * lock - * 如果flock不管用,请继承本类,并重载此方法 - * - * @param mixed $is_block 是否阻塞 - * @access public - * @return void - */ - public function lock($is_block, $whatever = false) - { - return flock($this->_rs, $is_block ? LOCK_EX : LOCK_EX + LOCK_NB); - } - - /** - * unlock - * 如果flock不管用,请继承本类,并重载此方法 - * - * @access public - * @return void - */ - public function unlock() - { - return flock($this->_rs, LOCK_UN); - } - - public function delete($key, $pos = false) - { - if ($pos || $this->search($key, $pos)) { - if ($info = $this->_get_node($pos)) { - //删除data区域 - if ($info['prev']) { - $this->_set_node($info['prev'], 'next', $info['next']); - $this->_set_node($info['next'], 'prev', $info['prev']); - } else { - //改入口位置 - $this->_set_node($info['next'], 'prev', 0); - $this->_set_node_root($key, $info['next']); - } - $this->_free_dspace($info['size'], $info['data']); - $this->_lru_delete($info); - $this->_free_node($pos); - return $info['prev']; - } - } - return false; - } - - public function store($key, $value) - { - - if ($this->lock(true)) { - //save data - $data = serialize($value); - $size = strlen($data); - - //get list_idx - $has_key = $this->search($key, $list_idx_offset); - $schema_id = $this->_get_size_schema_id($size); - if (false === $schema_id) { - $this->unlock(); - return false; - } - if ($has_key) { - $hdseq = $list_idx_offset; - - $info = $this->_get_node($hdseq); - if ($this->_get_size_schema_id($info['size']) == $schema_id) { - $dataoffset = $info['data']; - } else { - //破掉原有lru - $this->_lru_delete($info); - if (!($dataoffset = $this->_dalloc($schema_id))) { - $this->unlock(); - return false; - } - $this->_free_dspace($info['size'], $info['data']); - $this->_set_node($hdseq, 'lru_left', 0); - $this->_set_node($hdseq, 'lru_right', 0); - } - - $this->_set_node($hdseq, 'size', $size); - $this->_set_node($hdseq, 'data', $dataoffset); - } else { - - if (!($dataoffset = $this->_dalloc($schema_id))) { - $this->unlock(); - return false; - } - $hdseq = $this->_alloc_idx(array( - 'next' => 0, - 'prev' => $list_idx_offset, - 'data' => $dataoffset, - 'size' => $size, - 'lru_right' => 0, - 'lru_left' => 0, - 'key' => $key, - )); - - if ($list_idx_offset > 0) { - $this->_set_node($list_idx_offset, 'next', $hdseq); - } else { - $this->_set_node_root($key, $hdseq); - } - } - - if ($dataoffset > $this->max_size) { - $this->triggerError('alloc datasize:' . $dataoffset, E_USER_WARNING); - return false; - } - $this->_puts($dataoffset, $data); - - $this->_set_schema($schema_id, 'miss', $this->_get_schema($schema_id, 'miss') + 1); - - $this->_lru_push($schema_id, $hdseq); - $this->unlock(); - return true; - } else { - $this->triggerError("Couldn't lock the file !", E_USER_WARNING); - return false; - } - - } - - /** - * search - * 查找指定的key - * 如果找到节点则$pos=节点本身 返回true - * 否则 $pos=树的末端 返回false - * - * @param mixed $key - * @access public - * @return void - */ - public function search($key, &$pos) - { - return $this->_get_pos_by_key($this->_get_node_root($key), $key, $pos); - } - - public function _get_size_schema_id($size) - { - foreach ($this->_block_size_list as $k => $block_size) { - if ($size <= $block_size) { - return $k; - } - } - return false; - } - - public function _parse_str_size($str_size, $default) - { - if (preg_match('/^([0-9]+)\s*([gmk]|)$/i', $str_size, $match)) { - switch (strtolower($match[2])) { - case 'g': - if ($match[1] > 1) { - $this->triggerError('Max cache size 1G', E_USER_ERROR); - } - $size = $match[1] << 30; - break; - case 'm': - $size = $match[1] << 20; - break; - case 'k': - $size = $match[1] << 10; - break; - default: - $size = $match[1]; - } - if ($size <= 0) { - $this->triggerError('Error cache size ' . $this->max_size, E_USER_ERROR); - return false; - } elseif ($size < 10485760) { - return 10485760; - } else { - return $size; - } - } else { - return $default; - } - } - - public function _format($truncate = false) - { - if ($this->lock(true, true)) { - - if ($truncate) { - $this->_seek(0); - ftruncate($this->_rs, $this->idx_node_base); - } - - $this->max_size = $this->_parse_str_size(SECACHE_SIZE, 15728640); //default:15m - $this->_puts($this->header_padding, pack('V1a*', $this->max_size, $this->ver)); - - ksort($this->_bsize_list); - $ds_offset = $this->data_base_pos; - $i = 0; - foreach ($this->_bsize_list as $size => $count) { - - //将预分配的空间注册到free链表里 - $count *= min(3, floor($this->max_size / 10485760)); - $next_free_node = 0; - for ($j = 0; $j < $count; $j++) { - $this->_puts($ds_offset, pack('V', $next_free_node)); - $next_free_node = $ds_offset; - $ds_offset += intval($size); - } - - $code = pack(str_repeat('V1', count($this->schema_struct)), $size, $next_free_node, 0, 0, 0, 0); - - $this->_puts(60 + $i * $this->schema_item_size, $code); - $i++; - } - $this->_set_dcur_pos($ds_offset); - - $this->_puts($this->idx_base_pos, str_repeat("\0", 262144)); - $this->_puts($this->idx_seq_pos, pack('V', 1)); - $this->unlock(); - return true; - } else { - $this->triggerError("Couldn't lock the file !", E_USER_ERROR); - return false; - } - } - - public function _get_node_root($key) - { - $this->_seek(hexdec(substr($key, 0, 4)) * 4 + $this->idx_base_pos); - $a = fread($this->_rs, 4); - list(, $offset) = unpack('V', $a); - return $offset; - } - - public function _set_node_root($key, $value) - { - return $this->_puts(hexdec(substr($key, 0, 4)) * 4 + $this->idx_base_pos, pack('V', $value)); - } - - public function _set_node($pos, $key, $value) - { - - if (!$pos) { - return false; - } - - if (isset($this->_node_struct[$key])) { - return $this->_puts($pos * $this->idx_node_size + $this->idx_node_base + $this->_node_struct[$key][0], pack($this->_node_struct[$key][1], $value)); - } else { - return false; - } - } - - public function _get_pos_by_key($offset, $key, &$pos) - { - if (!$offset) { - $pos = 0; - return false; - } - - $info = $this->_get_node($offset); - - if ($info['key'] == $key) { - $pos = $info['offset']; - return true; - } elseif ($info['next'] && $info['next'] != $offset) { - return $this->_get_pos_by_key($info['next'], $key, $pos); - } else { - $pos = $offset; - return false; - } - } - - public function _lru_delete($info) - { - - if ($info['lru_right']) { - $this->_set_node($info['lru_right'], 'lru_left', $info['lru_left']); - } else { - $this->_set_schema($this->_get_size_schema_id($info['size']), 'lru_tail', $info['lru_left']); - } - - if ($info['lru_left']) { - $this->_set_node($info['lru_left'], 'lru_right', $info['lru_right']); - } else { - $this->_set_schema($this->_get_size_schema_id($info['size']), 'lru_head', $info['lru_right']); - } - - return true; - } - - public function _lru_push($schema_id, $offset) - { - $lru_head = $this->_get_schema($schema_id, 'lru_head'); - $lru_tail = $this->_get_schema($schema_id, 'lru_tail'); - - if ((!$offset) || ($lru_head == $offset)) { - return; - } - - $info = $this->_get_node($offset); - - $this->_set_node($info['lru_right'], 'lru_left', $info['lru_left']); - $this->_set_node($info['lru_left'], 'lru_right', $info['lru_right']); - - $this->_set_node($offset, 'lru_right', $lru_head); - $this->_set_node($offset, 'lru_left', 0); - - $this->_set_node($lru_head, 'lru_left', $offset); - $this->_set_schema($schema_id, 'lru_head', $offset); - - if (0 == $lru_tail) { - $this->_set_schema($schema_id, 'lru_tail', $offset); - } elseif ($lru_tail == $offset && $info['lru_left']) { - $this->_set_schema($schema_id, 'lru_tail', $info['lru_left']); - } - return true; - } - - public function _get_node($offset) - { - $this->_seek($offset * $this->idx_node_size + $this->idx_node_base); - $info = unpack('V1next/V1prev/V1data/V1size/V1lru_right/V1lru_left/H*key', fread($this->_rs, $this->idx_node_size)); - $info['offset'] = $offset; - return $info; - } - - public function _lru_pop($schema_id) - { - if ($node = $this->_get_schema($schema_id, 'lru_tail')) { - $info = $this->_get_node($node); - if (!$info['data']) { - return false; - } - $this->delete($info['key'], $info['offset']); - if (!$this->_get_schema($schema_id, 'free')) { - $this->triggerError('pop lru,But nothing free...', E_USER_ERROR); - } - return $info; - } else { - return false; - } - } - - public function _dalloc($schema_id, $lru_freed = false) - { - - if ($free = $this->_get_schema($schema_id, 'free')) { - //如果lru里有链表 - $this->_seek($free); - list(, $next) = unpack('V', fread($this->_rs, 4)); - $this->_set_schema($schema_id, 'free', $next); - return $free; - } elseif ($lru_freed) { - $this->triggerError('Bat lru poped freesize', E_USER_ERROR); - return false; - } else { - $ds_offset = $this->_get_dcur_pos(); - $size = $this->_get_schema($schema_id, 'size'); - - if ($size + $ds_offset > $this->max_size) { - if ($info = $this->_lru_pop($schema_id)) { - return $this->_dalloc($schema_id, $info); - } else { - $this->triggerError('Can\'t alloc dataspace', E_USER_ERROR); - return false; - } - } else { - $this->_set_dcur_pos($ds_offset + $size); - return $ds_offset; - } - } - } - - public function _get_dcur_pos() - { - $this->_seek($this->dfile_cur_pos); - list(, $ds_offset) = unpack('V', fread($this->_rs, 4)); - return $ds_offset; - } - public function _set_dcur_pos($pos) - { - return $this->_puts($this->dfile_cur_pos, pack('V', $pos)); - } - - public function _free_dspace($size, $pos) - { - - if ($pos > $this->max_size) { - $this->triggerError('free dspace over quota:' . $pos, E_USER_ERROR); - return false; - } - - $schema_id = $this->_get_size_schema_id($size); - if ($free = $this->_get_schema($schema_id, 'free')) { - $this->_puts($free, pack('V1', $pos)); - } else { - $this->_set_schema($schema_id, 'free', $pos); - } - $this->_puts($pos, pack('V1', 0)); - } - - public function _dfollow($pos, &$c) - { - $c++; - $this->_seek($pos); - list(, $next) = unpack('V1', fread($this->_rs, 4)); - if ($next) { - return $this->_dfollow($next, $c); - } else { - return $pos; - } - } - - public function _free_node($pos) - { - $this->_seek($this->idx_free_pos); - list(, $prev_free_node) = unpack('V', fread($this->_rs, 4)); - $this->_puts($pos * $this->idx_node_size + $this->idx_node_base, pack('V', $prev_free_node) . str_repeat("\0", $this->idx_node_size - 4)); - return $this->_puts($this->idx_free_pos, pack('V', $pos)); - } - - public function _alloc_idx($data) - { - $this->_seek($this->idx_free_pos); - list(, $list_pos) = unpack('V', fread($this->_rs, 4)); - if ($list_pos) { - - $this->_seek($list_pos * $this->idx_node_size + $this->idx_node_base); - list(, $prev_free_node) = unpack('V', fread($this->_rs, 4)); - $this->_puts($this->idx_free_pos, pack('V', $prev_free_node)); - - } else { - $this->_seek($this->idx_seq_pos); - list(, $list_pos) = unpack('V', fread($this->_rs, 4)); - $this->_puts($this->idx_seq_pos, pack('V', $list_pos + 1)); - } - return $this->_create_node($list_pos, $data); - } - - public function _create_node($pos, $data) - { - $this->_puts($pos * $this->idx_node_size + $this->idx_node_base - , pack('V1V1V1V1V1V1H*', $data['next'], $data['prev'], $data['data'], $data['size'], $data['lru_right'], $data['lru_left'], $data['key'])); - return $pos; - } - - public function _set_schema($schema_id, $key, $value) - { - $info = array_flip($this->schema_struct); - return $this->_puts(60 + $schema_id * $this->schema_item_size + $info[$key] * 4, pack('V', $value)); - } - - public function _get_schema($id, $key) - { - $info = array_flip($this->schema_struct); - - $this->_seek(60 + $id * $this->schema_item_size); - unpack('V1' . implode('/V1', $this->schema_struct), fread($this->_rs, $this->schema_item_size)); - - $this->_seek(60 + $id * $this->schema_item_size + $info[$key] * 4); - list(, $value) = unpack('V', fread($this->_rs, 4)); - return $value; - } - - public function _all_schemas() - { - $schema = []; - for ($i = 0; $i < 16; $i++) { - $this->_seek(60 + $i * $this->schema_item_size); - $info = unpack('V1' . implode('/V1', $this->schema_struct), fread($this->_rs, $this->schema_item_size)); - if ($info['size']) { - $info['id'] = $i; - $schema[$i] = $info; - } else { - return $schema; - } - } - } - - public function schemaStatus() - { - $return = []; - foreach ($this->_all_schemas() as $k => $schemaItem) { - if ($schemaItem['free']) { - $this->_dfollow($schemaItem['free'], $schemaItem['freecount']); - } - $return[] = $schemaItem; - } - return $return; - } - - public function status(&$curBytes, &$totalBytes) - { - $totalBytes = $curBytes = 0; - $hits = $miss = 0; - - $schemaStatus = $this->schemaStatus(); - $totalBytes = $this->max_size; - $freeBytes = $this->max_size - $this->_get_dcur_pos(); - - foreach ($schemaStatus as $schema) { - $freeBytes += $schema['freecount'] * $schema['size']; - $miss += $schema['miss']; - $hits += $schema['hits']; - } - $curBytes = $totalBytes - $freeBytes; - - $return[] = array('name' => '缓存命中', 'value' => $hits); - $return[] = array('name' => '缓存未命中', 'value' => $miss); - return $return; - } - - public function triggerError($errstr, $errno) - { - triggerError($errstr, $errno); - } - -} diff --git a/thinkphp/library/think/cache/driver/Sqlite.php b/thinkphp/library/think/cache/driver/Sqlite.php deleted file mode 100644 index 254bdebc4..000000000 --- a/thinkphp/library/think/cache/driver/Sqlite.php +++ /dev/null @@ -1,133 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\cache\driver; - -use think\Cache; -use think\Exception; - -/** - * Sqlite缓存驱动 - * @author liu21st - */ -class Sqlite -{ - - protected $options = [ - 'db' => ':memory:', - 'table' => 'sharedmemory', - 'prefix' => '', - 'expire' => 0, - 'length' => 0, - 'persistent' => false, - ]; - - /** - * 架构函数 - * - * @param array $options 缓存参数 - * - * @throws Exception - * @access public - */ - public function __construct($options = []) - { - if (!extension_loaded('sqlite')) { - throw new Exception('_NOT_SUPPERT_:sqlite'); - } - if (!empty($options)) { - $this->options = array_merge($this->options, $options); - } - $func = $this->options['persistent'] ? 'sqlite_popen' : 'sqlite_open'; - $this->handler = $func($this->options['db']); - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) - { - Cache::$readTimes++; - $name = $this->options['prefix'] . sqlite_escape_string($name); - $sql = 'SELECT value FROM ' . $this->options['table'] . ' WHERE var=\'' . $name . '\' AND (expire=0 OR expire >' . time() . ') LIMIT 1'; - $result = sqlite_query($this->handler, $sql); - if (sqlite_num_rows($result)) { - $content = sqlite_fetch_single($result); - if (function_exists('gzcompress')) { - //启用数据压缩 - $content = gzuncompress($content); - } - return unserialize($content); - } - return false; - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return boolean - */ - public function set($name, $value, $expire = null) - { - Cache::$writeTimes++; - $name = $this->options['prefix'] . sqlite_escape_string($name); - $value = sqlite_escape_string(serialize($value)); - if (is_null($expire)) { - $expire = $this->options['expire']; - } - $expire = (0 == $expire) ? 0 : (time() + $expire); //缓存有效期为0表示永久缓存 - if (function_exists('gzcompress')) { - //数据压缩 - $value = gzcompress($value, 3); - } - $sql = 'REPLACE INTO ' . $this->options['table'] . ' (var, value,expire) VALUES (\'' . $name . '\', \'' . $value . '\', \'' . $expire . '\')'; - if (sqlite_query($this->handler, $sql)) { - if ($this->options['length'] > 0) { - // 记录缓存队列 - $this->queue($name); - } - return true; - } - return false; - } - - /** - * 删除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolean - */ - public function rm($name) - { - $name = $this->options['prefix'] . sqlite_escape_string($name); - $sql = 'DELETE FROM ' . $this->options['table'] . ' WHERE var=\'' . $name . '\''; - sqlite_query($this->handler, $sql); - return true; - } - - /** - * 清除缓存 - * @access public - * @return boolean - */ - public function clear() - { - $sql = 'DELETE FROM ' . $this->options['table']; - sqlite_query($this->handler, $sql); - return; - } -} diff --git a/thinkphp/library/think/cache/driver/Wincache.php b/thinkphp/library/think/cache/driver/Wincache.php deleted file mode 100644 index 397f58dac..000000000 --- a/thinkphp/library/think/cache/driver/Wincache.php +++ /dev/null @@ -1,120 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\cache\driver; - -use think\Cache; -use think\Exception; - -/** - * Wincache缓存驱动 - * @author liu21st - */ -class Wincache -{ - - protected $options = [ - 'prefix' => '', - 'expire' => 0, - 'length' => 0, - ]; - - /** - * 架构函数 - * - * @param array $options 缓存参数 - * - * @throws Exception - * @access public - */ - public function __construct($options = []) - { - if (!function_exists('wincache_ucache_info')) { - throw new Exception('_NOT_SUPPERT_:WinCache'); - } - if (!empty($options)) { - $this->options = array_merge($this->options, $options); - } - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) - { - Cache::$readTimes++; - $name = $this->options['prefix'] . $name; - return wincache_ucache_exists($name) ? wincache_ucache_get($name) : false; - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return boolean - */ - public function set($name, $value, $expire = null) - { - Cache::$writeTimes++; - if (is_null($expire)) { - $expire = $this->options['expire']; - } - $name = $this->options['prefix'] . $name; - if (wincache_ucache_set($name, $value, $expire)) { - if ($this->options['length'] > 0) { - // 记录缓存队列 - $queue = wincache_ucache_get('__info__'); - if (!$queue) { - $queue = []; - } - if (false === array_search($name, $queue)) { - array_push($queue, $name); - } - - if (count($queue) > $this->options['length']) { - // 出列 - $key = array_shift($queue); - // 删除缓存 - wincache_ucache_delete($key); - } - wincache_ucache_set('__info__', $queue); - } - return true; - } - return false; - } - - /** - * 删除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolean - */ - public function rm($name) - { - return wincache_ucache_delete($this->options['prefix'] . $name); - } - - /** - * 清除缓存 - * @access public - * @return boolean - */ - public function clear() - { - return; - } -} diff --git a/thinkphp/library/think/cache/driver/Xcache.php b/thinkphp/library/think/cache/driver/Xcache.php deleted file mode 100644 index 5cca03acc..000000000 --- a/thinkphp/library/think/cache/driver/Xcache.php +++ /dev/null @@ -1,120 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\cache\driver; - -use think\Cache; -use think\Exception; - -/** - * Xcache缓存驱动 - * @author liu21st - */ -class Xcache -{ - - protected $options = [ - 'prefix' => '', - 'expire' => 0, - 'length' => 0, - ]; - - /** - * 架构函数 - * @param array $options 缓存参数 - * @access public - */ - public function __construct($options = []) - { - if (!function_exists('xcache_info')) { - throw new Exception('_NOT_SUPPERT_:Xcache'); - } - if (!empty($options)) { - $this->options = array_merge($this->options, $options); - } - } - - /** - * 读取缓存 - * @access public - * @param string $name 缓存变量名 - * @return mixed - */ - public function get($name) - { - Cache::$readTimes++; - $name = $this->options['prefix'] . $name; - if (xcache_isset($name)) { - return xcache_get($name); - } - return false; - } - - /** - * 写入缓存 - * @access public - * @param string $name 缓存变量名 - * @param mixed $value 存储数据 - * @param integer $expire 有效时间(秒) - * @return boolean - */ - public function set($name, $value, $expire = null) - { - Cache::$writeTimes++; - if (is_null($expire)) { - $expire = $this->options['expire']; - } - $name = $this->options['prefix'] . $name; - if (xcache_set($name, $value, $expire)) { - if ($this->options['length'] > 0) { - // 记录缓存队列 - $queue = xcache_get('__info__'); - if (!$queue) { - $queue = []; - } - if (false === array_search($name, $queue)) { - array_push($queue, $name); - } - - if (count($queue) > $this->options['length']) { - // 出列 - $key = array_shift($queue); - // 删除缓存 - xcache_unset($key); - } - xcache_set('__info__', $queue); - } - return true; - } - return false; - } - - /** - * 删除缓存 - * @access public - * @param string $name 缓存变量名 - * @return boolean - */ - public function rm($name) - { - return xcache_unset($this->options['prefix'] . $name); - } - - /** - * 清除缓存 - * @access public - * @return boolean - */ - public function clear() - { - return; - } -} diff --git a/thinkphp/library/think/config/driver/Ini.php b/thinkphp/library/think/config/driver/Ini.php deleted file mode 100644 index d8dc558d4..000000000 --- a/thinkphp/library/think/config/driver/Ini.php +++ /dev/null @@ -1,24 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\config\driver; - -class Ini -{ - public function parse($config) - { - if (is_file($config)) { - return parse_ini_file($config, true); - } else { - return parse_ini_string($config, true); - } - } -} diff --git a/thinkphp/library/think/config/driver/Xml.php b/thinkphp/library/think/config/driver/Xml.php deleted file mode 100644 index 5bc93015a..000000000 --- a/thinkphp/library/think/config/driver/Xml.php +++ /dev/null @@ -1,31 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\config\driver; - -class Xml -{ - public function parse($config) - { - if (is_file($config)) { - $content = simplexml_load_file($config); - } else { - $content = simplexml_load_string($config); - } - $result = (array) $content; - foreach ($result as $key => $val) { - if (is_object($val)) { - $result[$key] = (array) $val; - } - } - return $result; - } -} diff --git a/thinkphp/library/think/controller/Hprose.php b/thinkphp/library/think/controller/Hprose.php deleted file mode 100644 index cf0711e72..000000000 --- a/thinkphp/library/think/controller/Hprose.php +++ /dev/null @@ -1,67 +0,0 @@ - -// +---------------------------------------------------------------------- -namespace think\controller; - -/** - * ThinkPHP Hprose控制器类 - */ -abstract class Hprose -{ - - protected $allowMethodList = ''; - protected $crossDomain = false; - protected $P3P = false; - protected $get = true; - protected $debug = false; - - /** - * 架构函数 - * @access public - */ - public function __construct() - { - //控制器初始化 - if (method_exists($this, '_initialize')) { - $this->_initialize(); - } - - //导入类库 - \think\Loader::import('vendor.Hprose.HproseHttpServer'); - //实例化HproseHttpServer - $server = new \HproseHttpServer(); - if ($this->allowMethodList) { - $methods = $this->allowMethodList; - } else { - $methods = get_class_methods($this); - $methods = array_diff($methods, array('__construct', '__call', '_initialize')); - } - $server->addMethods($methods, $this); - if (APP_DEBUG || $this->debug) { - $server->setDebugEnabled(true); - } - // Hprose设置 - $server->setCrossDomainEnabled($this->crossDomain); - $server->setP3PEnabled($this->P3P); - $server->setGetEnabled($this->get); - // 启动server - $server->start(); - } - - /** - * 魔术方法 有不存在的操作的时候执行 - * @access public - * @param string $method 方法名 - * @param array $args 参数 - * @return mixed - */ - public function __call($method, $args) - {} -} diff --git a/thinkphp/library/think/controller/Jsonrpc.php b/thinkphp/library/think/controller/Jsonrpc.php deleted file mode 100644 index e93d80a1a..000000000 --- a/thinkphp/library/think/controller/Jsonrpc.php +++ /dev/null @@ -1,45 +0,0 @@ - -// +---------------------------------------------------------------------- -namespace think\controller; - -/** - * ThinkPHP JsonRPC控制器类 - */ -abstract class Jsonrpc -{ - - /** - * 架构函数 - * @access public - */ - public function __construct() - { - //控制器初始化 - if (method_exists($this, '_initialize')) { - $this->_initialize(); - } - - //导入类库 - \think\Loader::import('vendor.jsonrpc.jsonRPCServer'); - // 启动server - \jsonRPCServer::handle($this); - } - - /** - * 魔术方法 有不存在的操作的时候执行 - * @access public - * @param string $method 方法名 - * @param array $args 参数 - * @return mixed - */ - public function __call($method, $args) - {} -} diff --git a/thinkphp/library/think/controller/Rest.php b/thinkphp/library/think/controller/Rest.php deleted file mode 100644 index 33372e1b9..000000000 --- a/thinkphp/library/think/controller/Rest.php +++ /dev/null @@ -1,140 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\controller; - -use think\Response; - -abstract class Rest -{ - - protected $_method = ''; // 当前请求类型 - protected $_type = ''; // 当前资源类型 - // 输出类型 - protected $restMethodList = 'get|post|put|delete'; - protected $restDefaultMethod = 'get'; - protected $restTypeList = 'html|xml|json|rss'; - protected $restDefaultType = 'html'; - protected $restOutputType = [ // REST允许输出的资源类型列表 - 'xml' => 'application/xml', - 'json' => 'application/json', - 'html' => 'text/html', - ]; - - /** - * 架构函数 取得模板对象实例 - * @access public - */ - public function __construct() - { - // 资源类型检测 - if ('' == __EXT__) { - // 自动检测资源类型 - $this->_type = $this->getAcceptType(); - } elseif (!preg_match('/\(' . $this->restTypeList . '\)$/i', __EXT__)) { - // 资源类型非法 则用默认资源类型访问 - $this->_type = $this->restDefaultType; - } else { - $this->_type = __EXT__; - } - // 请求方式检测 - $method = strtolower($_SERVER['REQUEST_METHOD']); - if (false === stripos($this->restMethodList, $method)) { - // 请求方式非法 则用默认请求方法 - $method = $this->restDefaultMethod; - } - $this->_method = $method; - } - - /** - * REST 调用 - * @access public - * - * @param string $method 方法名 - * @param array $args 参数 - * - * @return mixed - * @throws \think\Exception - */ - public function _empty($method, $args) - { - if (method_exists($this, $method . '_' . $this->_method . '_' . $this->_type)) { - // RESTFul方法支持 - $fun = $method . '_' . $this->_method . '_' . $this->_type; - } elseif ($this->_method == $this->restDefaultMethod && method_exists($this, $method . '_' . $this->_type)) { - $fun = $method . '_' . $this->_type; - } elseif ($this->_type == $this->restDefaultType && method_exists($this, $method . '_' . $this->_method)) { - $fun = $method . '_' . $this->_method; - } - if (isset($fun)) { - return $this->$fun(); - } else { - // 抛出异常 - throw new \Exception('error action :' . ACTION_NAME); - } - } - - /** - * 输出返回数据 - * @access protected - * @param mixed $data 要返回的数据 - * @param String $type 返回类型 JSON XML - * @param integer $code HTTP状态 - * @return void - */ - protected function response($data, $type = '', $code = 200) - { - http_response_code($code); - Response::data($data); - if ($type) { - Response::type($type); - } - } - - /** - * 获取当前请求的Accept头信息 - * @return string - */ - public static function getAcceptType() - { - if (!isset($_SERVER['HTTP_ACCEPT'])) { - return false; - } - - $type = [ - 'html' => 'text/html,application/xhtml+xml,*/*', - 'xml' => 'application/xml,text/xml,application/x-xml', - 'json' => 'application/json,text/x-json,application/jsonrequest,text/json', - 'js' => 'text/javascript,application/javascript,application/x-javascript', - 'css' => 'text/css', - 'rss' => 'application/rss+xml', - 'yaml' => 'application/x-yaml,text/yaml', - 'atom' => 'application/atom+xml', - 'pdf' => 'application/pdf', - 'text' => 'text/plain', - 'png' => 'image/png', - 'jpg' => 'image/jpg,image/jpeg,image/pjpeg', - 'gif' => 'image/gif', - 'csv' => 'text/csv', - ]; - - foreach ($type as $key => $val) { - $array = explode(',', $val); - foreach ($array as $k => $v) { - if (stristr($_SERVER['HTTP_ACCEPT'], $v)) { - return $key; - } - } - } - - return false; - } -} diff --git a/thinkphp/library/think/controller/Rpc.php b/thinkphp/library/think/controller/Rpc.php deleted file mode 100644 index 7e2fe0bd5..000000000 --- a/thinkphp/library/think/controller/Rpc.php +++ /dev/null @@ -1,62 +0,0 @@ - -// +---------------------------------------------------------------------- -namespace think\controller; - -/** - * ThinkPHP RPC控制器类 - */ -abstract class Rpc -{ - - protected $allowMethodList = ''; - protected $debug = false; - - /** - * 架构函数 - * @access public - */ - public function __construct() - { - //控制器初始化 - if (method_exists($this, '_initialize')) { - $this->_initialize(); - } - - //导入类库 - \think\Loader::import('vendor.phprpc.phprpc_server'); - //实例化phprpc - $server = new \PHPRPC_Server(); - if ($this->allowMethodList) { - $methods = $this->allowMethodList; - } else { - $methods = get_class_methods($this); - $methods = array_diff($methods, array('__construct', '__call', '_initialize')); - } - $server->add($methods, $this); - - if (APP_DEBUG || $this->debug) { - $server->setDebugMode(true); - } - $server->setEnableGZIP(true); - $server->start(); - echo $server->comment(); - } - - /** - * 魔术方法 有不存在的操作的时候执行 - * @access public - * @param string $method 方法名 - * @param array $args 参数 - * @return mixed - */ - public function __call($method, $args) - {} -} diff --git a/thinkphp/library/think/controller/Yar.php b/thinkphp/library/think/controller/Yar.php deleted file mode 100644 index 05627c75c..000000000 --- a/thinkphp/library/think/controller/Yar.php +++ /dev/null @@ -1,50 +0,0 @@ - -// +---------------------------------------------------------------------- -namespace think\controller; - -/** - * ThinkPHP Yar控制器类 - */ -abstract class Yar -{ - - /** - * 架构函数 - * @access public - */ - public function __construct() - { - //控制器初始化 - if (method_exists($this, '_initialize')) { - $this->_initialize(); - } - - //判断扩展是否存在 - if (!extension_loaded('yar')) { - throw new Exception('not support yar'); - } - - //实例化Yar_Server - $server = new \Yar_Server($this); - // 启动server - $server->handle(); - } - - /** - * 魔术方法 有不存在的操作的时候执行 - * @access public - * @param string $method 方法名 - * @param array $args 参数 - * @return mixed - */ - public function __call($method, $args) - {} -} diff --git a/thinkphp/library/think/db/Driver.php b/thinkphp/library/think/db/Driver.php deleted file mode 100644 index b23b3fd9c..000000000 --- a/thinkphp/library/think/db/Driver.php +++ /dev/null @@ -1,1282 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\db; - -use PDO; -use think\Config; -use think\Db; -use think\Debug; -use think\Exception; -use think\Log; - -abstract class Driver -{ - // PDO操作实例 - protected $PDOStatement = null; - // 当前操作所属的模型名 - protected $model = '_think_'; - // 当前SQL指令 - protected $queryStr = ''; - protected $modelSql = []; - // 最后插入ID - protected $lastInsID = null; - // 返回或者影响记录数 - protected $numRows = 0; - // 事务指令数 - protected $transTimes = 0; - // 错误信息 - protected $error = ''; - // 数据库连接ID 支持多个连接 - protected $links = []; - // 当前连接ID - protected $linkID = null; - // 数据库连接参数配置 - protected $config = [ - // 数据库类型 - 'type' => '', - // 服务器地址 - 'hostname' => '127.0.0.1', - // 数据库名 - 'database' => '', - // 用户名 - 'username' => '', - // 密码 - 'password' => '', - // 端口 - 'hostport' => '', - 'dsn' => '', - // 数据库连接参数 - 'params' => [], - // 数据库编码默认采用utf8 - 'charset' => 'utf8', - // 数据库表前缀 - 'prefix' => '', - // 数据库调试模式 - 'debug' => false, - // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) - 'deploy' => 0, - // 数据库读写是否分离 主从式有效 - 'rw_separate' => false, - // 读写分离后 主服务器数量 - 'master_num' => 1, - // 指定从服务器序号 - 'slave_no' => '', - // like字段自动替换为%%包裹 - 'db_like_fields' => '', - // 是否开启数据库调试 - 'debug' => false, - ]; - // 数据库表达式 - protected $exp = ['eq' => '=', 'neq' => '<>', 'gt' => '>', 'egt' => '>=', 'lt' => '<', 'elt' => '<=', 'notlike' => 'NOT LIKE', 'like' => 'LIKE', 'in' => 'IN', 'notin' => 'NOT IN', 'not in' => 'NOT IN', 'between' => 'BETWEEN', 'not between' => 'NOT BETWEEN', 'notbetween' => 'NOT BETWEEN']; - // 查询表达式 - protected $selectSql = 'SELECT%DISTINCT% %FIELD% FROM %TABLE%%FORCE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%%LIMIT% %UNION%%LOCK%%COMMENT%'; - - // PDO连接参数 - protected $options = [ - PDO::ATTR_CASE => PDO::CASE_LOWER, - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL, - PDO::ATTR_STRINGIFY_FETCHES => false, - ]; - // 参数绑定 - protected $bind = []; - - /** - * 架构函数 读取数据库配置信息 - * @access public - * @param array $config 数据库配置数组 - */ - public function __construct($config = '') - { - if (!empty($config)) { - $this->config = array_merge($this->config, $config); - if (is_array($this->config['params'])) { - $this->options = $this->config['params'] + $this->options; - } - } - } - - /** - * 连接数据库方法 - * @access public - */ - public function connect($config = '', $linkNum = 0, $autoConnection = false) - { - if (!isset($this->links[$linkNum])) { - if (empty($config)) { - $config = $this->config; - } - - try { - if (empty($config['dsn'])) { - $config['dsn'] = $this->parseDsn($config); - } - $this->links[$linkNum] = new PDO($config['dsn'], $config['username'], $config['password'], $this->options); - // 记录数据库连接信息 - APP_DEBUG && Log::record('[ DB ] CONNECT: ' . $config['dsn'], 'info'); - } catch (\PDOException $e) { - if ($autoConnection) { - Log::record($e->getMessage(), 'error'); - return $this->connect($autoConnection, $linkNum); - } else { - throw new Exception($e->getMessage()); - } - } - } - return $this->links[$linkNum]; - } - - /** - * 解析pdo连接的dsn信息 - * @access public - * @param array $config 连接信息 - * @return string - */ - protected function parseDsn($config) - {} - - /** - * 释放查询结果 - * @access public - */ - public function free() - { - $this->PDOStatement = null; - } - - /** - * 执行查询 返回数据集 - * @access public - * @param string $sql sql指令 - * @param array $bind 参数绑定 - * @param boolean $fetch 不执行只是获取SQL - * @param boolean $master 是否在主服务器读操作 - * @return mixed - */ - public function query($sql, $bind = [], $fetch = false, $master = false) - { - $this->initConnect($master); - if (!$this->linkID) { - return false; - } - - // 根据参数绑定组装最终的SQL语句 - $this->queryStr = $this->getBindSql($sql, $bind); - - if ($fetch) { - return $this->queryStr; - } - //释放前次的查询结果 - if (!empty($this->PDOStatement)) { - $this->free(); - } - - Db::$queryTimes++; - try { - // 调试开始 - $this->debug(true); - // 预处理 - $this->PDOStatement = $this->linkID->prepare($sql); - // 参数绑定 - $this->bindValue($bind); - // 执行查询 - $result = $this->PDOStatement->execute(); - // 调试结束 - $this->debug(false); - return $this->getResult(); - } catch (\PDOException $e) { - throw new Exception($this->getError()); - } - } - - /** - * 执行语句 - * @access public - * @param string $sql sql指令 - * @param array $bind 参数绑定 - * @param boolean $fetch 不执行只是获取SQL - * @return integer - */ - public function execute($sql, $bind = [], $fetch = false) - { - $this->initConnect(true); - if (!$this->linkID) { - return false; - } - - // 根据参数绑定组装最终的SQL语句 - $this->queryStr = $this->getBindSql($sql, $bind); - - if ($fetch) { - return $this->queryStr; - } - //释放前次的查询结果 - if (!empty($this->PDOStatement)) { - $this->free(); - } - - Db::$executeTimes++; - try { - // 调试开始 - $this->debug(true); - // 预处理 - $this->PDOStatement = $this->linkID->prepare($sql); - // 参数绑定操作 - $this->bindValue($bind); - // 执行语句 - $result = $this->PDOStatement->execute(); - // 调试结束 - $this->debug(false); - - $this->numRows = $this->PDOStatement->rowCount(); - if (preg_match("/^\s*(INSERT\s+INTO|REPLACE\s+INTO)\s+/i", $sql)) { - $this->lastInsID = $this->linkID->lastInsertId(); - } - return $this->numRows; - } catch (\PDOException $e) { - throw new Exception($this->getError()); - } - } - - /** - * 组装最终的SQL语句 便于调试 - * @access public - * @param string $sql 带参数绑定的sql语句 - * @param array $bind 参数绑定列表 - * @return string - */ - protected function getBindSql($sql, array $bind = []) - { - if ($bind) { - foreach ($bind as $key => $val) { - $val = $this->parseValue(is_array($val) ? $val[0] : $val); - // 判断占位符 - $sql = is_numeric($key) ? - substr_replace($sql, $val, strpos($sql, '?'), 1) : - str_replace(':' . $key, $val, $sql); - } - } - return $sql; - } - - /** - * 参数绑定 - * 支持 ['name'=>'value','id'=>123] 对应命名占位符 - * 或者 ['value',123] 对应问号占位符 - * @access public - * @param array $bind 要绑定的参数列表 - * @return void - */ - protected function bindValue(array $bind = []) - { - foreach ($bind as $key => $val) { - // 占位符 - $param = is_numeric($key) ? $key + 1 : ':' . $key; - if (is_array($val)) { - $result = $this->PDOStatement->bindValue($param, $val[0], $val[1]); - } else { - $result = $this->PDOStatement->bindValue($param, $val); - } - if (!$result) { - throw new Exception('bind param error : [ ' . $param . '=>' . $val . ' ]'); - } - } - } - - /** - * 启动事务 - * @access public - * @return void - */ - public function startTrans() - { - $this->initConnect(true); - if (!$this->linkID) { - return false; - } - - //数据rollback 支持 - if (0 == $this->transTimes) { - $this->linkID->beginTransaction(); - } - $this->transTimes++; - return; - } - - /** - * 用于非自动提交状态下面的查询提交 - * @access public - * @return boolen - */ - public function commit() - { - if ($this->transTimes > 0) { - try { - $result = $this->linkID->commit(); - $this->transTimes = 0; - } catch (\PDOException $e) { - throw new Exception($e->getMessage()); - } - } - return true; - } - - /** - * 事务回滚 - * @access public - * @return boolen - */ - public function rollback() - { - if ($this->transTimes > 0) { - try { - $result = $this->linkID->rollback(); - $this->transTimes = 0; - } catch (\PDOException $e) { - throw new Exception($e->getMessage()); - } - } - return true; - } - - /** - * 获得所有的查询数据 - * @access private - * @return array - */ - private function getResult() - { - //返回数据集 - $result = $this->PDOStatement->fetchAll(PDO::FETCH_ASSOC); - $this->numRows = count($result); - return $result; - } - - /** - * 获得查询次数 - * @access public - * @param boolean $execute 是否包含所有查询 - * @return integer - */ - public function getQueryTimes($execute = false) - { - return $execute ? Db::$queryTimes + Db::$executeTimes : Db::$queryTimes; - } - - /** - * 获得执行次数 - * @access public - * @return integer - */ - public function getExecuteTimes() - { - return Db::$executeTimes; - } - - /** - * 关闭数据库 - * @access public - */ - public function close() - { - $this->linkID = null; - } - - /** - * 设置锁机制 - * @access protected - * @return string - */ - protected function parseLock($lock = false) - { - return $lock ? ' FOR UPDATE ' : ''; - } - - /** - * set分析 - * @access protected - * @param array $data - * @return string - */ - protected function parseSet($data) - { - foreach ($data as $key => $val) { - if (isset($val[0]) && 'exp' == $val[0]) { - $set[] = $this->parseKey($key) . '=' . $val[1]; - } elseif (is_null($val)) { - $set[] = $this->parseKey($key) . '=NULL'; - } elseif (is_scalar($val)) { - // 过滤非标量数据 - if (0 === strpos($val, ':') && isset($this->bind[substr($val, 1)])) { - $set[] = $this->parseKey($key) . '=' . $val; - } else { - $name = count($this->bind); - $set[] = $this->parseKey($key) . '=:' . $key . $_SERVER['REQUEST_TIME'] . '_' . $name; - $this->bindParam($key . $_SERVER['REQUEST_TIME'] . '_' . $name, $val); - } - } - } - return ' SET ' . implode(',', $set); - } - - /** - * 参数绑定 - * @access protected - * @param string $name 绑定参数名 - * @param mixed $value 绑定值 - * @return void - */ - protected function bindParam($name, $value) - { - $this->bind[$name] = $value; - } - - /** - * 获取参数绑定信息并清空 - * @access protected - * @param bool $reset 获取后清空 - * @return array - */ - protected function getBindParams($reset = false) - { - $bind = $this->bind; - if ($reset) { - $this->bind = []; - } - return $bind; - } - /** - * 字段名分析 - * @access protected - * @param string $key - * @return string - */ - protected function parseKey($key) - { - return $key; - } - - /** - * value分析 - * @access protected - * @param mixed $value - * @return string - */ - protected function parseValue($value) - { - if (is_string($value)) { - $value = strpos($value, ':') === 0 && isset($this->bind[substr($value, 1)]) ? $value : $this->quote($value); - } elseif (isset($value[0]) && is_string($value[0]) && strtolower($value[0]) == 'exp') { - $value = $this->quote($value[1]); - } elseif (is_array($value)) { - $value = array_map([$this, 'parseValue'], $value); - } elseif (is_bool($value)) { - $value = $value ? '1' : '0'; - } elseif (is_null($value)) { - $value = 'null'; - } - return $value; - } - - /** - * field分析 - * @access protected - * @param mixed $fields - * @return string - */ - protected function parseField($fields) - { - if (is_string($fields) && strpos($fields, ',')) { - $fields = explode(',', $fields); - } - if (is_array($fields)) { - // 完善数组方式传字段名的支持 - // 支持 'field1'=>'field2' 这样的字段别名定义 - $array = []; - foreach ($fields as $key => $field) { - if (!is_numeric($key)) { - $array[] = $this->parseKey($key) . ' AS ' . $this->parseKey($field); - } else { - $array[] = $this->parseKey($field); - } - } - $fieldsStr = implode(',', $array); - } elseif (is_string($fields) && !empty($fields)) { - $fieldsStr = $this->parseKey($fields); - } else { - $fieldsStr = '*'; - } - //TODO 如果是查询全部字段,并且是join的方式,那么就把要查的表加个别名,以免字段被覆盖 - return $fieldsStr; - } - - /** - * table分析 - * @access protected - * @param mixed $table - * @return string - */ - protected function parseTable($tables) - { - if (is_array($tables)) { - // 支持别名定义 - $array = []; - foreach ($tables as $table => $alias) { - if (!is_numeric($table)) { - $array[] = $this->parseKey($table) . ' ' . $this->parseKey($alias); - } else { - $array[] = $this->parseKey($alias); - } - } - $tables = $array; - } elseif (is_string($tables)) { - $tables = array_map([$this, 'parseKey'], explode(',', $tables)); - } - return implode(',', $tables); - } - - /** - * where分析 - * @access protected - * @param mixed $where - * @return string - */ - protected function parseWhere($where) - { - $whereStr = ''; - if (is_string($where)) { - // 直接使用字符串条件 - $whereStr = $where; - } else { - // 使用数组表达式 - $operate = isset($where['_logic']) ? strtoupper($where['_logic']) : ''; - if (in_array($operate, ['AND', 'OR', 'XOR'])) { - // 定义逻辑运算规则 例如 OR XOR AND NOT - $operate = ' ' . $operate . ' '; - unset($where['_logic']); - } else { - // 默认进行 AND 运算 - $operate = ' AND '; - } - foreach ($where as $key => $val) { - if (is_numeric($key)) { - $key = '_complex'; - } - if (0 === strpos($key, '_')) { - // 解析特殊条件表达式 - $whereStr .= $this->parseThinkWhere($key, $val); - } else { - // 多条件支持 - $multi = is_array($val) && isset($val['_multi']); - $key = trim($key); - if (strpos($key, '|')) { - // 支持 name|title|nickname 方式定义查询字段 - $array = explode('|', $key); - $str = []; - foreach ($array as $m => $k) { - $v = $multi ? $val[$m] : $val; - $str[] = $this->parseWhereItem($this->parseKey($k), $v); - } - $whereStr .= '( ' . implode(' OR ', $str) . ' )'; - } elseif (strpos($key, '&')) { - $array = explode('&', $key); - $str = []; - foreach ($array as $m => $k) { - $v = $multi ? $val[$m] : $val; - $str[] = '(' . $this->parseWhereItem($this->parseKey($k), $v) . ')'; - } - $whereStr .= '( ' . implode(' AND ', $str) . ' )'; - } else { - $whereStr .= $this->parseWhereItem($this->parseKey($key), $val); - } - } - $whereStr .= $operate; - } - $whereStr = substr($whereStr, 0, -strlen($operate)); - } - return empty($whereStr) ? '' : ' WHERE ' . $whereStr; - } - - // where子单元分析 - protected function parseWhereItem($key, $val) - { - $whereStr = ''; - if (is_array($val)) { - if (is_string($val[0])) { - $exp = strtolower($val[0]); - if (preg_match('/^(eq|neq|gt|egt|lt|elt)$/', $exp)) { - // 比较运算 - $whereStr .= $key . ' ' . $this->exp[$exp] . ' ' . $this->parseValue($val[1]); - } elseif (preg_match('/^(notlike|like)$/', $exp)) { - // 模糊查找 - if (is_array($val[1])) { - $likeLogic = isset($val[2]) ? strtoupper($val[2]) : 'OR'; - if (in_array($likeLogic, ['AND', 'OR', 'XOR'])) { - $like = []; - foreach ($val[1] as $item) { - $like[] = $key . ' ' . $this->exp[$exp] . ' ' . $this->parseValue($item); - } - $whereStr .= '(' . implode(' ' . $likeLogic . ' ', $like) . ')'; - } - } else { - $whereStr .= $key . ' ' . $this->exp[$exp] . ' ' . $this->parseValue($val[1]); - } - } elseif ('exp' == $exp) { - // 使用表达式 - $whereStr .= $key . ' ' . $val[1]; - } elseif (preg_match('/^(notin|not in|in)$/', $exp)) { - // IN 运算 - if (isset($val[2]) && 'exp' == $val[2]) { - $whereStr .= $key . ' ' . $this->exp[$exp] . ' ' . $val[1]; - } else { - if (is_string($val[1])) { - $val[1] = explode(',', $val[1]); - } - $zone = implode(',', $this->parseValue($val[1])); - $whereStr .= $key . ' ' . $this->exp[$exp] . ' (' . $zone . ')'; - } - } elseif (preg_match('/^(notbetween|not between|between)$/', $exp)) { - // BETWEEN运算 - $data = is_string($val[1]) ? explode(',', $val[1]) : $val[1]; - $whereStr .= $key . ' ' . $this->exp[$exp] . ' ' . $this->parseValue($data[0]) . ' AND ' . $this->parseValue($data[1]); - } else { - throw new Exception('where express error:' . $val[0]); - } - } else { - $count = count($val); - $rule = isset($val[$count - 1]) ? (is_array($val[$count - 1]) ? strtoupper($val[$count - 1][0]) : strtoupper($val[$count - 1])) : ''; - if (in_array($rule, ['AND', 'OR', 'XOR'])) { - $count = $count - 1; - } else { - $rule = 'AND'; - } - for ($i = 0; $i < $count; $i++) { - $data = is_array($val[$i]) ? $val[$i][1] : $val[$i]; - if ('exp' == strtolower($val[$i][0])) { - $whereStr .= $key . ' ' . $data . ' ' . $rule . ' '; - } else { - $whereStr .= $this->parseWhereItem($key, $val[$i]) . ' ' . $rule . ' '; - } - } - $whereStr = '( ' . substr($whereStr, 0, -4) . ' )'; - } - } else { - //对字符串类型字段采用模糊匹配 - $likeFields = $this->config['db_like_fields']; - if ($likeFields && preg_match('/^(' . $likeFields . ')$/i', $key)) { - $whereStr .= $key . ' LIKE ' . $this->parseValue('%' . $val . '%'); - } else { - $whereStr .= $key . ' = ' . $this->parseValue($val); - } - } - return $whereStr; - } - - /** - * 特殊条件分析 - * @access protected - * @param string $key - * @param mixed $val - * @return string - */ - protected function parseThinkWhere($key, $val) - { - $whereStr = ''; - switch ($key) { - case '_string': - // 字符串模式查询条件 - $whereStr = $val; - break; - case '_complex': - // 复合查询条件 - $whereStr = substr($this->parseWhere($val), 6); - break; - case '_query': - // 字符串模式查询条件 - parse_str($val, $where); - if (isset($where['_logic'])) { - $op = ' ' . strtoupper($where['_logic']) . ' '; - unset($where['_logic']); - } else { - $op = ' AND '; - } - $array = []; - foreach ($where as $field => $data) { - $array[] = $this->parseKey($field) . ' = ' . $this->parseValue($data); - } - - $whereStr = implode($op, $array); - break; - } - return $whereStr; - } - - /** - * limit分析 - * @access protected - * @param mixed $lmit - * @return string - */ - protected function parseLimit($limit) - { - return (!empty($limit) && false === strpos($limit, '(')) ? ' LIMIT ' . $limit . ' ' : ''; - } - - /** - * join分析 - * @access protected - * @param mixed $join - * @return string - */ - protected function parseJoin($join) - { - $joinStr = ''; - if (!empty($join)) { - $joinStr = ' ' . implode(' ', $join) . ' '; - } - return $joinStr; - } - - /** - * order分析 - * @access protected - * @param mixed $order - * @return string - */ - protected function parseOrder($order) - { - if (is_array($order)) { - $array = []; - foreach ($order as $key => $val) { - if (is_numeric($key)) { - if (false === strpos($val, '(')) { - $array[] = $this->parseKey($val); - } elseif ('[rand]' == $val) { - $array[] = $this->parseRand(); - } - } else { - $sort = in_array(strtolower(trim($val)), ['asc', 'desc']) ? ' ' . $val : ''; - $array[] = $this->parseKey($key) . ' ' . $sort; - } - } - $order = implode(',', $array); - } - return !empty($order) ? ' ORDER BY ' . $order : ''; - } - - /** - * group分析 - * @access protected - * @param mixed $group - * @return string - */ - protected function parseGroup($group) - { - return !empty($group) ? ' GROUP BY ' . $group : ''; - } - - /** - * having分析 - * @access protected - * @param string $having - * @return string - */ - protected function parseHaving($having) - { - return !empty($having) ? ' HAVING ' . $having : ''; - } - - /** - * comment分析 - * @access protected - * @param string $comment - * @return string - */ - protected function parseComment($comment) - { - return !empty($comment) ? ' /* ' . $comment . ' */' : ''; - } - - /** - * distinct分析 - * @access protected - * @param mixed $distinct - * @return string - */ - protected function parseDistinct($distinct) - { - return !empty($distinct) ? ' DISTINCT ' : ''; - } - - /** - * union分析 - * @access protected - * @param mixed $union - * @return string - */ - protected function parseUnion($union) - { - if (empty($union)) { - return ''; - } - - if (isset($union['_all'])) { - $str = 'UNION ALL '; - unset($union['_all']); - } else { - $str = 'UNION '; - } - foreach ($union as $u) { - $sql[] = $str . (is_array($u) ? $this->buildSelectSql($u) : $u); - } - return implode(' ', $sql); - } - - /** - * index分析,可在操作链中指定需要强制使用的索引 - * @access protected - * @param mixed $index - * @return string - */ - protected function parseForce($index) - { - if (empty($index)) { - return ''; - } - - if (is_array($index)) { - $index = join(",", $index); - } - - return sprintf(" FORCE INDEX ( %s ) ", $index); - } - - /** - * ON DUPLICATE KEY UPDATE 分析 - * @access protected - * @param mixed $duplicate - * @return string - */ - protected function parseDuplicate($duplicate) - { - return ''; - } - - /** - * 插入记录 - * @access public - * @param mixed $data 数据 - * @param array $options 参数表达式 - * @param boolean $replace 是否replace - * @return false | integer - */ - public function insert($data, $options = [], $replace = false) - { - $values = $fields = []; - $this->model = $options['model']; - $this->bind = array_merge($this->bind, !empty($options['bind']) ? $options['bind'] : []); - - foreach ($data as $key => $val) { - if (isset($val[0]) && 'exp' == $val[0]) { - $fields[] = $this->parseKey($key); - $values[] = $val[1]; - } elseif (is_null($val)) { - $fields[] = $this->parseKey($key); - $values[] = 'NULL'; - } elseif (is_scalar($val)) { - // 过滤非标量数据 - $fields[] = $this->parseKey($key); - if (0 === strpos($val, ':') && isset($this->bind[substr($val, 1)])) { - $values[] = $val; - } else { - $name = count($this->bind); - $values[] = ':' . $key . $_SERVER['REQUEST_TIME'] . '_' . $name; - $this->bindParam($key . $_SERVER['REQUEST_TIME'] . '_' . $name, $val); - } - } - } - // 兼容数字传入方式 - $replace = (is_numeric($replace) && $replace > 0) ? true : $replace; - $sql = (true === $replace ? 'REPLACE' : 'INSERT') . ' INTO ' . $this->parseTable($options['table']) . ' (' . implode(',', $fields) . ') VALUES (' . implode(',', $values) . ')' . $this->parseDuplicate($replace); - $sql .= $this->parseComment(!empty($options['comment']) ? $options['comment'] : ''); - return $this->execute($sql, $this->getBindParams(true), !empty($options['fetch_sql']) ? true : false); - } - - /** - * 批量插入记录 - * @access public - * @param mixed $dataSet 数据集 - * @param array $options 参数表达式 - * @param boolean $replace 是否replace - * @return false | integer - */ - public function insertAll($dataSet, $options = [], $replace = false) - { - $values = []; - $this->model = $options['model']; - if (!is_array($dataSet[0])) { - return false; - } - $this->bind = array_merge($this->bind, !empty($options['bind']) ? $options['bind'] : []); - $fields = array_map([$this, 'parseKey'], array_keys($dataSet[0])); - foreach ($dataSet as $data) { - $value = []; - foreach ($data as $key => $val) { - if (is_array($val) && 'exp' == $val[0]) { - $value[] = $val[1]; - } elseif (is_null($val)) { - $value[] = 'NULL'; - } elseif (is_scalar($val)) { - if (0 === strpos($val, ':') && isset($this->bind[substr($val, 1)])) { - $value[] = $val; - } else { - $name = count($this->bind); - $value[] = ':' . $key . $_SERVER['REQUEST_TIME'] . '_' . $name; - $this->bindParam($key . $_SERVER['REQUEST_TIME'] . '_' . $name, $val); - } - } - } - $values[] = 'SELECT ' . implode(',', $value); - } - $sql = 'INSERT INTO ' . $this->parseTable($options['table']) . ' (' . implode(',', $fields) . ') ' . implode(' UNION ALL ', $values); - $sql .= $this->parseComment(!empty($options['comment']) ? $options['comment'] : ''); - return $this->execute($sql, $this->getBindParams(true), !empty($options['fetch_sql']) ? true : false); - } - - /** - * 通过Select方式插入记录 - * @access public - * @param string $fields 要插入的数据表字段名 - * @param string $table 要插入的数据表名 - * @param array $option 查询数据参数 - * @return false | integer - */ - public function selectInsert($fields, $table, $options = []) - { - $this->model = $options['model']; - $this->bind = array_merge($this->bind, !empty($options['bind']) ? $options['bind'] : []); - if (is_string($fields)) { - $fields = explode(',', $fields); - } - - $fields = array_map([$this, 'parseKey'], $fields); - $sql = 'INSERT INTO ' . $this->parseTable($table) . ' (' . implode(',', $fields) . ') '; - $sql .= $this->buildSelectSql($options); - return $this->execute($sql, $this->getBindParams(true), !empty($options['fetch_sql']) ? true : false); - } - - /** - * 更新记录 - * @access public - * @param mixed $data 数据 - * @param array $options 表达式 - * @return false | integer - */ - public function update($data, $options) - { - $this->model = $options['model']; - $this->bind = array_merge($this->bind, !empty($options['bind']) ? $options['bind'] : []); - $table = $this->parseTable($options['table']); - $sql = 'UPDATE ' . $table . $this->parseSet($data); - if (strpos($table, ',')) { - // 多表更新支持JOIN操作 - $sql .= $this->parseJoin(!empty($options['join']) ? $options['join'] : ''); - } - $sql .= $this->parseWhere(!empty($options['where']) ? $options['where'] : ''); - if (!strpos($table, ',')) { - // 单表更新支持order和lmit - $sql .= $this->parseOrder(!empty($options['order']) ? $options['order'] : '') - . $this->parseLimit(!empty($options['limit']) ? $options['limit'] : ''); - } - $sql .= $this->parseComment(!empty($options['comment']) ? $options['comment'] : ''); - return $this->execute($sql, $this->getBindParams(true), !empty($options['fetch_sql']) ? true : false); - } - - /** - * 删除记录 - * @access public - * @param array $options 表达式 - * @return false | integer - */ - public function delete($options = []) - { - $this->model = $options['model']; - $this->bind = array_merge($this->bind, !empty($options['bind']) ? $options['bind'] : []); - $table = $this->parseTable($options['table']); - $sql = 'DELETE FROM ' . $table; - if (strpos($table, ',')) { - // 多表删除支持USING和JOIN操作 - if (!empty($options['using'])) { - $sql .= ' USING ' . $this->parseTable($options['using']) . ' '; - } - $sql .= $this->parseJoin(!empty($options['join']) ? $options['join'] : ''); - } - $sql .= $this->parseWhere(!empty($options['where']) ? $options['where'] : ''); - if (!strpos($table, ',')) { - // 单表删除支持order和limit - $sql .= $this->parseOrder(!empty($options['order']) ? $options['order'] : '') - . $this->parseLimit(!empty($options['limit']) ? $options['limit'] : ''); - } - $sql .= $this->parseComment(!empty($options['comment']) ? $options['comment'] : ''); - return $this->execute($sql, $this->getBindParams(true), !empty($options['fetch_sql']) ? true : false); - } - - /** - * 查找记录 - * @access public - * @param array $options 表达式 - * @return mixed - */ - public function select($options = []) - { - $this->model = $options['model']; - $this->bind = array_merge($this->bind, !empty($options['bind']) ? $options['bind'] : []); - $sql = $this->buildSelectSql($options); - $result = $this->query($sql, $this->getBindParams(true), !empty($options['fetch_sql']) ? true : false, !empty($options['master']) ? true : false); - return $result; - } - - /** - * 生成查询SQL - * @access public - * @param array $options 表达式 - * @return string - */ - public function buildSelectSql($options = []) - { - if (isset($options['page'])) { - // 根据页数计算limit - list($page, $listRows) = $options['page']; - $page = $page > 0 ? $page : 1; - $listRows = $listRows > 0 ? $listRows : (is_numeric($options['limit']) ? $options['limit'] : 20); - $offset = $listRows * ($page - 1); - $options['limit'] = $offset . ',' . $listRows; - } - $sql = $this->parseSql($this->selectSql, $options); - return $sql; - } - - /** - * 替换SQL语句中表达式 - * @access public - * @param array $options 表达式 - * @return string - */ - public function parseSql($sql, $options = []) - { - $sql = str_replace( - ['%TABLE%', '%DISTINCT%', '%FIELD%', '%JOIN%', '%WHERE%', '%GROUP%', '%HAVING%', '%ORDER%', '%LIMIT%', '%UNION%', '%LOCK%', '%COMMENT%', '%FORCE%'], - [ - $this->parseTable($options['table']), - $this->parseDistinct(isset($options['distinct']) ? $options['distinct'] : false), - $this->parseField(!empty($options['field']) ? $options['field'] : '*'), - $this->parseJoin(!empty($options['join']) ? $options['join'] : ''), - $this->parseWhere(!empty($options['where']) ? $options['where'] : ''), - $this->parseGroup(!empty($options['group']) ? $options['group'] : ''), - $this->parseHaving(!empty($options['having']) ? $options['having'] : ''), - $this->parseOrder(!empty($options['order']) ? $options['order'] : ''), - $this->parseLimit(!empty($options['limit']) ? $options['limit'] : ''), - $this->parseUnion(!empty($options['union']) ? $options['union'] : ''), - $this->parseLock(isset($options['lock']) ? $options['lock'] : false), - $this->parseComment(!empty($options['comment']) ? $options['comment'] : ''), - $this->parseForce(!empty($options['force']) ? $options['force'] : ''), - ], $sql); - return $sql; - } - - /** - * 获取最近一次查询的sql语句 - * @param string $model 模型名 - * @access public - * @return string - */ - public function getLastSql($model = '') - { - return $model ? $this->modelSql[$model] : $this->queryStr; - } - - /** - * 获取最近插入的ID - * @access public - * @return string - */ - public function getLastInsID() - { - return $this->lastInsID; - } - - /** - * 获取最近的错误信息 - * @access public - * @return string - */ - public function getError() - { - if ($this->PDOStatement) { - $error = $this->PDOStatement->errorInfo(); - $error = $error[1] . ':' . $error[2]; - } else { - $error = ''; - } - if ('' != $this->queryStr) { - $error .= "\n [ SQL语句 ] : " . $this->queryStr; - } - return $error; - } - - /** - * SQL指令安全过滤 - * @access public - * @param string $str SQL字符串 - * @return string - */ - public function quote($str) - { - $this->initConnect(); - return $this->linkID ? $this->linkID->quote($str) : $str; - } - - /** - * 设置当前操作模型 - * @access public - * @param string $model 模型名 - * @return void - */ - public function setModel($model) - { - $this->model = $model; - } - - /** - * 数据库调试 记录当前SQL - * @access protected - * @param boolean $start 调试开始标记 true 开始 false 结束 - */ - protected function debug($start) - { - if (!empty($this->config['debug'])) { - // 开启数据库调试模式 - if ($start) { - Debug::remark('queryStartTime', 'time'); - } else { - $this->modelSql[$this->model] = $this->queryStr; - // 记录操作结束时间 - Debug::remark('queryEndTime', 'time'); - $log = $this->queryStr . ' [ RunTime:' . Debug::getRangeTime('queryStartTime', 'queryEndTime') . 's ]'; - // SQL性能分析 - if (0 === stripos(trim($this->queryStr), 'select')) { - $pdo = $this->linkID->query("EXPLAIN " . $this->queryStr); - $result = $pdo->fetch(PDO::FETCH_ASSOC); - if (strpos($result['extra'], 'filesort') || strpos($result['extra'], 'temporary')) { - Log::record('SQL:' . $this->queryStr . '[' . $result['extra'] . ']', 'warn'); - } - $log .= '[ EXPLAIN : ' . var_export($result, true) . ' ]'; - } - Log::record('[ SQL ] ' . $log, 'sql'); - } - } - } - - /** - * 初始化数据库连接 - * @access protected - * @param boolean $master 主服务器 - * @return void - */ - protected function initConnect($master = true) - { - if (!empty($this->config['deploy'])) { - // 采用分布式数据库 - $this->linkID = $this->multiConnect($master); - } elseif (!$this->linkID) { - // 默认单数据库 - $this->linkID = $this->connect(); - } - - } - - /** - * 连接分布式服务器 - * @access protected - * @param boolean $master 主服务器 - * @return void - */ - protected function multiConnect($master = false) - { - // 分布式数据库配置解析 - $_config['username'] = explode(',', $this->config['username']); - $_config['password'] = explode(',', $this->config['password']); - $_config['hostname'] = explode(',', $this->config['hostname']); - $_config['hostport'] = explode(',', $this->config['hostport']); - $_config['database'] = explode(',', $this->config['database']); - $_config['dsn'] = explode(',', $this->config['dsn']); - $_config['charset'] = explode(',', $this->config['charset']); - - $m = floor(mt_rand(0, $this->config['master_num'] - 1)); - // 数据库读写是否分离 - if ($this->config['rw_separate']) { - // 主从式采用读写分离 - if ($master) - // 主服务器写入 - { - $r = $m; - } else { - if (is_numeric($this->config['slave_no'])) { - // 指定服务器读 - $r = $this->config['slave_no']; - } else { - // 读操作连接从服务器 - $r = floor(mt_rand($this->config['master_num'], count($_config['hostname']) - 1)); // 每次随机连接的数据库 - } - } - } else { - // 读写操作不区分服务器 - $r = floor(mt_rand(0, count($_config['hostname']) - 1)); // 每次随机连接的数据库 - } - - if ($m != $r) { - $db_master = [ - 'username' => isset($_config['username'][$m]) ? $_config['username'][$m] : $_config['username'][0], - 'password' => isset($_config['password'][$m]) ? $_config['password'][$m] : $_config['password'][0], - 'hostname' => isset($_config['hostname'][$m]) ? $_config['hostname'][$m] : $_config['hostname'][0], - 'hostport' => isset($_config['hostport'][$m]) ? $_config['hostport'][$m] : $_config['hostport'][0], - 'database' => isset($_config['database'][$m]) ? $_config['database'][$m] : $_config['database'][0], - 'dsn' => isset($_config['dsn'][$m]) ? $_config['dsn'][$m] : $_config['dsn'][0], - 'charset' => isset($_config['charset'][$m]) ? $_config['charset'][$m] : $_config['charset'][0], - ]; - } - $db_config = [ - 'username' => isset($_config['username'][$r]) ? $_config['username'][$r] : $_config['username'][0], - 'password' => isset($_config['password'][$r]) ? $_config['password'][$r] : $_config['password'][0], - 'hostname' => isset($_config['hostname'][$r]) ? $_config['hostname'][$r] : $_config['hostname'][0], - 'hostport' => isset($_config['hostport'][$r]) ? $_config['hostport'][$r] : $_config['hostport'][0], - 'database' => isset($_config['database'][$r]) ? $_config['database'][$r] : $_config['database'][0], - 'dsn' => isset($_config['dsn'][$r]) ? $_config['dsn'][$r] : $_config['dsn'][0], - 'charset' => isset($_config['charset'][$r]) ? $_config['charset'][$r] : $_config['charset'][0], - ]; - return $this->connect($db_config, $r, $r == $m ? false : $db_master); - } - - /** - * 析构方法 - * @access public - */ - public function __destruct() - { - // 释放查询 - if ($this->PDOStatement) { - $this->free(); - } - // 关闭连接 - $this->close(); - } -} diff --git a/thinkphp/library/think/db/driver/Mongo.php b/thinkphp/library/think/db/driver/Mongo.php deleted file mode 100644 index 5ecf28bb6..000000000 --- a/thinkphp/library/think/db/driver/Mongo.php +++ /dev/null @@ -1,820 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\db\driver; - -use think\db\Driver; -use think\Exception; -use think\Lang; - -/** - * Mongo数据库驱动 - */ -class Mongo extends Driver -{ - - protected $_mongo = null; // MongoDb Object - protected $_collection = null; // MongoCollection Object - protected $_dbName = ''; // dbName - protected $_collectionName = ''; // collectionName - protected $_cursor = null; // MongoCursor Object - protected $comparison = ['neq' => 'ne', 'ne' => 'ne', 'gt' => 'gt', 'egt' => 'gte', 'gte' => 'gte', 'lt' => 'lt', 'elt' => 'lte', 'lte' => 'lte', 'in' => 'in', 'not in' => 'nin', 'nin' => 'nin']; - - /** - * 架构函数 读取数据库配置信息 - * @access public - * - * @param array|string $config 数据库配置数组 - * - * @throws Exception - */ - public function __construct($config = '') - { - if (!class_exists('mongoClient')) { - throw new Exception(Lang::get('_NOT_SUPPERT_') . ':Mongo'); - } - if (!empty($config)) { - $this->config = array_merge($this->config, $config); - if (empty($this->config['params'])) { - $this->config['params'] = []; - } - } - } - - /** - * 连接数据库方法 - * @access public - * - * @param string $config - * @param int $linkNum - * - * @return - * @throws Exception - */ - public function connect($config = '', $linkNum = 0, $autoConnection = false) - { - if (!isset($this->links[$linkNum])) { - if (empty($config)) { - $config = $this->config; - } - - $host = 'mongodb://' . ($config['username'] ? "{$config['username']}" : '') . ($config['password'] ? ":{$config['password']}@" : '') . $config['hostname'] . ($config['hostport'] ? ":{$config['hostport']}" : '') . '/' . ($config['database'] ? "{$config['database']}" : ''); - try { - $this->links[$linkNum] = new \mongoClient($host, !empty($this->config['params']) ? $this->config['params'] : array()); - } catch (\MongoConnectionException $e) { - throw new Exception($e->getmessage()); - } - } - return $this->links[$linkNum]; - } - - /** - * 切换当前操作的Db和Collection - * @access public - * - * @param string $collection collection - * @param string $db db - * @param boolean $master 是否主服务器 - * - * @throws Exception - */ - public function switchCollection($collection, $db = '', $master = true) - { - // 当前没有连接 则首先进行数据库连接 - if (!$this->linkID) { - $this->initConnect($master); - } - - $db = $db ? $db : $this->config['database']; - - try { - if (!empty($db)) { - // 传人Db则切换数据库 - // 当前MongoDb对象 - $this->_dbName = $db; - $this->_mongo = $this->linkID->selectDb($db); - } - // 当前MongoCollection对象 - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.getCollection(' . $collection . ')'; - } - if ($this->_collectionName != $collection) { - $this->queryTimes++; - $this->debug(true); - $this->_collection = $this->_mongo->selectCollection($collection); - $this->debug(false); - $this->_collectionName = $collection; // 记录当前Collection名称 - } - } catch (\MongoException $e) { - throw new Exception($e->getMessage()); - } - } - - /** - * 释放查询结果 - * @access public - */ - public function free() - { - $this->_cursor = null; - } - - /** - * 执行命令 - * @access public - * @param array $command 指令 - * @return array - */ - public function command($command = []) - { - $this->executeTimes++; - $this->debug(true); - $this->queryStr = 'command:' . json_encode($command); - $result = $this->_mongo->command($command); - $this->debug(false); - if (!$result['ok']) { - throw new Exception($result['errmsg']); - } - return $result; - } - - /** - * 执行语句 - * @access public - * - * @param string $code sql指令 - * @param array $args 参数 - * - * @return mixed - * @throws Exception - */ - public function execute($code, $args = []) - { - $this->executeTimes++; - $this->debug(true); - $this->queryStr = 'execute:' . $code; - $result = $this->_mongo->execute($code, $args); - $this->debug(false); - if ($result['ok']) { - return $result['retval']; - } else { - throw new Exception($result['errmsg']); - } - } - - /** - * 关闭数据库 - * @access public - */ - public function close() - { - if ($this->linkID) { - $this->linkID->close(); - $this->linkID = null; - $this->_mongo = null; - $this->_collection = null; - $this->_cursor = null; - } - } - - /** - * 数据库错误信息 - * @access public - * @return string - */ - public function getError() - { - $error = $this->_mongo->lastError(); - return $error; - } - - /** - * 插入记录 - * @access public - * - * @param mixed $data 数据 - * @param array $options 参数表达式 - * @param boolean $replace 是否replace - * - * @return false|int - * @throws Exception - */ - public function insert($data, $options = [], $replace = false) - { - if (isset($options['table'])) { - $this->switchCollection($options['table']); - } - $this->model = $options['model']; - $this->executeTimes++; - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.' . $this->_collectionName . '.insert('; - $this->queryStr .= $data ? json_encode($data) : '{}'; - $this->queryStr .= ')'; - } - try { - $this->debug(true); - $result = $replace ? $this->_collection->save($data) : $this->_collection->insert($data); - $this->debug(false); - if ($result) { - $_id = $data['_id']; - if (is_object($_id)) { - $_id = $_id->__toString(); - } - $this->lastInsID = $_id; - } - return $result; - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - } - - /** - * 插入多条记录 - * @access public - * - * @param array $dataList 数据 - * @param array $options 参数表达式 - * - * @return bool - * @throws Exception - */ - public function insertAll($dataList, $options = [], $replace = false) - { - if (isset($options['table'])) { - $this->switchCollection($options['table']); - } - $this->model = $options['model']; - $this->executeTimes++; - try { - $this->debug(true); - $result = $this->_collection->batchInsert($dataList); - $this->debug(false); - return $result; - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - } - - /** - * 生成下一条记录ID 用于自增非MongoId主键 - * @access public - * - * @param string $pk 主键名 - * - * @return int - * @throws Exception - */ - public function getMongoNextId($pk) - { - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.' . $this->_collectionName . '.find({},{' . $pk . ':1}).sort({' . $pk . ':-1}).limit(1)'; - } - try { - $this->debug(true); - $result = $this->_collection->find([], [$pk => 1])->sort([$pk => -1])->limit(1); - $this->debug(false); - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - $data = $result->getNext(); - return isset($data[$pk]) ? $data[$pk] + 1 : 1; - } - - /** - * 更新记录 - * @access public - * - * @param mixed $data 数据 - * @param array $options 表达式 - * - * @return bool - * @throws Exception - */ - public function update($data, $options) - { - if (isset($options['table'])) { - $this->switchCollection($options['table']); - } - $this->executeTimes++; - $this->model = $options['model']; - $query = $this->parseWhere($options['where']); - $set = $this->parseSet($data); - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.' . $this->_collectionName . '.update('; - $this->queryStr .= $query ? json_encode($query) : '{}'; - $this->queryStr .= ',' . json_encode($set) . ')'; - } - try { - $this->debug(true); - if (isset($options['limit']) && 1 == $options['limit']) { - $multiple = ["multiple" => false]; - } else { - $multiple = ["multiple" => true]; - } - $result = $this->_collection->update($query, $set, $multiple); - $this->debug(false); - return $result; - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - } - - /** - * 删除记录 - * @access public - * @param array $options 表达式 - * @return false | integer - */ - public function delete($options = []) - { - if (isset($options['table'])) { - $this->switchCollection($options['table']); - } - $query = $this->parseWhere($options['where']); - $this->model = $options['model']; - $this->executeTimes++; - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.' . $this->_collectionName . '.remove(' . json_encode($query) . ')'; - } - try { - $this->debug(true); - $result = $this->_collection->remove($query); - $this->debug(false); - return $result; - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - } - - /** - * 清空记录 - * @access public - * @param array $options 表达式 - * @return false | integer - */ - public function clear($options = []) - { - if (isset($options['table'])) { - $this->switchCollection($options['table']); - } - $this->model = $options['model']; - $this->executeTimes++; - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.' . $this->_collectionName . '.remove({})'; - } - try { - $this->debug(true); - $result = $this->_collection->drop(); - $this->debug(false); - return $result; - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - } - - /** - * 查找记录 - * @access public - * @param array $options 表达式 - * @return iterator - */ - public function select($options = []) - { - if (isset($options['table'])) { - $this->switchCollection($options['table'], '', false); - } - $cache = isset($options['cache']) ? $options['cache'] : false; - if ($cache) { - // 查询缓存检测 - $key = is_string($cache['key']) ? $cache['key'] : md5(serialize($options)); - $value = S($key, '', '', $cache['type']); - if (false !== $value) { - return $value; - } - } - $this->model = $options['model']; - $this->queryTimes++; - $query = $this->parseWhere(!empty($options['where']) ? $options['where'] : array()); - $field = $this->parseField(!empty($options['field']) ? $options['field'] : ''); - try { - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.' . $this->_collectionName . '.find('; - $this->queryStr .= $query ? json_encode($query) : '{}'; - $this->queryStr .= $field ? ',' . json_encode($field) : ''; - $this->queryStr .= ')'; - } - $this->debug(true); - $_cursor = $this->_collection->find($query, $field); - if ($options['order']) { - $order = $this->parseOrder($options['order']); - if ($this->config['debug']) { - $this->queryStr .= '.sort(' . json_encode($order) . ')'; - } - $_cursor = $_cursor->sort($order); - } - if (isset($options['page'])) { - // 根据页数计算limit - if (strpos($options['page'], ',')) { - list($page, $length) = explode(',', $options['page']); - } else { - $page = $options['page']; - } - $page = $page ? $page : 1; - $length = isset($length) ? $length : (is_numeric($options['limit']) ? $options['limit'] : 20); - $offset = $length * ((int) $page - 1); - $options['limit'] = $offset . ',' . $length; - } - if (isset($options['limit'])) { - list($offset, $length) = $this->parseLimit($options['limit']); - if (!empty($offset)) { - if ($this->config['debug']) { - $this->queryStr .= '.skip(' . intval($offset) . ')'; - } - $_cursor = $_cursor->skip(intval($offset)); - } - if ($this->config['debug']) { - $this->queryStr .= '.limit(' . intval($length) . ')'; - } - $_cursor = $_cursor->limit(intval($length)); - } - $this->debug(false); - $this->_cursor = $_cursor; - $resultSet = iterator_to_array($_cursor); - if ($cache && $resultSet) { - // 查询缓存写入 - S($key, $resultSet, $cache['expire'], $cache['type']); - } - return $resultSet; - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - } - - /** - * 查找某个记录 - * @access public - * @param array $options 表达式 - * @return array - */ - public function find($options = []) - { - if (isset($options['table'])) { - $this->switchCollection($options['table'], '', false); - } - $cache = isset($options['cache']) ? $options['cache'] : false; - if ($cache) { - // 查询缓存检测 - $key = is_string($cache['key']) ? $cache['key'] : md5(serialize($options)); - $value = S($key, '', '', $cache['type']); - if (false !== $value) { - return $value; - } - } - $this->model = $options['model']; - $this->queryTimes++; - $query = $this->parseWhere(!empty($options['where']) ? $options['where'] : ''); - $fields = $this->parseField(!empty($options['field']) ? $options['field'] : ''); - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.' . $this->_collectionName . '.findOne('; - $this->queryStr .= $query ? json_encode($query) : '{}'; - $this->queryStr .= $fields ? ',' . json_encode($fields) : ''; - $this->queryStr .= ')'; - } - try { - $this->debug(true); - $result = $this->_collection->findOne($query, $fields); - $this->debug(false); - if ($cache && $result) { - // 查询缓存写入 - S($key, $result, $cache['expire'], $cache['type']); - } - return $result; - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - } - - /** - * 统计记录数 - * @access public - * @param array $options 表达式 - * @return iterator - */ - public function count($options = []) - { - if (isset($options['table'])) { - $this->switchCollection($options['table'], '', false); - } - $this->model = $options['model']; - $this->queryTimes++; - $query = $this->parseWhere($options['where']); - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.' . $this->_collectionName; - $this->queryStr .= $query ? '.find(' . json_encode($query) . ')' : ''; - $this->queryStr .= '.count()'; - } - try { - $this->debug(true); - $count = $this->_collection->count($query); - $this->debug(false); - return $count; - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - } - - public function group($keys, $initial, $reduce, $options = []) - { - $this->_collection->group($keys, $initial, $reduce, $options); - } - - /** - * 取得数据表的字段信息 - * @access public - * @return array - */ - public function getFields($collection = '') - { - if (!empty($collection) && $collection != $this->_collectionName) { - $this->switchCollection($collection, '', false); - } - $this->queryTimes++; - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.' . $this->_collectionName . '.findOne()'; - } - try { - $this->debug(true); - $result = $this->_collection->findOne(); - $this->debug(false); - } catch (\MongoCursorException $e) { - throw new Exception($e->getMessage()); - } - if ($result) { - // 存在数据则分析字段 - $info = []; - foreach ($result as $key => $val) { - $info[$key] = [ - 'name' => $key, - 'type' => getType($val), - ]; - } - return $info; - } - // 暂时没有数据 返回false - return false; - } - - /** - * 取得当前数据库的collection信息 - * @access public - */ - public function getTables() - { - if ($this->config['debug']) { - $this->queryStr = $this->_dbName . '.getCollenctionNames()'; - } - $this->queryTimes++; - $this->debug(true); - $list = $this->_mongo->listCollections(); - $this->debug(false); - $info = []; - foreach ($list as $collection) { - $info[] = $collection->getName(); - } - return $info; - } - - /** - * set分析 - * @access protected - * @param array $data - * @return string - */ - protected function parseSet($data) - { - $result = []; - foreach ($data as $key => $val) { - if (is_array($val)) { - switch ($val[0]) { - case 'inc': - $result['$inc'][$key] = (int) $val[1]; - break; - case 'set': - case 'unset': - case 'push': - case 'pushall': - case 'addtoset': - case 'pop': - case 'pull': - case 'pullall': - $result['$' . $val[0]][$key] = $val[1]; - break; - default: - $result['$set'][$key] = $val; - } - } else { - $result['$set'][$key] = $val; - } - } - return $result; - } - - /** - * order分析 - * @access protected - * @param mixed $order - * @return array - */ - protected function parseOrder($order) - { - if (is_array($order)) { - $order = join(',', $order); - } - if (is_string($order)) { - $array = explode(',', $order); - $order = []; - foreach ($array as $key => $val) { - $arr = explode(' ', trim($val)); - if (isset($arr[1])) { - $arr[1] = 'asc' == $arr[1] ? 1 : -1; - } else { - $arr[1] = 1; - } - $order[$arr[0]] = $arr[1]; - } - } - return $order; - } - - /** - * limit分析 - * @access protected - * @param mixed $limit - * @return array - */ - protected function parseLimit($limit) - { - if (strpos($limit, ',')) { - $array = explode(',', $limit); - } else { - $array = [0, $limit]; - } - return $array; - } - - /** - * field分析 - * @access protected - * @param mixed $fields - * @return array - */ - public function parseField($fields) - { - if (empty($fields)) { - $fields = []; - } - if (is_string($fields)) { - $fields = explode(',', $fields); - } - return $fields; - } - - /** - * where分析 - * @access protected - * @param mixed $where - * @return array - */ - public function parseWhere($where) - { - $query = []; - foreach ((array) $where as $key => $val) { - if ('_id' != $key && 0 === strpos($key, '_')) { - // 解析特殊条件表达式 - $query = $this->parseThinkWhere($key, $val); - } else { - // 查询字段的安全过滤 - if (!preg_match('/^[A-Z_\|\&\-.a-z0-9]+$/', trim($key))) { - throw new Exception(Lang::get('_ERROR_QUERY_') . ':' . $key); - } - $key = trim($key); - if (strpos($key, '|')) { - $array = explode('|', $key); - $str = []; - foreach ($array as $k) { - $str[] = $this->parseWhereItem($k, $val); - } - $query['$or'] = $str; - } elseif (strpos($key, '&')) { - $array = explode('&', $key); - $str = []; - foreach ($array as $k) { - $str[] = $this->parseWhereItem($k, $val); - } - $query = array_merge($query, $str); - } else { - $str = $this->parseWhereItem($key, $val); - $query = array_merge($query, $str); - } - } - } - return $query; - } - - /** - * 特殊条件分析 - * @access protected - * @param string $key - * @param mixed $val - * @return string - */ - protected function parseThinkWhere($key, $val) - { - $query = []; - switch ($key) { - case '_query': // 字符串模式查询条件 - parse_str($val, $query); - if (isset($query['_logic']) && strtolower($query['_logic']) == 'or') { - unset($query['_logic']); - $query['$or'] = $query; - } - break; - case '_string': // MongoCode查询 - $query['$where'] = new \MongoCode($val); - break; - } - return $query; - } - - /** - * where子单元分析 - * @access protected - * @param string $key - * @param mixed $val - * @return array - */ - protected function parseWhereItem($key, $val) - { - $query = []; - if (is_array($val)) { - if (is_string($val[0])) { - $con = strtolower($val[0]); - if (in_array($con, ['neq', 'ne', 'gt', 'egt', 'gte', 'lt', 'lte', 'elt'])) { - // 比较运算 - $k = '$' . $this->comparison[$con]; - $query[$key] = [$k => $val[1]]; - } elseif ('like' == $con) { - // 模糊查询 采用正则方式 - $query[$key] = new \MongoRegex("/" . $val[1] . "/"); - } elseif ('mod' == $con) { - // mod 查询 - $query[$key] = ['$mod' => $val[1]]; - } elseif ('regex' == $con) { - // 正则查询 - $query[$key] = new \MongoRegex($val[1]); - } elseif (in_array($con, ['in', 'nin', 'not in'])) { - // IN NIN 运算 - $data = is_string($val[1]) ? explode(',', $val[1]) : $val[1]; - $k = '$' . $this->comparison[$con]; - $query[$key] = [$k => $data]; - } elseif ('all' == $con) { - // 满足所有指定条件 - $data = is_string($val[1]) ? explode(',', $val[1]) : $val[1]; - $query[$key] = ['$all' => $data]; - } elseif ('between' == $con) { - // BETWEEN运算 - $data = is_string($val[1]) ? explode(',', $val[1]) : $val[1]; - $query[$key] = ['$gte' => $data[0], '$lte' => $data[1]]; - } elseif ('not between' == $con) { - $data = is_string($val[1]) ? explode(',', $val[1]) : $val[1]; - $query[$key] = ['$lt' => $data[0], '$gt' => $data[1]]; - } elseif ('exp' == $con) { - // 表达式查询 - $query['$where'] = new \MongoCode($val[1]); - } elseif ('exists' == $con) { - // 字段是否存在 - $query[$key] = ['$exists' => (bool) $val[1]]; - } elseif ('size' == $con) { - // 限制属性大小 - $query[$key] = ['$size' => intval($val[1])]; - } elseif ('type' == $con) { - // 限制字段类型 1 浮点型 2 字符型 3 对象或者MongoDBRef 5 MongoBinData 7 MongoId 8 布尔型 9 MongoDate 10 NULL 15 MongoCode 16 32位整型 17 MongoTimestamp 18 MongoInt64 如果是数组的话判断元素的类型 - $query[$key] = ['$type' => intval($val[1])]; - } else { - $query[$key] = $val; - } - return $query; - } - } - $query[$key] = $val; - return $query; - } -} diff --git a/thinkphp/library/think/db/driver/Mysql.php b/thinkphp/library/think/db/driver/Mysql.php deleted file mode 100644 index 9bde9fdb7..000000000 --- a/thinkphp/library/think/db/driver/Mysql.php +++ /dev/null @@ -1,116 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\db\driver; - -use think\db\Driver; - -/** - * mysql数据库驱动 - */ -class Mysql extends Driver -{ - - /** - * 解析pdo连接的dsn信息 - * @access public - * @param array $config 连接信息 - * @return string - */ - protected function parseDsn($config) - { - $dsn = 'mysql:dbname=' . $config['database'] . ';host=' . $config['hostname']; - if (!empty($config['hostport'])) { - $dsn .= ';port=' . $config['hostport']; - } elseif (!empty($config['socket'])) { - $dsn .= ';unix_socket=' . $config['socket']; - } - if (!empty($config['charset'])) { - $dsn .= ';charset=' . $config['charset']; - } - return $dsn; - } - - /** - * 取得数据表的字段信息 - * @access public - * @param $tableName - * @return array - */ - public function getFields($tableName) - { - $this->initConnect(true); - list($tableName) = explode(' ', $tableName); - $sql = 'SHOW COLUMNS FROM `' . $tableName . '`'; - $result = $this->query($sql); - $info = []; - if ($result) { - foreach ($result as $key => $val) { - $info[$val['field']] = [ - 'name' => $val['field'], - 'type' => $val['type'], - 'notnull' => (bool) ('' === $val['null']), // not null is empty, null is yes - 'default' => $val['default'], - 'primary' => (strtolower($val['key']) == 'pri'), - 'autoinc' => (strtolower($val['extra']) == 'auto_increment'), - ]; - } - } - return $info; - } - - /** - * 取得数据库的表信息 - * @access public - * @param string $dbName - * @return array - */ - public function getTables($dbName = '') - { - $sql = !empty($dbName) ? 'SHOW TABLES FROM ' . $dbName : 'SHOW TABLES '; - $result = $this->query($sql); - $info = []; - foreach ($result as $key => $val) { - $info[$key] = current($val); - } - return $info; - } - - /** - * 字段和表名处理 - * @access protected - * @param string $key - * @return string - */ - protected function parseKey($key) - { - $key = trim($key); - if (strpos($key, '$.') && false === strpos($key, '(')) { - // JSON字段支持 - list($field, $name) = explode($key, '$.'); - $key = 'jsn_extract(' . $field . ', \'$.\'.' . $name . ')'; - } - if (!preg_match('/[,\'\"\*\(\)`.\s]/', $key)) { - $key = '`' . $key . '`'; - } - return $key; - } - - /** - * 随机排序 - * @access protected - * @return string - */ - protected function parseRand() - { - return 'rand()'; - } -} diff --git a/thinkphp/library/think/db/driver/Oracle.php b/thinkphp/library/think/db/driver/Oracle.php deleted file mode 100644 index dccb815c3..000000000 --- a/thinkphp/library/think/db/driver/Oracle.php +++ /dev/null @@ -1,193 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\db\driver; - -use think\Db; -use think\db\Driver; - -/** - * Oracle数据库驱动 - */ -class Oracle extends Driver -{ - - private $table = ''; - protected $selectSql = 'SELECT * FROM (SELECT thinkphp.*, rownum AS numrow FROM (SELECT %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%) thinkphp ) %LIMIT%%COMMENT%'; - - /** - * 解析pdo连接的dsn信息 - * @access public - * @param array $config 连接信息 - * @return string - */ - protected function parseDsn($config) - { - $dsn = 'oci:dbname=' . $config['database']; - if (!empty($config['charset'])) { - $dsn .= ';charset=' . $config['charset']; - } - return $dsn; - } - - /** - * 执行语句 - * @access public - * @param string $str sql指令 - * @return integer - */ - public function execute($str, $bind = []) - { - $this->initConnect(true); - if (!$this->linkID) { - return false; - } - - $this->queryStr = $str; - if (!empty($bind)) { - $this->queryStr .= '[ ' . print_r($bind, true) . ' ]'; - } - $flag = false; - if (preg_match("/^\s*(INSERT\s+INTO)\s+(\w+)\s+/i", $str, $match)) { - $this->table = C("DB_SEQUENCE_PREFIX") . str_ireplace(C("DB_PREFIX"), "", $match[2]); - $flag = (boolean) $this->query("SELECT * FROM user_sequences WHERE sequence_name='" . strtoupper($this->table) . "'"); - } - //释放前次的查询结果 - if (!empty($this->PDOStatement)) { - $this->free(); - } - - Db::$executeTimes++; - try { - // 记录开始执行时间 - $this->debug(true); - $this->PDOStatement = $this->linkID->prepare($str); - $result = $this->PDOStatement->execute($bind); - $this->debug(false); - $this->numRows = $this->PDOStatement->rowCount(); - if ($flag || preg_match("/^\s*(INSERT\s+INTO|REPLACE\s+INTO)\s+/i", $str)) { - $this->lastInsID = $this->linkID->lastInsertId(); - } - return $this->numRows; - } catch (\PDOException $e) { - throw new Exception($e->getMessage()); - } - } - - /** - * 取得数据表的字段信息 - * @access public - * - * @param $tableName - * - * @return array - */ - public function getFields($tableName) - { - list($tableName) = explode(' ', $tableName); - $result = $this->query("select a.column_name,data_type,decode(nullable,'Y',0,1) notnull,data_default,decode(a.column_name,b.column_name,1,0) pk " - . "from user_tab_columns a,(select column_name from user_constraints c,user_cons_columns col " - . "where c.constraint_name=col.constraint_name and c.constraint_type='P'and c.table_name='" . strtoupper($tableName) - . "') b where table_name='" . strtoupper($tableName) . "' and a.column_name=b.column_name(+)"); - $info = []; - if ($result) { - foreach ($result as $key => $val) { - $info[strtolower($val['column_name'])] = [ - 'name' => strtolower($val['column_name']), - 'type' => strtolower($val['data_type']), - 'notnull' => $val['notnull'], - 'default' => $val['data_default'], - 'primary' => $val['pk'], - 'autoinc' => $val['pk'], - ]; - } - } - return $info; - } - - /** - * 取得数据库的表信息(暂时实现取得用户表信息) - * @access public - * @return array - * @internal param string $dbName - */ - public function getTables() - { - $result = $this->query("select table_name from user_tables"); - $info = []; - foreach ($result as $key => $val) { - $info[$key] = current($val); - } - return $info; - } - - /** - * limit - * @access public - * @return string - */ - public function parseLimit($limit) - { - $limitStr = ''; - if (!empty($limit)) { - $limit = explode(',', $limit); - if (count($limit) > 1) { - $limitStr = "(numrow>" . $limit[0] . ") AND (numrow<=" . ($limit[0] + $limit[1]) . ")"; - } else { - $limitStr = "(numrow>0 AND numrow<=" . $limit[0] . ")"; - } - - } - return $limitStr ? ' WHERE ' . $limitStr : ''; - } - /** - * 设置锁机制 - * @access protected - * @param bool|false $lock - * - * @return string - */ - protected function parseLock($lock = false) - { - if (!$lock) { - return ''; - } - - return ' FOR UPDATE NOWAIT '; - } - - /** - * 字段和表名处理 - * @access protected - * @param string $key - * @return string - */ - protected function parseKey($key) - { - $key = trim($key); - if (strpos($key, '$.') && false === strpos($key, '(')) { - // JSON字段支持 - list($field, $name) = explode($key, '$.'); - $key = $field . '."' . $name . '"'; - } - return $key; - } - - /** - * 随机排序 - * @access protected - * @return string - */ - protected function parseRand() - { - return 'DBMS_RANDOM.value'; - } -} diff --git a/thinkphp/library/think/db/driver/Pgsql.php b/thinkphp/library/think/db/driver/Pgsql.php deleted file mode 100644 index 961eb17a4..000000000 --- a/thinkphp/library/think/db/driver/Pgsql.php +++ /dev/null @@ -1,123 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\db\driver; - -use think\db\Driver; - -/** - * Pgsql数据库驱动 - */ -class Pgsql extends Driver -{ - - /** - * 解析pdo连接的dsn信息 - * @access public - * @param array $config 连接信息 - * @return string - */ - protected function parseDsn($config) - { - $dsn = 'pgsql:dbname=' . $config['database'] . ';host=' . $config['hostname']; - if (!empty($config['hostport'])) { - $dsn .= ';port=' . $config['hostport']; - } - return $dsn; - } - - /** - * 取得数据表的字段信息 - * @access public - * @return array - */ - public function getFields($tableName) - { - list($tableName) = explode(' ', $tableName); - $result = $this->query('select fields_name as "field",fields_type as "type",fields_not_null as "null",fields_key_name as "key",fields_default as "default",fields_default as "extra" from table_msg(' . $tableName . ');'); - $info = []; - if ($result) { - foreach ($result as $key => $val) { - $info[$val['field']] = [ - 'name' => $val['field'], - 'type' => $val['type'], - 'notnull' => (bool) ('' === $val['null']), // not null is empty, null is yes - 'default' => $val['default'], - 'primary' => (strtolower($val['key']) == 'pri'), - 'autoinc' => (strtolower($val['extra']) == 'auto_increment'), - ]; - } - } - return $info; - } - - /** - * 取得数据库的表信息 - * @access public - * @return array - */ - public function getTables($dbName = '') - { - $result = $this->query("select tablename as Tables_in_test from pg_tables where schemaname ='public'"); - $info = []; - foreach ($result as $key => $val) { - $info[$key] = current($val); - } - return $info; - } - - /** - * limit分析 - * @access protected - * @param mixed $lmit - * @return string - */ - public function parseLimit($limit) - { - $limitStr = ''; - if (!empty($limit)) { - $limit = explode(',', $limit); - if (count($limit) > 1) { - $limitStr .= ' LIMIT ' . $limit[1] . ' OFFSET ' . $limit[0] . ' '; - } else { - $limitStr .= ' LIMIT ' . $limit[0] . ' '; - } - } - return $limitStr; - } - - /** - * 字段和表名处理 - * @access protected - * @param string $key - * @return string - */ - protected function parseKey($key) - { - $key = trim($key); - if (strpos($key, '$.') && false === strpos($key, '(')) { - // JSON字段支持 - list($field, $name) = explode($key, '$.'); - $key = $field . '->>\'' . $name . '\''; - } - return $key; - } - - /** - * 随机排序 - * @access protected - * @return string - */ - protected function parseRand() - { - return 'RANDOM()'; - } -} diff --git a/thinkphp/library/think/db/driver/Sqlite.php b/thinkphp/library/think/db/driver/Sqlite.php deleted file mode 100644 index dfb91b539..000000000 --- a/thinkphp/library/think/db/driver/Sqlite.php +++ /dev/null @@ -1,104 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\db\driver; - -use think\db\Driver; - -/** - * Sqlite数据库驱动 - */ -class Sqlite extends Driver -{ - - /** - * 解析pdo连接的dsn信息 - * @access public - * @param array $config 连接信息 - * @return string - */ - protected function parseDsn($config) - { - $dsn = 'sqlite:' . $config['database']; - return $dsn; - } - - /** - * 取得数据表的字段信息 - * @access public - * @return array - */ - public function getFields($tableName) - { - list($tableName) = explode(' ', $tableName); - $result = $this->query('PRAGMA table_info( ' . $tableName . ' )'); - $info = []; - if ($result) { - foreach ($result as $key => $val) { - $info[$val['name']] = [ - 'name' => $val['name'], - 'type' => $val['type'], - 'notnull' => 1 === $val['notnull'], - 'default' => $val['dflt_value'], - 'primary' => '1' == $val['pk'], - 'autoinc' => '1' == $val['pk'], - ]; - } - } - return $info; - } - - /** - * 取得数据库的表信息 - * @access public - * @return array - */ - public function getTables($dbName = '') - { - $result = $this->query("SELECT name FROM sqlite_master WHERE type='table' " - . "UNION ALL SELECT name FROM sqlite_temp_master " - . "WHERE type='table' ORDER BY name"); - $info = []; - foreach ($result as $key => $val) { - $info[$key] = current($val); - } - return $info; - } - - /** - * limit - * @access public - * @return string - */ - public function parseLimit($limit) - { - $limitStr = ''; - if (!empty($limit)) { - $limit = explode(',', $limit); - if (count($limit) > 1) { - $limitStr .= ' LIMIT ' . $limit[1] . ' OFFSET ' . $limit[0] . ' '; - } else { - $limitStr .= ' LIMIT ' . $limit[0] . ' '; - } - } - return $limitStr; - } - - /** - * 随机排序 - * @access protected - * @return string - */ - protected function parseRand() - { - return 'RANDOM()'; - } -} diff --git a/thinkphp/library/think/db/driver/Sqlsrv.php b/thinkphp/library/think/db/driver/Sqlsrv.php deleted file mode 100644 index 470f5dac3..000000000 --- a/thinkphp/library/think/db/driver/Sqlsrv.php +++ /dev/null @@ -1,178 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\db\driver; - -use PDO; -use think\db\Driver; - -/** - * Sqlsrv数据库驱动 - */ -class Sqlsrv extends Driver -{ - protected $selectSql = 'SELECT T1.* FROM (SELECT thinkphp.*, ROW_NUMBER() OVER (%ORDER%) AS ROW_NUMBER FROM (SELECT %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%) AS thinkphp) AS T1 %LIMIT%%COMMENT%'; - // PDO连接参数 - protected $options = [ - PDO::ATTR_CASE => PDO::CASE_LOWER, - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - PDO::ATTR_STRINGIFY_FETCHES => false, - PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8, - ]; - - /** - * 解析pdo连接的dsn信息 - * @access public - * @param array $config 连接信息 - * @return string - */ - protected function parseDsn($config) - { - $dsn = 'sqlsrv:dbname=' . $config['database'] . ';Server=' . $config['hostname']; - if (!empty($config['hostport'])) { - $dsn .= ',' . $config['hostport']; - } - return $dsn; - } - - /** - * 取得数据表的字段信息 - * @access public - * @return array - */ - public function getFields($tableName) - { - list($tableName) = explode(' ', $tableName); - $result = $this->query("SELECT column_name, data_type, column_default, is_nullable - FROM information_schema.tables AS t - JOIN information_schema.columns AS c - ON t.table_catalog = c.table_catalog - AND t.table_schema = c.table_schema - AND t.table_name = c.table_name - WHERE t.table_name = '$tableName'"); - $info = []; - if ($result) { - foreach ($result as $key => $val) { - $info[$val['column_name']] = [ - 'name' => $val['column_name'], - 'type' => $val['data_type'], - 'notnull' => (bool) ('' === $val['is_nullable']), // not null is empty, null is yes - 'default' => $val['column_default'], - 'primary' => false, - 'autoinc' => false, - ]; - } - } - return $info; - } - - /** - * 取得数据表的字段信息 - * @access public - * @return array - */ - public function getTables($dbName = '') - { - $result = $this->query("SELECT TABLE_NAME - FROM INFORMATION_SCHEMA.TABLES - WHERE TABLE_TYPE = 'BASE TABLE' - "); - $info = []; - foreach ($result as $key => $val) { - $info[$key] = current($val); - } - return $info; - } - - /** - * 随机排序 - * @access protected - * @return string - */ - protected function parseRand() - { - return 'rand()'; - } - - /** - * 字段名分析 - * @access protected - * @param string $key - * @return string - */ - protected function parseKey($key) - { - $key = trim($key); - if (!preg_match('/[,\'\"\*\(\)\[.\s]/', $key)) { - $key = '[' . $key . ']'; - } - return $key; - } - - /** - * limit - * @access public - * @param mixed $limit - * @return string - */ - public function parseLimit($limit) - { - if (empty($limit)) { - return ''; - } - - $limit = explode(',', $limit); - if (count($limit) > 1) { - $limitStr = '(T1.ROW_NUMBER BETWEEN ' . $limit[0] . ' + 1 AND ' . $limit[0] . ' + ' . $limit[1] . ')'; - } else { - $limitStr = '(T1.ROW_NUMBER BETWEEN 1 AND ' . $limit[0] . ")"; - } - - return 'WHERE ' . $limitStr; - } - - /** - * 更新记录 - * @access public - * @param mixed $data 数据 - * @param array $options 表达式 - * @return false | integer - */ - public function update($data, $options) - { - $this->model = $options['model']; - $sql = 'UPDATE ' - . $this->parseTable($options['table']) - . $this->parseSet($data) - . $this->parseWhere(!empty($options['where']) ? $options['where'] : '') - . $this->parseLock(isset($options['lock']) ? $options['lock'] : false) - . $this->parseComment(!empty($options['comment']) ? $options['comment'] : ''); - return $this->execute($sql, $this->parseBind(!empty($options['bind']) ? $options['bind'] : [])); - } - - /** - * 删除记录 - * @access public - * @param array $options 表达式 - * @return false | integer - */ - public function delete($options = []) - { - $this->model = $options['model']; - $sql = 'DELETE FROM ' - . $this->parseTable($options['table']) - . $this->parseWhere(!empty($options['where']) ? $options['where'] : '') - . $this->parseLock(isset($options['lock']) ? $options['lock'] : false) - . $this->parseComment(!empty($options['comment']) ? $options['comment'] : ''); - return $this->execute($sql, $this->parseBind(!empty($options['bind']) ? $options['bind'] : [])); - } - -} diff --git a/thinkphp/library/think/log/alarm/Email.php b/thinkphp/library/think/log/alarm/Email.php deleted file mode 100644 index 0cc58332d..000000000 --- a/thinkphp/library/think/log/alarm/Email.php +++ /dev/null @@ -1,40 +0,0 @@ - -// +---------------------------------------------------------------------- -namespace think\log\alarm; - -/** - * 邮件通知驱动 - */ -class Email -{ - - protected $config = [ - 'address' => '', - ]; - - // 实例化并传入参数 - public function __construct($config = []) - { - $this->config = array_merge($this->config, $config); - } - - /** - * 通知发送接口 - * @access public - * @param string $log 日志信息 - * @return void - */ - public function send($msg = '') - { - error_log($msg, 1, $this->config['address']); - } - -} diff --git a/thinkphp/library/think/log/driver/File.php b/thinkphp/library/think/log/driver/File.php deleted file mode 100644 index 6cd01c2db..000000000 --- a/thinkphp/library/think/log/driver/File.php +++ /dev/null @@ -1,74 +0,0 @@ - -// +---------------------------------------------------------------------- -namespace think\log\driver; - -/** - * 本地化调试输出到文件 - */ -class File -{ - - protected $config = [ - 'time_format' => ' c ', - 'file_size' => 2097152, - 'path' => LOG_PATH, - ]; - - // 实例化并传入参数 - public function __construct($config = []) - { - $this->config = array_merge($this->config, $config); - } - - /** - * 日志写入接口 - * @access public - * @param array $log 日志信息 - * @return void - */ - public function save($log = []) - { - $now = date($this->config['time_format']); - $destination = $this->config['path'] . date('y_m_d') . '.log'; - - !is_dir($this->config['path']) && mkdir($this->config['path'], 0755, true); - - //检测日志文件大小,超过配置大小则备份日志文件重新生成 - if (is_file($destination) && floor($this->config['file_size']) <= filesize($destination)) { - rename($destination, dirname($destination) . DS . time() . '-' . basename($destination)); - } - - // 获取基本信息 - if (isset($_SERVER['HTTP_HOST'])) { - $current_uri = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; - } else { - $current_uri = "cmd:" . implode(' ', $_SERVER['argv']); - } - $runtime = number_format(microtime(true) - START_TIME, 6); - $reqs = number_format(1 / $runtime, 2); - $time_str = " [运行时间:{$runtime}s] [吞吐率:{$reqs}req/s]"; - $memory_use = number_format((memory_get_usage() - START_MEM) / 1024, 2); - $memory_str = " [内存消耗:{$memory_use}kb]"; - $file_load = " [文件加载:" . count(get_included_files()) . "]"; - - array_unshift($log, [ - 'type' => 'log', - 'msg' => $current_uri . $time_str . $memory_str . $file_load, - ]); - - $info = ''; - foreach ($log as $line) { - $info .= '[' . $line['type'] . '] ' . $line['msg'] . "\r\n"; - } - error_log("[{$now}] {$_SERVER['SERVER_ADDR']} {$_SERVER['REMOTE_ADDR']} {$_SERVER['REQUEST_URI']}\r\n{$info}\r\n", 3, $destination); - } - -} diff --git a/thinkphp/library/think/log/driver/Sae.php b/thinkphp/library/think/log/driver/Sae.php deleted file mode 100644 index 79b278fab..000000000 --- a/thinkphp/library/think/log/driver/Sae.php +++ /dev/null @@ -1,79 +0,0 @@ - -// +---------------------------------------------------------------------- -namespace think\log\driver; - -/** - * 调试输出到SAE - */ -class Sae -{ - protected $config = [ - 'log_time_format' => ' c ', - ]; - - // 实例化并传入参数 - public function __construct($config = []) - { - $this->config = array_merge($this->config, $config); - } - - /** - * 日志写入接口 - * @access public - * @param array $log 日志信息 - * @return void - */ - public function save($log = []) - { - static $is_debug = null; - $now = date($this->config['log_time_format']); - // 获取基本信息 - if (isset($_SERVER['HTTP_HOST'])) { - $current_uri = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; - } else { - $current_uri = "cmd:" . implode(' ', $_SERVER['argv']); - } - $runtime = number_format(microtime(true) - START_TIME, 6); - $reqs = number_format(1 / $runtime, 2); - $time_str = " [运行时间:{$runtime}s] [吞吐率:{$reqs}req/s]"; - $memory_use = number_format((memory_get_usage() - START_MEM) / 1024, 2); - $memory_str = " [内存消耗:{$memory_use}kb]"; - $file_load = " [文件加载:" . count(get_included_files()) . "]"; - - array_unshift($log, [ - 'type' => 'log', - 'msg' => $current_uri . $time_str . $memory_str . $file_load, - ]); - - $info = ''; - foreach ($log as $line) { - $info .= '[' . $line['type'] . '] ' . $line['msg'] . "\r\n"; - } - - $logstr = "[{$now}] {$_SERVER['SERVER_ADDR']} {$_SERVER['REMOTE_ADDR']} {$_SERVER['REQUEST_URI']}\r\n{$info}\r\n"; - if (is_null($is_debug)) { - $appSettings=[]; - preg_replace_callback('@(\w+)\=([^;]*)@', function($match)use(&$appSettings){ - $appSettings[$match['1']]=$match['2']; - }, $_SERVER['HTTP_APPCOOKIE']); - $is_debug = in_array($_SERVER['HTTP_APPVERSION'], explode(',', $appSettings['debug'])) ? true : false; - } - if ($is_debug) { - sae_set_display_errors(false); //记录日志不将日志打印出来 - } - sae_debug($logstr); - if ($is_debug) { - sae_set_display_errors(true); - } - - } - -} diff --git a/thinkphp/library/think/log/driver/Socket.php b/thinkphp/library/think/log/driver/Socket.php deleted file mode 100644 index 807fa7bd8..000000000 --- a/thinkphp/library/think/log/driver/Socket.php +++ /dev/null @@ -1,218 +0,0 @@ - - */ -namespace think\log\driver; - -class Socket -{ - public $port = 1116; //SocketLog 服务的http的端口号 - - protected $config = [ - 'enable' => true, //是否记录日志的开关 - 'host' => 'localhost', - //是否显示利于优化的参数,如果允许时间,消耗内存等 - 'optimize' => false, - 'show_included_files' => false, - 'error_handler' => false, - //日志强制记录到配置的client_id - 'force_client_ids' => [], - //限制允许读取日志的client_id - 'allow_client_ids' => [], - ]; - - protected $css = [ - 'sql' => 'color:#009bb4;', - 'sql_warn' => 'color:#009bb4;font-size:14px;', - 'error_handler' => 'color:#f4006b;font-size:14px;', - 'page' => 'color:#40e2ff;background:#171717;', - 'big' => 'font-size:20px;color:red;', - ]; - - protected $_allowForceClientIds = []; //配置强制推送且被授权的client_id - - /** - * 架构函数 - * @param array $options 缓存参数 - * @access public - */ - public function __construct($config = []) - { - if (!empty($config)) { - $this->config = array_merge($this->config, $config); - } - if (isset($this->config['allow_client_id'])) { - //兼容旧配置 - $this->allow_client_ids = array_merge($this->allow_client_ids, [$this->config['allow_client_id']]); - } - } - - public function save($logs = []) - { - if (!$this->check()) { - return; - } - $runtime = number_format(microtime(true) - START_TIME, 6); - $reqs = number_format(1 / $runtime, 2); - $time_str = " [运行时间:{$runtime}s][吞吐率:{$reqs}req/s]"; - $memory_use = number_format((memory_get_usage() - START_MEM) / 1024, 2); - $memory_str = " [内存消耗:{$memory_use}kb]"; - $file_load = " [文件加载:" . count(get_included_files()) . "]"; - - if (isset($_SERVER['HTTP_HOST'])) { - $current_uri = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; - } else { - $current_uri = "cmd:" . implode(' ', $_SERVER['argv']); - } - array_unshift($logs, [ - 'type' => 'group', - 'msg' => $current_uri . $time_str . $memory_str . $file_load, - 'css' => $this->css['page'], - ]); - - $logs[] = [ - 'type' => 'groupCollapsed', - 'msg' => 'included_files', - 'css' => '', - ]; - $logs[] = [ - 'type' => 'log', - 'msg' => implode("\n", get_included_files()), - 'css' => '', - ]; - $logs[] = [ - 'type' => 'groupEnd', - 'msg' => '', - 'css' => '', - ]; - - $logs[] = [ - 'type' => 'groupEnd', - 'msg' => '', - 'css' => '', - ]; - - foreach ($logs as &$log) { - if (in_array($log['type'], ['sql', 'notic', 'debug', 'info'])) { - $log['type'] = 'log'; - } - } - $tabid = $this->getClientArg('tabid'); - if (!$client_id = $this->getClientArg('client_id')) { - $client_id = ''; - } - - if (!empty($this->_allowForceClientIds)) { - //强制推送到多个client_id - foreach ($this->_allowForceClientIds as $force_client_id) { - $client_id = $force_client_id; - $this->sendToClient($tabid, $client_id, $logs, $force_client_id); - } - } else { - $this->sendToClient($tabid, $client_id, $logs, ''); - } - - } - - /** - * 发送给指定客户端 - * @author Zjmainstay - * @param $tabid - * @param $client_id - * @param $logs - * @param $force_client_id - */ - protected function sendToClient($tabid, $client_id, $logs, $force_client_id) - { - $logs = array( - 'tabid' => $tabid, - 'client_id' => $client_id, - 'logs' => $logs, - 'force_client_id' => $force_client_id, - ); - $msg = @json_encode($logs); - $address = '/' . $client_id; //将client_id作为地址, server端通过地址判断将日志发布给谁 - $this->send($this->config['host'], $msg, $address); - } - - protected function check() - { - if (!$this->config['enable']) { - return false; - } - $tabid = $this->getClientArg('tabid'); - //是否记录日志的检查 - if (!$tabid && !$this->config['force_client_ids']) { - return false; - } - //用户认证 - $allow_client_ids = $this->config['allow_client_ids']; - if (!empty($allow_client_ids)) { - //通过数组交集得出授权强制推送的client_id - $this->_allowForceClientIds = array_intersect($allow_client_ids, $this->config['force_client_ids']); - if (!$tabid && count($this->_allowForceClientIds)) { - return true; - } - - $client_id = $this->getClientArg('client_id'); - if (!in_array($client_id, $allow_client_ids)) { - return false; - } - } else { - $this->_allowForceClientIds = $this->config['force_client_ids']; - } - return true; - } - - protected function getClientArg($name) - { - static $args = []; - - $key = 'HTTP_USER_AGENT'; - - if (isset($_SERVER['HTTP_SOCKETLOG'])) { - $key = 'HTTP_SOCKETLOG'; - } - - if (!isset($_SERVER[$key])) { - return null; - } - if (empty($args)) { - if (!preg_match('/SocketLog\((.*?)\)/', $_SERVER[$key], $match)) { - $args = ['tabid' => null]; - return null; - } - parse_str($match[1], $args); - } - if (isset($args[$name])) { - return $args[$name]; - } - return null; - } - - /** - * @param null $host - $host of socket server - * @param string $message - 发送的消息 - * @param string $address - 地址 - * @return bool - */ - protected function send($host, $message = '', $address = '/') - { - $url = 'http://' . $host . ':' . $this->port . $address; - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_POST, true); - curl_setopt($ch, CURLOPT_POSTFIELDS, $message); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 1); - curl_setopt($ch, CURLOPT_TIMEOUT, 10); - $headers = [ - "Content-Type: application/json;charset=UTF-8", - ]; - curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); //设置header - $txt = curl_exec($ch); - return true; - } - -} diff --git a/thinkphp/library/think/log/driver/Trace.php b/thinkphp/library/think/log/driver/Trace.php deleted file mode 100644 index c33010bf5..000000000 --- a/thinkphp/library/think/log/driver/Trace.php +++ /dev/null @@ -1,96 +0,0 @@ - -// +---------------------------------------------------------------------- -namespace think\log\driver; - -/** - * 页面Trace调试 需要设置 'response_exit' => false 才能生效 - */ -class Trace -{ - protected $tabs = ['base' => '基本', 'file' => '文件', 'info' => '流程', 'notic|error' => '错误', 'sql' => 'SQL', 'debug|log' => '调试']; - protected $config = [ - 'trace_file' => '', - ]; - - // 实例化并传入参数 - public function __construct($config = []) - { - $this->config['trace_file'] = THINK_PATH . 'tpl/page_trace.tpl'; - $this->config = array_merge($this->config, $config); - } - - /** - * 日志写入接口 - * @access public - * @param array $log 日志信息 - * @return void - */ - public function save($log = []) - { - if (IS_AJAX || IS_CLI || IS_API) { - // ajax cli api方式下不输出 - return; - } - // 获取基本信息 - $runtime = number_format(microtime(true) - START_TIME, 6); - $reqs = number_format(1 / $runtime, 2); - $mem = number_format((memory_get_usage() - START_MEM) / 1024, 2); - - // 页面Trace信息 - $base = [ - '请求信息' => date('Y-m-d H:i:s', $_SERVER['REQUEST_TIME']) . ' ' . $_SERVER['SERVER_PROTOCOL'] . ' ' . $_SERVER['REQUEST_METHOD'] . ' : ' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], - '运行时间' => "{$runtime}s [ 吞吐率:{$reqs}req/s ] 内存消耗:{$mem}kb 文件加载:" . count(get_included_files()), - '查询信息' => \think\Db::$queryTimes . ' queries ' . \think\Db::$executeTimes . ' writes ', - '缓存信息' => \think\Cache::$readTimes . ' reads,' . \think\Cache::$writeTimes . ' writes', - '配置加载' => count(\think\Config::get()), - '会话信息' => 'SESSION_ID=' . session_id(), - ]; - - $info = \think\Debug::getFile(true); - - // 获取调试日志 - $debug = []; - foreach ($log as $line) { - $debug[$line['type']][] = $line['msg']; - } - - // 页面Trace信息 - $trace = []; - foreach ($this->tabs as $name => $title) { - $name = strtolower($name); - switch ($name) { - case 'base': // 基本信息 - $trace[$title] = $base; - break; - case 'file': // 文件信息 - $trace[$title] = $info; - break; - default: // 调试信息 - if (strpos($name, '|')) { - // 多组信息 - $names = explode('|', $name); - $result = []; - foreach ($names as $name) { - $result = array_merge($result, isset($debug[$name]) ? $debug[$name] : []); - } - $trace[$title] = $result; - } else { - $trace[$title] = isset($debug[$name]) ? $debug[$name] : ''; - } - } - } - // 调用Trace页面模板 - ob_start(); - include $this->config['trace_file']; - echo ob_get_clean(); - } - -} diff --git a/thinkphp/library/think/model/Mongo.php b/thinkphp/library/think/model/Mongo.php deleted file mode 100644 index ae7982761..000000000 --- a/thinkphp/library/think/model/Mongo.php +++ /dev/null @@ -1,311 +0,0 @@ - -// +---------------------------------------------------------------------- -namespace think\model; - -use think\Lang; -use think\Loader; - -T('modle/Adv'); - -/** - * MongoModel模型类 - * 实现了ODM和ActiveRecords模式 - */ -class Mongo extends \think\Model -{ - use \traits\model\Adv; - - // 主键类型 - const TYPE_OBJECT = 1; - const TYPE_INT = 2; - const TYPE_STRING = 3; - - // 主键名称 - protected $pk = '_id'; - // _id 类型 1 Object 采用MongoId对象 2 Int 整形 支持自动增长 3 String 字符串Hash - protected $_idType = self::TYPE_OBJECT; - // 主键是否自动增长 支持Int型主键 - protected $_autoInc = false; - // Mongo默认关闭字段检测 可以动态追加字段 - protected $autoCheckFields = false; - - /** - * 利用__call方法实现一些特殊的Model方法 - * @access public - * - * @param string $method 方法名称 - * @param array $args 调用参数 - * - * @return mixed - * @throws \think\Exception - */ - public function __call($method, $args) - { - if (strtolower(substr($method, 0, 5)) == 'getby') { - // 根据某个字段获取记录 - $field = Loader::parseName(substr($method, 5)); - $where[$field] = $args[0]; - return $this->where($where)->find(); - } elseif (strtolower(substr($method, 0, 10)) == 'getfieldby') { - // 根据某个字段获取记录的某个值 - $name = Loader::parseName(substr($method, 10)); - $where[$name] = $args[0]; - return $this->where($where)->getField($args[1]); - } else { - throw new \think\Exception(__CLASS__ . ':' . $method . Lang::get('_METHOD_NOT_EXIST_')); - } - } - - // 写入数据前的回调方法 包括新增和更新 - protected function _before_write(&$data) - { - $pk = $this->getPk(); - // 根据主键类型处理主键数据 - if (isset($data[$pk]) && self::TYPE_OBJECT == $this->_idType) { - $data[$pk] = new MongoId($data[$pk]); - } - } - - /** - * count统计 配合where连贯操作 - * @access public - * @return integer - */ - public function count() - { - // 分析表达式 - $options = $this->_parseOptions(); - return $this->db->count($options); - } - - /** - * 获取下一ID 用于自动增长型 - * @access public - * @param string $pk 字段名 默认为主键 - * @return mixed - */ - public function getMongoNextId($pk = '') - { - if (empty($pk)) { - $pk = $this->getPk(); - } - return $this->db->getMongoNextId($pk); - } - - // 插入数据前的回调方法 - protected function _before_insert(&$data, $options = []) - { - // 写入数据到数据库 - if ($this->_autoInc && self::TYPE_INT == $this->_idType) { - // 主键自动增长 - $pk = $this->getPk(); - if (!isset($data[$pk])) { - $data[$pk] = $this->db->mongo_next_id($pk); - } - } - } - - public function clear() - { - return $this->db->clear(); - } - - // 查询成功后的回调方法 - protected function _after_select(&$resultSet, $options = []) - { - array_walk($resultSet, [$this, 'checkMongoId']); - } - - /** - * 获取MongoId - * @access protected - * @param array $result 返回数据 - * @return array - */ - protected function checkMongoId(&$result) - { - if (is_object($result['_id'])) { - $result['_id'] = $result['_id']->__toString(); - } - return $result; - } - - // 表达式过滤回调方法 - protected function _options_filter(&$options) - { - $id = $this->getPk(); - if (isset($options['where'][$id]) && is_scalar($options['where'][$id]) && self::TYPE_OBJECT == $this->_idType) { - $options['where'][$id] = new MongoId($options['where'][$id]); - } - } - - /** - * 查询数据 - * @access public - * @param mixed $options 表达式参数 - * @return mixed - */ - public function find($options = []) - { - if (is_numeric($options) || is_string($options)) { - $id = $this->getPk(); - $where[$id] = $options; - $options = []; - $options['where'] = $where; - } - // 分析表达式 - $options = $this->_parseOptions($options); - $result = $this->db->find($options); - if (false === $result) { - return false; - } - if (empty($result)) { - // 查询结果为空 - return null; - } else { - $this->checkMongoId($result); - } - $this->data = $result; - $this->_after_find($this->data, $options); - return $this->data; - } - - /** - * 字段值增长 - * @access public - * @param string $field 字段名 - * @param integer $step 增长值 - * @return boolean - */ - public function setInc($field, $step = 1, $lazyTime = 0) - { - return $this->setField($field, ['inc', $step]); - } - - /** - * 字段值减少 - * @access public - * @param string $field 字段名 - * @param integer $step 减少值 - * @return boolean - */ - public function setDec($field, $step = 1, $lazyTime = 0) - { - return $this->setField($field, ['inc', '-' . $step]); - } - - /** - * 获取一条记录的某个字段值 - * @access public - * @param string $field 字段名 - * @param string $spea 字段数据间隔符号 - * @return mixed - */ - public function getField($field, $sepa = null) - { - $options['field'] = $field; - $options = $this->_parseOptions($options); - if (strpos($field, ',')) { - // 多字段 - if (is_numeric($sepa)) { - // 限定数量 - $options['limit'] = $sepa; - $sepa = null; // 重置为null 返回数组 - } - $resultSet = $this->db->select($options); - if (!empty($resultSet)) { - $_field = explode(',', $field); - $field = array_keys($resultSet[0]); - $key = array_shift($field); - $key2 = array_shift($field); - $cols = []; - $count = count($_field); - foreach ($resultSet as $result) { - $name = $result[$key]; - if (2 == $count) { - $cols[$name] = $result[$key2]; - } else { - $cols[$name] = is_null($sepa) ? $result : implode($sepa, $result); - } - } - return $cols; - } - } else { - // 返回数据个数 - if (true !== $sepa) { - // 当sepa指定为true的时候 返回所有数据 - $options['limit'] = is_numeric($sepa) ? $sepa : 1; - } - // 查找一条记录 - $result = $this->db->find($options); - if (!empty($result)) { - if (1 == $options['limit']) { - return reset($result[0]); - } - - foreach ($result as $val) { - $array[] = $val[$field]; - } - return $array; - } - } - return null; - } - - /** - * 执行Mongo指令 - * @access public - * @param array $command 指令 - * @return mixed - */ - public function command($command) - { - return $this->db->command($command); - } - - /** - * 执行MongoCode - * @access public - * @param string $code MongoCode - * @param array $args 参数 - * @return mixed - */ - public function mongoCode($code, $args = []) - { - return $this->db->execute($code, $args); - } - - // 数据库切换后回调方法 - protected function _after_db() - { - // 切换Collection - $this->db->switchCollection($this->getTableName(), $this->dbName); - } - - /** - * 得到完整的数据表名 Mongo表名不带dbName - * @access public - * @return string - */ - public function getTableName() - { - if (empty($this->trueTableName)) { - $tableName = !empty($this->tablePrefix) ? $this->tablePrefix : ''; - if (!empty($this->tableName)) { - $tableName .= $this->tableName; - } else { - $tableName .= Loader::parseName($this->name); - } - $this->trueTableName = strtolower($tableName); - } - return $this->trueTableName; - } -} diff --git a/thinkphp/library/think/session/driver/Memcached.php b/thinkphp/library/think/session/driver/Memcached.php deleted file mode 100644 index bccfdda0c..000000000 --- a/thinkphp/library/think/session/driver/Memcached.php +++ /dev/null @@ -1,117 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\session\driver; - -use SessionHandler; -use think\Exception; - -class Memcached extends SessionHandler -{ - protected $handler = null; - protected $config = [ - 'host' => '127.0.0.1', // memcache主机 - 'port' => 1121, // memcache端口 - 'expire' => 3600, // session有效期 - 'timeout' => 0, // 连接超时时间(单位:毫秒) - 'session_name' => '', // memcache key前缀 - ]; - - public function __construct($config = []) - { - $this->config = array_merge($this->config, $config); - } - - /** - * 打开Session - * @access public - * @param string $savePath - * @param mixed $sessName - */ - public function open($savePath, $sessName) - { - // 检测php环境 - if (!extension_loaded('memcached')) { - throw new Exception('_NOT_SUPPERT_:memcached'); - } - $this->handler = new \Memcached; - // 设置连接超时时间(单位:毫秒) - if ($this->config['timeout'] > 0) { - $this->handler->setOption(\Memcached::OPT_CONNECT_TIMEOUT, $this->config['timeout']); - } - // 支持集群 - $hosts = explode(',', $this->config['host']); - $ports = explode(',', $this->config['port']); - if (empty($ports[0])) { - $ports[0] = 11211; - } - // 建立连接 - $servers = []; - foreach ((array) $hosts as $i => $host) { - $servers[] = [$host, (isset($ports[$i]) ? $ports[$i] : $ports[0]), 1]; - } - $this->handler->addServers($servers); - return true; - } - - /** - * 关闭Session - * @access public - */ - public function close() - { - $this->gc(ini_get('session.gc_maxlifetime')); - $this->handler->close(); - $this->handler = null; - return true; - } - - /** - * 读取Session - * @access public - * @param string $sessID - */ - public function read($sessID) - { - return $this->handler->get($this->config['session_name'] . $sessID); - } - - /** - * 写入Session - * @access public - * @param string $sessID - * @param String $sessData - */ - public function write($sessID, $sessData) - { - return $this->handler->set($this->config['session_name'] . $sessID, $sessData, $this->config['expire']); - } - - /** - * 删除Session - * @access public - * @param string $sessID - */ - public function destroy($sessID) - { - return $this->handler->delete($this->config['session_name'] . $sessID); - } - - /** - * Session 垃圾回收 - * @access public - * @param string $sessMaxLifeTime - */ - public function gc($sessMaxLifeTime) - { - return true; - } -} diff --git a/thinkphp/library/think/session/driver/Redis.php b/thinkphp/library/think/session/driver/Redis.php deleted file mode 100644 index 43954629b..000000000 --- a/thinkphp/library/think/session/driver/Redis.php +++ /dev/null @@ -1,111 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\session\driver; - -use SessionHandler; -use think\Exception; - -class Redis extends SessionHandler -{ - protected $handler = null; - protected $config = [ - 'host' => '127.0.0.1', // 主机 - 'port' => 6379, // 端口 - 'password' => '', // 密码 - 'expire' => 3600, // 有效期 - 'timeout' => false, // 超时时间 - 'persistent' => 0, // 是否长连接 - 'session_name' => '', // memcache key前缀 - ]; - - public function __construct($config = []) - { - $this->config = array_merge($this->config, $config); - } - - /** - * 打开Session - * @access public - * @param string $savePath - * @param mixed $sessName - */ - public function open($savePath, $sessName) - { - // 检测php环境 - if (!extension_loaded('redis')) { - throw new Exception('_NOT_SUPPERT_:redis'); - } - $this->handler = new \Redis; - // 建立连接 - $func = $this->config['persistent'] ? 'pconnect' : 'connect'; - false === $this->config['timeout'] ? - $this->handler->$func($this->config['host'], $this->config['port']) : - $this->handler->$func($this->config['host'], $this->config['port'], $this->config['timeout']); - if ('' != $this->config['password']) { - $this->handler->auth($this->config['password']); - } - return true; - } - - /** - * 关闭Session - * @access public - */ - public function close() - { - $this->gc(ini_get('session.gc_maxlifetime')); - $this->handler->close(); - $this->handler = null; - return true; - } - - /** - * 读取Session - * @access public - * @param string $sessID - */ - public function read($sessID) - { - return $this->handler->get($this->config['session_name'] . $sessID); - } - - /** - * 写入Session - * @access public - * @param string $sessID - * @param String $sessData - */ - public function write($sessID, $sessData) - { - return $this->handler->set($this->config['session_name'] . $sessID, $sessData, 0, $this->config['expire']); - } - - /** - * 删除Session - * @access public - * @param string $sessID - */ - public function destroy($sessID) - { - return $this->handler->delete($this->config['session_name'] . $sessID); - } - - /** - * Session 垃圾回收 - * @access public - * @param string $sessMaxLifeTime - */ - public function gc($sessMaxLifeTime) - { - return true; - } -} diff --git a/thinkphp/library/think/template/TagLib.php b/thinkphp/library/think/template/TagLib.php deleted file mode 100644 index be02d6a05..000000000 --- a/thinkphp/library/think/template/TagLib.php +++ /dev/null @@ -1,388 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\template; - -use think\Exception; - -/** - * ThinkPHP标签库TagLib解析基类 - * @category Think - * @package Think - * @subpackage Template - * @author liu21st - */ -class TagLib -{ - - /** - * 标签库定义XML文件 - * @var string - * @access protected - */ - protected $xml = ''; - protected $tags = []; // 标签定义 - /** - * 标签库名称 - * @var string - * @access protected - */ - protected $tagLib = ''; - - /** - * 标签库标签列表 - * @var string - * @access protected - */ - protected $tagList = []; - - /** - * 标签库分析数组 - * @var string - * @access protected - */ - protected $parse = []; - - /** - * 标签库是否有效 - * @var string - * @access protected - */ - protected $valid = false; - - /** - * 当前模板对象 - * @var object - * @access protected - */ - protected $tpl; - - protected $comparison = [' nheq ' => ' !== ', ' heq ' => ' === ', ' neq ' => ' != ', ' eq ' => ' == ', ' egt ' => ' >= ', ' gt ' => ' > ', ' elt ' => ' <= ', ' lt ' => ' < ']; - - /** - * 架构函数 - * @access public - * @param class $template 模板引擎对象 - */ - public function __construct($template) - { - $this->tpl = $template; - } - - /** - * 按签标库替换页面中的标签 - * @access public - * @param string $content 模板内容 - * @param string $lib 标签库名 - * @return void - */ - public function parseTag(&$content, $lib = '') - { - $tags = []; - foreach ($this->tags as $name => $val) { - $close = !isset($val['close']) || $val['close'] ? 1 : 0; - $_key = $lib ? $lib . ':' . $name : $name; - $tags[$close][$_key] = $name; - if (isset($val['alias'])) { - // 别名设置 - foreach (explode(',', $val['alias']) as $v) { - $_key = $lib ? $lib . ':' . $v : $v; - $tags[$close][$_key] = $name; - } - } - } - - // 闭合标签 - if (!empty($tags[1])) { - $nodes = []; - $regex = $this->getRegex(array_keys($tags[1]), 1); - if (preg_match_all($regex, $content, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { - $right = []; - foreach ($matches as $match) { - if ('' == $match[1][0]) { - $name = $match[2][0]; - // 如果有没闭合的标签头则取出最后一个 - if (!empty($right[$name])) { - // $match[0][1]为标签结束符在模板中的位置 - $nodes[$match[0][1]] = [ - 'name' => $name, - 'begin' => array_pop($right[$name]), // 标签开始符 - 'end' => $match[0], // 标签结束符 - ]; - } else { - continue; - } - } else { - // 标签头压入栈 - $right[$match[1][0]][] = $match[0]; - } - } - unset($right, $matches); - // 按标签在模板中的位置从后向前排序 - krsort($nodes); - } - - $break = ''; - if ($nodes) { - $beginArray = []; - // 标签替换 从后向前 - foreach ($nodes as $pos => $node) { - // 对应的标签名 - $name = $tags[1][$node['name']]; - // 解析标签属性 - $attrs = $this->parseAttr($node['begin'][0], $name); - $method = '_' . $name; - // 读取标签库中对应的标签内容 replace[0]用来替换标签头,replace[1]用来替换标签尾 - $replace = explode($break, $this->$method($attrs, $break, $node['name'])); - if (count($replace) > 1) { - while ($beginArray) { - $begin = end($beginArray); - // 判断当前标签尾的位置是否在栈中最后一个标签头的后面,是则为子标签 - if ($node['end'][1] > $begin['pos']) { - break; - } else { - // 不为子标签时,取出栈中最后一个标签头 - $begin = array_pop($beginArray); - // 替换标签头部 - $content = substr_replace($content, $begin['str'], $begin['pos'], $begin['len']); - } - } - // 替换标签尾部 - $content = substr_replace($content, $replace[1], $node['end'][1], strlen($node['end'][0])); - // 把标签头压入栈 - $beginArray[] = ['pos' => $node['begin'][1], 'len' => strlen($node['begin'][0]), 'str' => $replace[0]]; - } - } - while ($beginArray) { - $begin = array_pop($beginArray); - // 替换标签头部 - $content = substr_replace($content, $begin['str'], $begin['pos'], $begin['len']); - } - } - } - // 自闭合标签 - if (!empty($tags[0])) { - $regex = $this->getRegex(array_keys($tags[0]), 0); - $self = &$this; - $content = preg_replace_callback($regex, function ($matches) use (&$tags, &$self) { - $name = $tags[0][$matches[1]]; - // 解析标签属性 - $attrs = $self->parseAttr($matches[0], $name); - $method = '_' . $name; - return $self->$method($attrs, '', $matches[1]); - }, $content); - } - return; - } - - /** - * 按标签生成正则 - * @access private - * @param array|string $tags 标签名 - * @param boolean $close 是否为闭合标签 - * @return string - */ - private function getRegex($tags, $close) - { - $begin = $this->tpl->config('taglib_begin'); - $end = $this->tpl->config('taglib_end'); - $single = strlen(ltrim($begin, '\\')) == 1 && strlen(ltrim($end, '\\')) == 1 ? true : false; - if (is_array($tags)) { - $tagName = implode('|', $tags); - } else { - $tagName = $tags; - } - if ($single) { - if ($close) { - // 如果是闭合标签 - $regex = $begin . '(?:(' . $tagName . ')\b(?>[^' . $end . ']*)|\/(' . $tagName . '))' . $end; - } else { - $regex = $begin . '(' . $tagName . ')\b(?>[^' . $end . ']*)' . $end; - } - } else { - if ($close) { - // 如果是闭合标签 - $regex = $begin . '(?:(' . $tagName . ')\b(?>(?:(?!' . $end . ').)*)|\/(' . $tagName . '))' . $end; - } else { - $regex = $begin . '(' . $tagName . ')\b(?>(?:(?!' . $end . ').)*)' . $end; - } - } - return '/' . $regex . '/is'; - } - - /** - * TagLib标签属性分析 返回标签属性数组 - * @access public - * @param string $attr 标签属性字符串 - * @param string $tag 标签名 - * @return array - * @throws Exception - * @internal param string $tagStr 标签内容 - */ - public function parseXmlAttr($attr, $tag) - { - if ('' == trim($attr)) { - return []; - } - //XML解析安全过滤 - $attr = str_replace('&', '___', $attr); - if (substr($attr, 0, 1) == '<' && substr($attr, -1, 1) == '>') { - $xml = '' . $attr . ''; - } else { - $xml = ''; - } - $xml = simplexml_load_string($xml); - if (!$xml) { - throw new Exception('_XML_TAG_ERROR_ : ' . $attr); - } - $xml = (array) ($xml->tag->attributes()); - if (isset($xml['@attributes']) && $result = array_change_key_case($xml['@attributes'])) { - $tag = strtolower($tag); - if (!isset($this->tags[$tag])) { - // 检测是否存在别名定义 - foreach ($this->tags as $key => $val) { - if (isset($val['alias']) && in_array($tag, explode(',', $val['alias']))) { - $item = $val; - break; - } - } - } else { - $item = $this->tags[$tag]; - } - if (!empty($item['attr'])) { - if (isset($item['must'])) { - $must = explode(',', $item['must']); - } else { - $must = []; - } - $attrs = explode(',', $item['attr']); - foreach ($attrs as $name) { - if (isset($result[$name])) { - $result[$name] = str_replace('___', '&', $result[$name]); - } elseif (false !== array_search($name, $must)) { - throw new Exception('_PARAM_ERROR_:' . $name); - } - } - } - return $result; - } else { - return []; - } - } - - /** - * 分析标签属性 正则方式 - * @access public - * @param string $str 标签属性字符串 - * @param string $tag 标签名 - * @return array - */ - public function parseAttr($str, $tag) - { - if (ini_get('magic_quotes_sybase')) { - $str = str_replace('\"', '\'', $str); - } - $regex = '/\s+(?>(?\w+)\s*)=(?>\s*)([\"\'])(?(?:(?!\\2).)*)\\2/is'; - $result = []; - if (preg_match_all($regex, $str, $matches)) { - foreach ($matches['name'] as $key => $val) { - $result[$val] = $matches['value'][$key]; - } - $tag = strtolower($tag); - if (!isset($this->tags[$tag])) { - // 检测是否存在别名定义 - foreach ($this->tags as $key => $val) { - if (isset($val['alias']) && in_array($tag, explode(',', $val['alias']))) { - $item = $val; - break; - } - } - } else { - $item = $this->tags[$tag]; - } - if (!empty($item['must'])) { - $must = explode(',', $item['must']); - foreach ($must as $name) { - if (!isset($result[$name])) { - throw new Exception('_PARAM_ERROR_:' . $name); - } - } - } - } else { - // 允许直接使用表达式的标签 - if (!empty($this->tags[$tag]['expression'])) { - static $_taglibs; - if (!isset($_taglibs[$tag])) { - $_taglibs[$tag][0] = strlen(ltrim($this->tpl->config('taglib_begin'), '\\') . $tag); - $_taglibs[$tag][1] = strlen(ltrim($this->tpl->config('taglib_end'), '\\')); - } - $result['expression'] = substr($str, $_taglibs[$tag][0], -$_taglibs[$tag][1]); - // 清除自闭合标签尾部/ - $result['expression'] = rtrim($result['expression'], '/'); - $result['expression'] = trim($result['expression']); - } elseif (empty($this->tags[$tag]) || !empty($this->tags[$tag]['attr'])) { - throw new Exception('_XML_TAG_ERROR_:' . $tag); - } - } - return $result; - } - - /** - * 解析条件表达式 - * @access public - * @param string $condition 表达式标签内容 - * @return string - */ - public function parseCondition($condition) - { - $condition = str_ireplace(array_keys($this->comparison), array_values($this->comparison), $condition); - $this->tpl->parseVar($condition); - $this->tpl->parseVarFunction($condition); // XXX: 此句能解析表达式中用|分隔的函数,但表达式中如果有|、||这样的逻辑运算就产生了歧异 - return $condition; - } - - /** - * 自动识别构建变量 - * @access public - * @param string $name 变量描述 - * @return string - */ - public function autoBuildVar(&$name) - { - $flag = substr($name, 0, 1); - if (':' == $flag) { - // 以:开头为函数调用,解析前去掉: - $name = substr($name, 1); - } elseif ('$' != $flag && preg_match('/[a-zA-Z_]/', $flag)) { - // XXX: 这句的写法可能还需要改进 - // 常量不需要解析 - if (defined($name)) { - return $name; - } - // 不以$开头并且也不是常量,自动补上$前缀 - $name = '$' . $name; - } - $this->tpl->parseVar($name); - $this->tpl->parseVarFunction($name); - return $name; - } - - /** - * 获取标签列表 - * @access public - * @return array - */ - // 获取标签定义 - public function getTags() - { - return $this->tags; - } -} diff --git a/thinkphp/library/think/template/driver/File.php b/thinkphp/library/think/template/driver/File.php deleted file mode 100644 index 2fb143a83..000000000 --- a/thinkphp/library/think/template/driver/File.php +++ /dev/null @@ -1,53 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\template\driver; - -use think\Exception; - -class File -{ - // 写入编译缓存 - public function write($cacheFile, $content) - { - // 检测模板目录 - $dir = dirname($cacheFile); - if (!is_dir($dir)) { - mkdir($dir, 0777, true); - } - // 生成模板缓存文件 - if (false === file_put_contents($cacheFile, $content)) { - throw new Exception('cache write error :' . $cacheFile, 11602); - } - } - - // 读取编译编译 - public function read($cacheFile, $vars) - { - // 模板阵列变量分解成为独立变量 - extract($vars, EXTR_OVERWRITE); - //载入模版缓存文件 - include $cacheFile; - } - - // 检查编译缓存是否有效 - public function check($template, $cacheFile, $cacheTime) - { - if (!is_file($cacheFile) || (is_file($template) && filemtime($template) > filemtime($cacheFile))) { - // 模板文件如果有更新则缓存需要更新 - return false; - } elseif (0 != $cacheTime && time() > filemtime($cacheFile) + $cacheTime) { - // 缓存是否在有效期 - return false; - } - return true; - } -} diff --git a/thinkphp/library/think/template/driver/Sae.php b/thinkphp/library/think/template/driver/Sae.php deleted file mode 100644 index 8e1c93002..000000000 --- a/thinkphp/library/think/template/driver/Sae.php +++ /dev/null @@ -1,98 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\template\driver; - -use think\Exception; - -class Sae -{ - // mc 对象 - private $mc; - // 编译缓存内容 - private $contents = []; - - /** - * 架构函数 - * @access public - */ - public function __construct() - { - if (!function_exists('memcache_init')) { - throw new Exception('请在SAE平台上运行代码。'); - } - $this->mc = @memcache_init(); - if (!$this->mc) { - throw new Exception('您未开通Memcache服务,请在SAE管理平台初始化Memcache服务'); - } - } - - // 写入编译缓存 - public function write($cacheFile, $content) - { - // 添加写入时间 - $content = time() . $content; - if (!$this->mc->set($cacheFile, $content, MEMCACHE_COMPRESSED, 0)) { - throw new Exception('sae mc write error :' . $cacheFile); - } else { - $this->contents[$cacheFile] = $content; - return true; - } - } - - // 读取编译编译 - public function read($cacheFile, $vars) - { - if (!is_null($vars)) { - extract($vars, EXTR_OVERWRITE); - } - eval('?>' . $this->get($cacheFile, 'content')); - } - - // 检查编译缓存是否有效 - public function check($template, $cacheFile, $cacheTime) - { - $mtime = $this->get($cacheFile, 'mtime'); - if (!$this->get($cacheFile, 'content') || (is_file($template) && filemtime($template) > $mtime)) { - // 模板文件如果有更新则缓存需要更新 - return false; - }if (0 != $cacheTime && time() > $mtime + $cacheTime) { - // 缓存是否在有效期 - return false; - } else { - return true; - } - } - - /** - * 读取文件信息 - * @access private - * @param string $filename 文件名 - * @param string $name 信息名 mtime或者content - * @return boolean - */ - private function get($filename, $name) - { - if (!isset($this->contents[$filename])) { - $this->contents[$filename] = $this->mc->get($filename); - } - $content = $this->contents[$filename]; - - if (false === $content) { - return false; - } - $info = array( - 'mtime' => substr($content, 0, 10), - 'content' => substr($content, 10), - ); - return $info[$name]; - } -} diff --git a/thinkphp/library/think/template/taglib/Cx.php b/thinkphp/library/think/template/taglib/Cx.php deleted file mode 100644 index 277556971..000000000 --- a/thinkphp/library/think/template/taglib/Cx.php +++ /dev/null @@ -1,705 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\template\taglib; - -use think\template\TagLib; - -/** - * CX标签库解析类 - * @category Think - * @package Think - * @subpackage Driver.Taglib - * @author liu21st - */ -class Cx extends Taglib -{ - - // 标签定义 - protected $tags = [ - // 标签定义: attr 属性列表 close 是否闭合(0 或者1 默认1) alias 标签别名 level 嵌套层次 - 'php' => ['attr' => ''], - 'volist' => ['attr' => 'name,id,offset,length,key,mod', 'alias' => 'iterate'], - 'foreach' => ['attr' => 'name,id,item,key,offset,length,mod', 'expression' => true], - 'if' => ['attr' => 'condition', 'expression' => true], - 'elseif' => ['attr' => 'condition', 'close' => 0, 'expression' => true], - 'else' => ['attr' => '', 'close' => 0], - 'switch' => ['attr' => 'name', 'expression' => true], - 'case' => ['attr' => 'value,break', 'expression' => true], - 'default' => ['attr' => '', 'close' => 0], - 'compare' => ['attr' => 'name,value,type', 'alias' => 'eq,equal,notequal,neq,gt,lt,egt,elt,heq,nheq'], - 'range' => ['attr' => 'name,value,type', 'alias' => 'in,notin,between,notbetween'], - 'empty' => ['attr' => 'name'], - 'notempty' => ['attr' => 'name'], - 'present' => ['attr' => 'name'], - 'notpresent' => ['attr' => 'name'], - 'defined' => ['attr' => 'name'], - 'notdefined' => ['attr' => 'name'], - 'import' => ['attr' => 'file,href,type,value,basepath', 'close' => 0, 'alias' => 'load,css,js'], - 'assign' => ['attr' => 'name,value', 'close' => 0], - 'define' => ['attr' => 'name,value', 'close' => 0], - 'for' => ['attr' => 'start,end,name,comparison,step'], - ]; - - /** - * php标签解析 - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _php($tag, $content) - { - $parseStr = ''; - return $parseStr; - } - - /** - * volist标签解析 循环输出数据集 - * 格式: - * - * {user.username} - * {user.email} - * - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string|void - */ - public function _volist($tag, $content) - { - $name = $tag['name']; - $id = $tag['id']; - $empty = isset($tag['empty']) ? $tag['empty'] : ''; - $key = !empty($tag['key']) ? $tag['key'] : 'i'; - $mod = isset($tag['mod']) ? $tag['mod'] : '2'; - // 允许使用函数设定数据集 {$vo.name} - $parseStr = 'autoBuildVar($name); - $parseStr .= '$_result=' . $name . ';'; - $name = '$_result'; - } else { - $name = $this->autoBuildVar($name); - } - $parseStr .= 'if(is_array(' . $name . ')): $' . $key . ' = 0;'; - if (isset($tag['length']) && '' != $tag['length']) { - $parseStr .= ' $__LIST__ = array_slice(' . $name . ',' . $tag['offset'] . ',' . $tag['length'] . ',true);'; - } elseif (isset($tag['offset']) && '' != $tag['offset']) { - $parseStr .= ' $__LIST__ = array_slice(' . $name . ',' . $tag['offset'] . ',null,true);'; - } else { - $parseStr .= ' $__LIST__ = ' . $name . ';'; - } - $parseStr .= 'if( count($__LIST__)==0 ) : echo "' . $empty . '" ;'; - $parseStr .= 'else: '; - $parseStr .= 'foreach($__LIST__ as $key=>$' . $id . '): '; - $parseStr .= '$mod = ($' . $key . ' % ' . $mod . ' );'; - $parseStr .= '++$' . $key . ';?>'; - $parseStr .= $content; - $parseStr .= ''; - - if (!empty($parseStr)) { - return $parseStr; - } - return; - } - - /** - * foreach标签解析 循环输出数据集 - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string|void - */ - public function _foreach($tag, $content) - { - // 直接使用表达式 - if (!empty($tag['expression'])) { - $expression = ltrim(rtrim($tag['expression'], ')'), '('); - $expression = $this->autoBuildVar($expression); - $parseStr = ''; - $parseStr .= $content; - $parseStr .= ''; - return $parseStr; - } - $name = $tag['name']; - $key = !empty($tag['key']) ? $tag['key'] : 'key'; - $item = !empty($tag['id']) ? $tag['id'] : $tag['item']; - $offset = !empty($tag['offset']) && is_numeric($tag['offset']) ? intval($tag['offset']) : 0; - $length = !empty($tag['length']) && is_numeric($tag['length']) ? intval($tag['length']) : 'null'; - - $parseStr = 'autoBuildVar($name); - $parseStr .= $var . '=' . $name . '; '; - $name = $var; - } else { - $name = $this->autoBuildVar($name); - } - $parseStr .= 'if(is_array(' . $name . ')): '; - // 设置了输出数组长度 - if (0 != $offset || 'null' != $length) { - if (!isset($var)) { - $var = '$_' . uniqid(); - } - $parseStr .= $var . ' = array_slice(' . $name . ',' . $offset . ',' . $length . ',true); '; - } else { - $var = &$name; - } - // 设置了索引项 - if (isset($tag['index'])) { - $index = $tag['index']; - $parseStr .= '$' . $index . '=0; '; - } - $parseStr .= 'foreach(' . $var . ' as $' . $key . '=>$' . $item . '): '; - // 设置了索引项 - if (isset($tag['index'])) { - $index = $tag['index']; - if (isset($tag['mod'])) { - $mod = (int) $tag['mod']; - $parseStr .= '$mod = ($' . $index . ' % ' . $mod . '); '; - } - $parseStr .= '++$' . $index . '; '; - } - $parseStr .= '?>'; - // 循环体中的内容 - $parseStr .= $content; - $parseStr .= ''; - // 设置了数组为空时的显示内容 - if (isset($tag['empty'])) { - $parseStr .= ''; - } - - if (!empty($parseStr)) { - return $parseStr; - } - return; - } - - /** - * if标签解析 - * 格式: - * - * - * - * - * 表达式支持 eq neq gt egt lt elt == > >= < <= or and || && - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _if($tag, $content) - { - $condition = !empty($tag['expression']) ? $tag['expression'] : $tag['condition']; - $condition = $this->parseCondition($condition); - $parseStr = '' . $content . ''; - return $parseStr; - } - - /** - * else标签解析 - * 格式:见if标签 - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _elseif($tag, $content) - { - $condition = !empty($tag['expression']) ? $tag['expression'] : $tag['condition']; - $condition = $this->parseCondition($condition); - $parseStr = ''; - return $parseStr; - } - - /** - * else标签解析 - * @access public - * @param array $tag 标签属性 - * @return string - */ - public function _else($tag) - { - $parseStr = ''; - return $parseStr; - } - - /** - * switch标签解析 - * 格式: - * - * 1 - * 2 - * other - * - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _switch($tag, $content) - { - $name = !empty($tag['expression']) ? $tag['expression'] : $tag['name']; - $name = $this->autoBuildVar($name); - $parseStr = '' . $content . ''; - return $parseStr; - } - - /** - * case标签解析 需要配合switch才有效 - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _case($tag, $content) - { - $value = !empty($tag['expression']) ? $tag['expression'] : $tag['value']; - $flag = substr($value, 0, 1); - if ('$' == $flag || ':' == $flag) { - $value = $this->autoBuildVar($value); - $value = 'case ' . $value . ':'; - } elseif (strpos($value, '|')) { - $values = explode('|', $value); - $value = ''; - foreach ($values as $val) { - $value .= 'case "' . addslashes($val) . '":'; - } - } else { - $value = 'case "' . $value . '":'; - } - $parseStr = '' . $content; - $isBreak = isset($tag['break']) ? $tag['break'] : ''; - if ('' == $isBreak || $isBreak) { - $parseStr .= ''; - } - return $parseStr; - } - - /** - * default标签解析 需要配合switch才有效 - * 使用: ddfdf - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _default($tag) - { - $parseStr = ''; - return $parseStr; - } - - /** - * compare标签解析 - * 用于值的比较 支持 eq neq gt lt egt elt heq nheq 默认是eq - * 格式: content - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @param string $type 比较类型 - * @return string - */ - public function _compare($tag, $content, $type = 'eq') - { - $name = $tag['name']; - $value = $tag['value']; - $type = isset($tag['type']) ? $tag['type'] : $type; - $name = $this->autoBuildVar($name); - $flag = substr($value, 0, 1); - if ('$' == $flag || ':' == $flag) { - $value = $this->autoBuildVar($value); - } else { - $value = '\'' . $value . '\''; - } - $type = $this->parseCondition(' ' . $type . ' '); - $parseStr = '' . $content . ''; - return $parseStr; - } - - public function _eq($tag, $content) - { - return $this->_compare($tag, $content, 'eq'); - } - - public function _equal($tag, $content) - { - return $this->_compare($tag, $content, 'eq'); - } - - public function _neq($tag, $content) - { - return $this->_compare($tag, $content, 'neq'); - } - - public function _notequal($tag, $content) - { - return $this->_compare($tag, $content, 'neq'); - } - - public function _gt($tag, $content) - { - return $this->_compare($tag, $content, 'gt'); - } - - public function _lt($tag, $content) - { - return $this->_compare($tag, $content, 'lt'); - } - - public function _egt($tag, $content) - { - return $this->_compare($tag, $content, 'egt'); - } - - public function _elt($tag, $content) - { - return $this->_compare($tag, $content, 'elt'); - } - - public function _heq($tag, $content) - { - return $this->_compare($tag, $content, 'heq'); - } - - public function _nheq($tag, $content) - { - return $this->_compare($tag, $content, 'nheq'); - } - - /** - * range标签解析 - * 如果某个变量存在于某个范围 则输出内容 type= in 表示在范围内 否则表示在范围外 - * 格式: content - * example: content - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @param string $type 比较类型 - * @return string - */ - public function _range($tag, $content, $type = 'in') - { - $name = $tag['name']; - $value = $tag['value']; - $type = isset($tag['type']) ? $tag['type'] : $type; - - $name = $this->autoBuildVar($name); - $flag = substr($value, 0, 1); - if ('$' == $flag || ':' == $flag) { - $value = $this->autoBuildVar($value); - $str = 'is_array(' . $value . ')?' . $value . ':explode(\',\',' . $value . ')'; - } else { - $value = '"' . $value . '"'; - $str = 'explode(\',\',' . $value . ')'; - } - if ('between' == $type) { - $parseStr = '= $_RANGE_VAR_[0] && ' . $name . '<= $_RANGE_VAR_[1]):?>' . $content . ''; - } elseif ('notbetween' == $type) { - $parseStr = '$_RANGE_VAR_[1]):?>' . $content . ''; - } else { - $fun = ('in' == $type) ? 'in_array' : '!in_array'; - $parseStr = '' . $content . ''; - } - return $parseStr; - } - - // range标签的别名 用于in判断 - public function _in($tag, $content) - { - return $this->_range($tag, $content, 'in'); - } - - // range标签的别名 用于notin判断 - public function _notin($tag, $content) - { - return $this->_range($tag, $content, 'notin'); - } - - public function _between($tag, $content) - { - return $this->_range($tag, $content, 'between'); - } - - public function _notbetween($tag, $content) - { - return $this->_range($tag, $content, 'notbetween'); - } - - /** - * present标签解析 - * 如果某个变量已经设置 则输出内容 - * 格式: content - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _present($tag, $content) - { - $name = $tag['name']; - $name = $this->autoBuildVar($name); - $parseStr = '' . $content . ''; - return $parseStr; - } - - /** - * notpresent标签解析 - * 如果某个变量没有设置,则输出内容 - * 格式: content - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _notpresent($tag, $content) - { - $name = $tag['name']; - $name = $this->autoBuildVar($name); - $parseStr = '' . $content . ''; - return $parseStr; - } - - /** - * empty标签解析 - * 如果某个变量为empty 则输出内容 - * 格式: content - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _empty($tag, $content) - { - $name = $tag['name']; - $name = $this->autoBuildVar($name); - $parseStr = '' . $content . ''; - return $parseStr; - } - - public function _notempty($tag, $content) - { - $name = $tag['name']; - $name = $this->autoBuildVar($name); - $parseStr = '' . $content . ''; - return $parseStr; - } - - /** - * 判断是否已经定义了该常量 - * 已定义 - * @param array $tag - * @param string $content - * @return string - */ - public function _defined($tag, $content) - { - $name = $tag['name']; - $parseStr = '' . $content . ''; - return $parseStr; - } - - public function _notdefined($tag, $content) - { - $name = $tag['name']; - $parseStr = '' . $content . ''; - return $parseStr; - } - - /** - * import 标签解析 - * - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @param boolean $isFile 是否文件方式 - * @param string $type 类型 - * @return string - */ - public function _import($tag, $content, $isFile = false, $type = '') - { - $file = isset($tag['file']) ? $tag['file'] : $tag['href']; - $parseStr = ''; - $endStr = ''; - // 判断是否存在加载条件 允许使用函数判断(默认为isset) - if (isset($tag['value'])) { - $name = $tag['value']; - $name = $this->autoBuildVar($name); - $name = 'isset(' . $name . ')'; - $parseStr .= ''; - $endStr = ''; - } - if ($isFile) { - // 根据文件名后缀自动识别 - $type = $type ? $type : (!empty($tag['type']) ? strtolower($tag['type']) : null); - // 文件方式导入 - $array = explode(',', $file); - foreach ($array as $val) { - if (!$type || isset($reset)) { - $type = $reset = strtolower(substr(strrchr($val, '.'), 1)); - } - switch ($type) { - case 'js': - $parseStr .= ''; - break; - case 'css': - $parseStr .= ''; - break; - case 'php': - $parseStr .= ''; - break; - } - } - } else { - // 命名空间导入模式 默认是js - $type = $type ? $type : (!empty($tag['type']) ? strtolower($tag['type']) : 'js'); - $basepath = !empty($tag['basepath']) ? $tag['basepath'] : __ROOT__ . '/Public'; - // 命名空间方式导入外部文件 - $array = explode(',', $file); - foreach ($array as $val) { - if (strpos($val, '?')) { - list($val, $version) = explode('?', $val); - } else { - $version = ''; - } - switch ($type) { - case 'js': - $parseStr .= ''; - break; - case 'css': - $parseStr .= ''; - break; - case 'php': - $parseStr .= ''; - break; - } - } - } - return $parseStr . $endStr; - } - - // import别名 采用文件方式加载(要使用命名空间必须用import) 例如 - public function _load($tag, $content) - { - return $this->_import($tag, $content, true); - } - - // import别名使用 导入css文件 - public function _css($tag, $content) - { - return $this->_import($tag, $content, true, 'css'); - } - - // import别名使用 导入js文件 - public function _js($tag, $content) - { - return $this->_import($tag, $content, true, 'js'); - } - - /** - * assign标签解析 - * 在模板中给某个变量赋值 支持变量赋值 - * 格式: - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _assign($tag, $content) - { - $name = $this->autoBuildVar($tag['name']); - $flag = substr($tag['value'], 0, 1); - if ('$' == $flag || ':' == $flag) { - $value = $this->autoBuildVar($tag['value']); - } else { - $value = '\'' . $tag['value'] . '\''; - } - $parseStr = ''; - return $parseStr; - } - - /** - * define标签解析 - * 在模板中定义常量 支持变量赋值 - * 格式: - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _define($tag, $content) - { - $name = '\'' . $tag['name'] . '\''; - $flag = substr($tag['value'], 0, 1); - if ('$' == $flag || ':' == $flag) { - $value = $this->autoBuildVar($tag['value']); - } else { - $value = '\'' . $tag['value'] . '\''; - } - $parseStr = ''; - return $parseStr; - } - - /** - * for标签解析 - * 格式: - * @access public - * @param array $tag 标签属性 - * @param string $content 标签内容 - * @return string - */ - public function _for($tag, $content) - { - //设置默认值 - $start = 0; - $end = 0; - $step = 1; - $comparison = 'lt'; - $name = 'i'; - $rand = rand(); //添加随机数,防止嵌套变量冲突 - //获取属性 - foreach ($tag as $key => $value) { - $value = trim($value); - $flag = substr($value, 0, 1); - if ('$' == $flag || ':' == $flag) { - $value = $this->autoBuildVar($value); - } - - switch ($key) { - case 'start': - $start = $value; - break; - case 'end': - $end = $value; - break; - case 'step': - $step = $value; - break; - case 'comparison': - $comparison = $value; - break; - case 'name': - $name = $value; - break; - } - } - - $parseStr = 'parseCondition('$' . $name . ' ' . $comparison . ' $__FOR_END_' . $rand . '__') . ';$' . $name . '+=' . $step . '){ ?>'; - $parseStr .= $content; - $parseStr .= ''; - return $parseStr; - } -} diff --git a/thinkphp/library/think/view/driver/Think.php b/thinkphp/library/think/view/driver/Think.php deleted file mode 100644 index 1c7a21a07..000000000 --- a/thinkphp/library/think/view/driver/Think.php +++ /dev/null @@ -1,32 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think\view\driver; - -use think\Template; - -class Think -{ - private $template = null; - public function __construct($config = []) - { - $this->template = new Template($config); - } - - public function fetch($template, $data = [], $cache = []) - { - if (is_file($template)) { - $this->template->display($template, $data, $cache); - } else { - $this->template->fetch($template, $data); - } - } -} diff --git a/thinkphp/library/traits/controller/Jump.php b/thinkphp/library/traits/controller/Jump.php deleted file mode 100644 index f40bae1a2..000000000 --- a/thinkphp/library/traits/controller/Jump.php +++ /dev/null @@ -1,61 +0,0 @@ -error(); - * $this->redirect(); - * } - * } - */ -namespace traits\controller; - -use think\Response; - -trait Jump -{ - /** - * 操作错误跳转的快捷方法 - * @access public - * @param mixed $msg 提示信息 - * @param mixed $data 返回的数据 - * @param mixed $url 跳转的URL地址 - * @param mixed $wait 跳转等待时间 - * @return void - */ - public function error($msg = '', $data = '', $url = '', $wait = 3) - { - return Response::error($msg, $data, $url, $wait); - } - - /** - * 操作成功跳转的快捷方法 - * @access public - * @param mixed $msg 提示信息 - * @param mixed $data 返回的数据 - * @param mixed $url 跳转的URL地址 - * @param mixed $wait 跳转等待时间 - * @return void - */ - public function success($msg = '', $data = '', $url = '', $wait = 3) - { - return Response::success($msg, $data, $url, $wait); - } - - /** - * URL重定向 - * @access protected - * @param string $url 跳转的URL表达式 - * @param array|int $params 其它URL参数或http code - * @return void - */ - public function redirect($url, $params = []) - { - return Response::redirect($url, $params); - } - -} diff --git a/thinkphp/library/traits/controller/View.php b/thinkphp/library/traits/controller/View.php deleted file mode 100644 index 87aac7408..000000000 --- a/thinkphp/library/traits/controller/View.php +++ /dev/null @@ -1,75 +0,0 @@ -assign(); - * $this->show(); - * } - * } - */ -namespace traits\controller; - -use think\Config; - -trait View -{ - // 视图类实例 - protected $view = null; - - /** - * 架构函数 初始化视图类 并采用内置模板引擎 - * @access public - */ - public function initView() - { - // 模板引擎参数 - if (is_null($this->view)) { - $this->view = \think\View::instance(Config::get()); // 只能这样写,不然view会冲突 - } - } - - /** - * 加载模板和页面输出 可以返回输出内容 - * @access public - * @param string $template 模板文件名 - * @param array $vars 模板输出变量 - * @param string $cache_id 模板缓存标识 - * @return mixed - */ - public function fetch($template = '', $vars = [], $cache_id = '') - { - $this->initView(); - return $this->view->fetch($template, $vars, $cache_id); - } - - /** - * 渲染内容输出 - * @access public - * @param string $content 内容 - * @param array $vars 模板输出变量 - * @return mixed - */ - public function show($content, $vars = []) - { - $this->initView(); - return $this->view->show($content, $vars); - } - - /** - * 模板变量赋值 - * @access protected - * @param mixed $name 要显示的模板变量 - * @param mixed $value 变量的值 - * @return void - */ - public function assign($name, $value = '') - { - $this->initView(); - $this->view->assign($name, $value); - } -} diff --git a/thinkphp/library/traits/model/Adv.php b/thinkphp/library/traits/model/Adv.php deleted file mode 100644 index 21c3d7e2b..000000000 --- a/thinkphp/library/traits/model/Adv.php +++ /dev/null @@ -1,394 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace traits\model; - -trait Adv -{ - protected $optimLock = 'lock_version'; - //protected $serializeField = []; - //protected $readonlyField = []; - //protected $partition = []; - - /** - * 利用__call方法重载 实现一些特殊的Model方法 (魔术方法) - * @access public - * @param string $method 方法名称 - * @param mixed $args 调用参数 - * @return mixed - */ - public function __call($method, $args) - { - if (strtolower(substr($method, 0, 3)) == 'top') { - // 获取前N条记录 - $count = substr($method, 3); - array_unshift($args, $count); - return call_user_func_array([ & $this, 'topN'], $args); - } else { - return parent::__call($method, $args); - } - } - - /** - * 对保存到数据库的数据进行处理 - * @access protected - * @param mixed $data 要操作的数据 - * @return boolean - */ - protected function _before_write(&$data) - { - // 检查序列化字段 - $data = $this->serializeField($data); - } - - // 查询成功后的回调方法 - protected function _after_find(&$result, $options = []) - { - // 检查序列化字段 - $this->checkSerializeField($result); - // 缓存乐观锁 - $this->cacheLockVersion($result); - } - - // 查询数据集成功后的回调方法 - protected function _after_select(&$resultSet, $options = []) - { - // 检查序列化字段 - $resultSet = $this->checkListSerializeField($resultSet); - } - - // 写入前的回调方法 - protected function _before_insert(&$data, $options = []) - { - // 记录乐观锁 - $data = $this->recordLockVersion($data); - } - - // 更新前的回调方法 - protected function _before_update(&$data, $options = []) - { - // 检查乐观锁 - $pk = $this->getPK(); - if (isset($options['where'][$pk])) { - $id = $options['where'][$pk]; - if (!$this->checkLockVersion($id, $data)) { - return false; - } - } - // 检查只读字段 - $data = $this->checkReadonlyField($data); - } - - /** - * 记录乐观锁 - * @access protected - * @param array $data 数据对象 - * @return array - */ - protected function recordLockVersion($data) - { - // 记录乐观锁 - if ($this->optimLock && !isset($data[$this->optimLock])) { - if (in_array($this->optimLock, $this->fields, true)) { - $data[$this->optimLock] = 0; - } - } - return $data; - } - - /** - * 缓存乐观锁 - * @access protected - * @param array $data 数据对象 - * @return void - */ - protected function cacheLockVersion($data) - { - if ($this->optimLock) { - if (isset($data[$this->optimLock]) && isset($data[$this->getPk()])) { - // 只有当存在乐观锁字段和主键有值的时候才记录乐观锁 - $_SESSION[$this->name . '_' . $data[$this->getPk()] . '_lock_version'] = $data[$this->optimLock]; - } - } - } - - /** - * 检查乐观锁 - * @access protected - * @param inteter $id 当前主键 - * @param array $data 当前数据 - * @return mixed - */ - protected function checkLockVersion($id, &$data) - { - // 检查乐观锁 - $identify = $this->name . '_' . $id . '_lock_version'; - if ($this->optimLock && isset($_SESSION[$identify])) { - $lock_version = $_SESSION[$identify]; - $vo = $this->field($this->optimLock)->find($id); - $_SESSION[$identify] = $lock_version; - $curr_version = $vo[$this->optimLock]; - if (isset($curr_version)) { - if ($curr_version > 0 && $lock_version != $curr_version) { - // 记录已经更新 - $this->error = 'record has update'; - return false; - } else { - // 更新乐观锁 - $save_version = $data[$this->optimLock]; - if ($save_version != $lock_version + 1) { - $data[$this->optimLock] = $lock_version + 1; - } - $_SESSION[$identify] = $lock_version + 1; - } - } - } - return true; - } - - /** - * 查找前N个记录 - * @access public - * @param integer $count 记录个数 - * @param array $options 查询表达式 - * @return array - */ - public function topN($count, $options = []) - { - $options['limit'] = $count; - return $this->select($options); - } - - /** - * 查询符合条件的第N条记录 - * 0 表示第一条记录 -1 表示最后一条记录 - * @access public - * @param integer $position 记录位置 - * @param array $options 查询表达式 - * @return mixed - */ - public function getN($position = 0, $options = []) - { - if ($position >= 0) { - // 正向查找 - $options['limit'] = $position . ',1'; - $list = $this->select($options); - return $list ? $list[0] : false; - } else { - // 逆序查找 - $list = $this->select($options); - return $list ? $list[count($list) - abs($position)] : false; - } - } - - /** - * 获取满足条件的第一条记录 - * @access public - * @param array $options 查询表达式 - * @return mixed - */ - public function first($options = []) - { - return $this->getN(0, $options); - } - - /** - * 获取满足条件的最后一条记录 - * @access public - * @param array $options 查询表达式 - * @return mixed - */ - public function last($options = []) - { - return $this->getN(-1, $options); - } - - /** - * 返回数据 - * @access public - * @param array $data 数据 - * @param string $type 返回类型 默认为数组 - * @return mixed - */ - public function returnResult($data, $type = 'array') - { - - switch ($type) { - case 'array': - return $data; - case 'object': - return (object) $data; - default: // 允许用户自定义返回类型 - if (class_exists($type)) { - return new $type($data); - } else { - throw new \think\Exception(' class not exist :' . $type); - } - } - } - - /** - * 返回数据列表 - * @access protected - * @param array $resultSet 数据 - * @param string $type 返回类型 默认为数组 - * @return void - */ - protected function returnResultSet(&$resultSet, $type = '') - { - foreach ($resultSet as $key => $data) { - $resultSet[$key] = $this->returnResult($data, $type); - } - return $resultSet; - } - - /** - * 检查序列化数据字段 - * @access protected - * @param array $data 数据 - * @return array - */ - protected function serializeField(&$data) - { - // 检查序列化字段 - if (!empty($this->serializeField)) { - // 定义方式 $this->serializeField = ['ser'=>['name','email']]; - foreach ($this->serializeField as $key => $val) { - if (empty($data[$key])) { - $serialize = []; - foreach ($val as $name) { - if (isset($data[$name])) { - $serialize[$name] = $data[$name]; - unset($data[$name]); - } - } - if (!empty($serialize)) { - $data[$key] = serialize($serialize); - } - } - } - } - return $data; - } - - // 检查返回数据的序列化字段 - protected function checkSerializeField(&$result) - { - // 检查序列化字段 - if (!empty($this->serializeField)) { - foreach ($this->serializeField as $key => $val) { - if (isset($result[$key])) { - $serialize = unserialize($result[$key]); - foreach ($serialize as $name => $value) { - $result[$name] = $value; - } - - unset($serialize, $result[$key]); - } - } - } - return $result; - } - - // 检查数据集的序列化字段 - protected function checkListSerializeField(&$resultSet) - { - // 检查序列化字段 - if (!empty($this->serializeField)) { - foreach ($this->serializeField as $key => $val) { - foreach ($resultSet as $k => $result) { - if (isset($result[$key])) { - $serialize = unserialize($result[$key]); - foreach ($serialize as $name => $value) { - $result[$name] = $value; - } - - unset($serialize, $result[$key]); - $resultSet[$k] = $result; - } - } - } - } - return $resultSet; - } - - /** - * 检查只读字段 - * @access protected - * @param array $data 数据 - * @return array - */ - protected function checkReadonlyField(&$data) - { - if (!empty($this->readonlyField)) { - foreach ($this->readonlyField as $key => $field) { - if (isset($data[$field])) { - unset($data[$field]); - } - } - } - return $data; - } - - /** - * 得到分表的的数据表名 - * @access public - * @param array $data 操作的数据 - * @return string - */ - public function getPartitionTableName($data = []) - { - // 对数据表进行分区 - if (isset($data[$this->partition['field']])) { - $field = $data[$this->partition['field']]; - switch ($this->partition['type']) { - case 'id': - // 按照id范围分表 - $step = $this->partition['expr']; - $seq = floor($field / $step) + 1; - break; - case 'year': - // 按照年份分表 - if (!is_numeric($field)) { - $field = strtotime($field); - } - $seq = date('Y', $field) - $this->partition['expr'] + 1; - break; - case 'mod': - // 按照id的模数分表 - $seq = ($field % $this->partition['num']) + 1; - break; - case 'md5': - // 按照md5的序列分表 - $seq = (ord(substr(md5($field), 0, 1)) % $this->partition['num']) + 1; - break; - default: - if (function_exists($this->partition['type'])) { - // 支持指定函数哈希 - $fun = $this->partition['type']; - $seq = (ord(substr($fun($field), 0, 1)) % $this->partition['num']) + 1; - } else { - // 按照字段的首字母的值分表 - $seq = (ord($field{0}) % $this->partition['num']) + 1; - } - } - return $this->getTableName() . '_' . $seq; - } else { - // 当设置的分表字段不在查询条件或者数据中 - // 进行联合查询,必须设定 partition['num'] - $tableName = []; - for ($i = 0; $i < $this->partition['num']; $i++) { - $tableName[] = 'SELECT * FROM ' . $this->getTableName() . '_' . ($i + 1); - } - return '( ' . implode(" UNION ", $tableName) . ') AS ' . $this->name; - } - } -} diff --git a/thinkphp/library/traits/model/Auto.php b/thinkphp/library/traits/model/Auto.php deleted file mode 100644 index 3c0558c62..000000000 --- a/thinkphp/library/traits/model/Auto.php +++ /dev/null @@ -1,491 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace traits\model; - -use think\Lang; - -trait Auto -{ - //protected $validate = []; // 自动验证定义 - //protected $auto = []; // 自动完成定义 - - /** - * 创建数据对象 但不保存到数据库 - * @access public - * @param mixed $data 创建数据 - * @param string $type 状态 - * @return mixed - */ - public function create($data = '', $type = '') - { - // 如果没有传值默认取POST数据 - if (empty($data)) { - $data = \think\Input::post(); - } elseif (is_object($data)) { - $data = get_object_vars($data); - } - // 验证数据 - if (empty($data) || !is_array($data)) { - $this->error = Lang::get('_DATA_TYPE_INVALID_'); - return false; - } - - // 状态 - $type = $type ? $type : (!empty($data[$this->getPk()]) ? self::MODEL_UPDATE : self::MODEL_INSERT); - $type = 1 << ($type - 1); - // 字段列表 - $keys = array_keys($data); - - // 检测提交字段的合法性 - if (isset($this->options['field'])) { - // $this->field('field1,field2...')->create() - $fields = $this->options['field']; - unset($this->options['field']); - } elseif (self::MODEL_INSERT == $type && isset($this->insertFields)) { - $fields = $this->insertFields; - } elseif (self::MODEL_UPDATE == $type && isset($this->updateFields)) { - $fields = $this->updateFields; - } - if (isset($fields)) { - if (is_string($fields)) { - $fields = explode(',', $fields); - } - // 判断令牌验证字段 - if (Config::get('token_on')) { - $fields[] = Config::get('token_name'); - } - - foreach ($keys as $i => $key) { - if (!in_array($key, $fields)) { - unset($keys[$i]); - unset($data[$key]); - } - } - } - - // 数据自动验证 - if (!$this->autoValidation($data, $type)) { - return false; - } - - // 验证完成生成数据对象 - if ($this->autoCheckFields && empty($this->options['link'])) { - // 开启字段检测并且没有关联表 则过滤非法字段数据 - $fields = $this->getDbFields(); - foreach ($keys as $i => $key) { - if (!in_array($key, $fields)) { - unset($data[$key]); - } - } - } - - // 创建完成对数据进行自动处理 - $this->autoOperation($data, $type); - // 验证后的回调方法 - $this->_after_create($data, $this->options); - // 赋值当前数据对象 - $this->data = $data; - // 返回创建的数据以供其他调用 - return $data; - } - - // 创建数据对象后的回调方法 - protected function _after_create(&$data, $options) - { - } - - /** - * 使用正则验证数据 - * @access public - * @param string $value 要验证的数据 - * @param string $rule 验证规则 - * @return boolean - */ - public function regex($value, $rule) - { - static $validate = [ - 'require' => '/.+/', - 'email' => '/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/', - 'url' => '/^http(s?):\/\/(?:[A-za-z0-9-]+\.)+[A-za-z]{2,4}(?:[\/\?#][\/=\?%\-&~`@[\]\':+!\.#\w]*)?$/', - 'currency' => '/^\d+(\.\d+)?$/', - 'number' => '/^\d+$/', - 'zip' => '/^\d{6}$/', - 'integer' => '/^[-\+]?\d+$/', - 'double' => '/^[-\+]?\d+(\.\d+)?$/', - 'english' => '/^[A-Za-z]+$/', - ]; - // 检查是否有内置的正则表达式 - if (isset($validate[strtolower($rule)])) { - $rule = $validate[strtolower($rule)]; - } - return preg_match($rule, $value) === 1; - } - - /** - * 自动表单处理 - * @access public - * @param array $data 创建数据 - * @param string $type 创建类型 - * @return mixed - */ - private function autoOperation(&$data, $type) - { - if (isset($this->options['auto'])) { - if (false === $this->options['auto']) { - // 关闭自动完成 - return; - } else { - $_auto = $this->options['auto']; - unset($this->options['auto']); - if (empty($_auto) && !empty($this->auto)) { - $_auto = $this->auto; - } - } - } elseif (!empty($this->auto)) { - $_auto = $this->auto; - } - // 自动填充 - if (!empty($_auto)) { - foreach ($_auto as $key => $val) { - if (!is_numeric($key) && is_array(current($val)) && isset($data[$key])) { - foreach ($val as $k => $v) { - $this->_operationField($data[$key], $v, $type); - } - } else { - $this->_operationField($data, $val, $type); - } - } - } - return; - } - - /** - * 填充表单字段 - * @access private - * @param array $data 创建数据 - * @param array $auto 填充因子 - * @param string $type 创建类型 - * @return boolean - */ - private function _operationField(&$data, &$auto, $type) - { - // 填充因子定义格式 - // array('field','填充内容','填充时间','附加规则',[额外参数]) - if (empty($auto[2])) { - $flags = 1 << (self::MODEL_INSERT - 1); - } elseif (is_array($auto[2])) { - $flags = 0; - foreach ($auto[2] as $v) { - $flags = $flags | 1 << ($v - 1); - } - } else { - $flags = 3 == $auto[2] ? 3 : 1 << ($auto[2] - 1); - } - // 检查填充条件 - if ($flags & $type) { - switch (trim($auto[3])) { - case 'function': // 使用函数进行填充 字段的值作为参数 - case 'callback': // 使用回调方法 - $args = isset($auto[4]) ? (array)$auto[4] : []; - if (is_string($auto[0]) && strpos($auto[0], ',')) { - $auto[0] = explode(',', $auto[0]); - } - if (is_array($auto[0])) { - // 支持多个字段验证 - foreach ($auto[0] as $field) { - $_data[$field] = isset($data[$field]) ? $data[$field] : null; - } - array_unshift($args, $_data); - } else { - array_unshift($args, isset($data[$auto[0]]) ? $data[$auto[0]] : null); - } - if ('function' == $auto[3]) { - $data[$auto[0]] = call_user_func_array($auto[1], $args); - } else { - $data[$auto[0]] = call_user_func_array([& $this, $auto[1]], $args); - } - break; - case 'field': // 用其它字段的值进行填充 - $data[$auto[0]] = $data[$auto[1]]; - break; - case 'ignore': // 为空忽略 - if ($auto[1] === $data[$auto[0]]) { - unset($data[$auto[0]]); - } - break; - case 'string': - default: // 默认作为字符串填充 - $data[$auto[0]] = $auto[1]; - } - if (isset($data[$auto[0]]) && false === $data[$auto[0]]) { - unset($data[$auto[0]]); - } - } - } - - /** - * 自动表单验证 - * @access protected - * @param array $data 创建数据 - * @param string $type 创建类型 - * @return boolean - */ - protected function autoValidation(&$data, $type) - { - if (isset($this->options['validate'])) { - if (false === $this->options['validate']) { - // 关闭自动验证 - return true; - } else { - $_validate = $this->options['validate']; - unset($this->options['validate']); - if (empty($_validate) && !empty($this->validate)) { - $_validate = $this->validate; - } - } - } elseif (!empty($this->validate)) { - $_validate = $this->validate; - } - // 属性验证 - if (!empty($_validate)) { - // 如果设置了数据自动验证则进行数据验证 - if ($this->patchValidate) { - // 重置验证错误信息 - $this->error = []; - } - foreach ($_validate as $key => $val) { - if (!is_numeric($key) && is_array(current($val)) && isset($data[$key])) { - foreach ($val as $k => $v) { - if (false === $this->_validationField($data[$key], $v, $type)) { - return false; - } - } - } else { - if (false === $this->_validationField($data, $val, $type)) { - return false; - } - } - } - // 批量验证的时候最后返回错误 - if (!empty($this->error)) { - return false; - } - } - return true; - } - - /** - * 验证表单字段 支持批量验证 - * 如果批量验证返回错误的数组信息 - * @access protected - * @param array $data 创建数据 - * @param array $val 验证因子 - * @param string $type 创建类型 - * @return boolean - */ - protected function _validationField(&$data, &$val, $type) - { - // 如果是批量验证,并且当前字段已经有规则验证没有通过则跳过 - if ($this->patchValidate && isset($this->error[$val[0]])) { - return true; - } - // 验证因子定义格式 - // [field,rule,message,condition,type,when,params] - if (empty($val[5])) { - $flags = 1 << (self::MODEL_BOTH - 1); - } elseif (is_array($val[5])) { - $flags = 0; - foreach ($val[5] as $v) { - $flags = $flags | 1 << ($v - 1); - } - } else { - $flags = 3 == $val[5] ? 3 : 1 << ($val[5] - 1); - } - // 判断是否需要执行验证 - if ($flags & $type) { - if (0 == strpos($val[2], '{%') && strpos($val[2], '}')) { - // 支持提示信息的多语言 使用 {%语言定义} 方式 - $val[2] = Lang::get(substr($val[2], 2, -1)); - } - $val[3] = isset($val[3]) ? $val[3] : self::EXISTS_VALIDATE; - $val[4] = isset($val[4]) ? $val[4] : 'regex'; - $status = true; - // 判断验证条件 - switch ($val[3]) { - case self::MUST_VALIDATE: // 必须验证 不管表单是否有设置该字段 - $status = $this->_validationFieldItem($data, $val); - break; - case self::VALUE_VALIDATE: // 值不为空的时候才验证 - if ('' != trim($data[$val[0]])) { - $status = $this->_validationFieldItem($data, $val); - } - break; - default: // 默认表单存在该字段就验证 - if (isset($data[$val[0]])) { - $status = $this->_validationFieldItem($data, $val); - } - } - if (false === $status) { - if ($this->patchValidate) { - $this->error[$val[0]] = $val[2]; - } else { - $this->error = $val[2]; - return false; - } - } - } - return true; - } - - /** - * 根据验证因子验证字段 - * @access protected - * @param array $data 创建数据 - * @param array $val 验证因子 - * @return boolean - */ - protected function _validationFieldItem($data, $val) - { - switch (strtolower(trim($val[4]))) { - case 'function': // 使用函数进行验证 - case 'callback': // 调用方法进行验证 - $args = isset($val[6]) ? (array)$val[6] : []; - if (is_string($val[0]) && strpos($val[0], ',')) { - $val[0] = explode(',', $val[0]); - } - if (is_array($val[0])) { - // 支持多个字段验证 - foreach ($val[0] as $field) { - $_data[$field] = isset($data[$field]) ? $data[$field] : null; - } - array_unshift($args, $_data); - } else { - array_unshift($args, isset($data[$val[0]]) ? $data[$val[0]] : null); - } - return call_user_func_array('function' == $val[4] ? $val[1] : [& $this, $val[1]], $args); - case 'confirm': // 验证两个字段是否相同 - return $data[$val[0]] == $data[$val[1]]; - case 'unique': // 验证某个值是否唯一 - if (is_string($val[0])) { - $val[0] = explode(',', $val[0]); - } - $map = []; - if (is_array($val[0])) { - // 支持多个字段验证 - foreach ($val[0] as $field) { - if (!isset($data[$field])) { - return false; - } - $map[$field] = $data[$field]; - } - } - $pk = $this->getPk(); - if (!empty($data[$pk]) && is_string($pk)) { - // 完善编辑的时候验证唯一 - $map[$pk] = ['neq', $data[$pk]]; - } - $options = $this->options; - if ($this->where($map)->find()) { - return false; - } - $this->options = $options; - return true; - default: // 检查附加规则 - return $this->check($data[$val[0]], $val[1], $val[4]); - } - } - - /** - * 验证数据 支持 in between equal length regex expire ip_allow ip_deny - * @access public - * @param string $value 验证数据 - * @param mixed $rule 验证表达式 - * @param string $type 验证方式 默认为正则验证 - * @return boolean - */ - public function check($value, $rule, $type = 'regex') - { - $type = strtolower(trim($type)); - switch ($type) { - case 'in': // 验证是否在某个指定范围之内 逗号分隔字符串或者数组 - case 'notin': - $range = is_array($rule) ? $rule : explode(',', $rule); - return 'in' == $type ? in_array($value, $range) : !in_array($value, $range); - case 'between': // 验证是否在某个范围 - case 'notbetween': // 验证是否不在某个范围 - if (is_array($rule)) { - $min = $rule[0]; - $max = $rule[1]; - } else { - list($min, $max) = explode(',', $rule); - } - return 'between' == $type ? $value >= $min && $value <= $max : $value < $min || $value > $max; - case 'equal': // 验证是否等于某个值 - case 'notequal': // 验证是否等于某个值 - return 'equal' == $type ? $value == $rule : $value != $rule; - case 'length': // 验证长度 - $length = mb_strlen($value, 'utf-8'); // 当前数据长度 - if (strpos($rule, ',')) { - // 长度区间 - list($min, $max) = explode(',', $rule); - return $length >= $min && $length <= $max; - } else { - // 指定长度 - return $length == $rule; - } - case 'expire': - list($start, $end) = explode(',', $rule); - if (!is_numeric($start)) { - $start = strtotime($start); - } - if (!is_numeric($end)) { - $end = strtotime($end); - } - return NOW_TIME >= $start && NOW_TIME <= $end; - case 'ip_allow': // IP 操作许可验证 - return in_array($_SERVER['REMOTE_ADDR'], explode(',', $rule)); - case 'ip_deny': // IP 操作禁止验证 - return !in_array($_SERVER['REMOTE_ADDR'], explode(',', $rule)); - case 'filter': // 使用filter_var验证 - $result = filter_var($value, is_int($rule) ? $rule : filter_id($rule)); - return false === $result ? false : true; - case 'regex': - default: // 默认使用正则验证 可以使用验证类中定义的验证名称 - // 检查附加规则 - return $this->regex($value, $rule); - } - } - - /** - * 指定自动完成 - * @access public - * @param array $auto 自动完成设置 - * @return Model - */ - public function auto($auto) - { - $this->options['auto'] = $auto; - return $this; - } - - /** - * 指定自动验证 - * @access public - * @param array $validate 自动验证设置 - * @return Model - */ - public function validate($validate) - { - $this->options['validate'] = $validate; - return $this; - } -} diff --git a/thinkphp/library/traits/model/Relation.php b/thinkphp/library/traits/model/Relation.php deleted file mode 100644 index ba6cf3fb3..000000000 --- a/thinkphp/library/traits/model/Relation.php +++ /dev/null @@ -1,445 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace traits\model; - -define('HAS_ONE', 1); -define('BELONGS_TO', 2); -define('HAS_MANY', 3); -define('MANY_TO_MANY', 4); - -trait Relation -{ - // 关联定义 - //protected $link = []; - - /** - * 得到关联的数据表名 - * @access public - * @return string - */ - public function getRelationTableName($relation) - { - $relationTable = !empty($this->tablePrefix) ? $this->tablePrefix : ''; - $relationTable .= $this->tableName ? $this->tableName : $this->name; - $relationTable .= '_' . $relation->getModelName(); - return strtolower($relationTable); - } - - // 查询成功后的回调方法 - protected function _after_find(&$result, $options = []) - { - // 获取关联数据 并附加到结果中 - if (!empty($options['link'])) { - $this->getRelation($result, $options['link']); - } - - } - - // 查询数据集成功后的回调方法 - protected function _after_select(&$result, $options = []) - { - // 获取关联数据 并附加到结果中 - if (!empty($options['link'])) { - $this->getRelations($result, $options['link']); - } - - } - - // 写入成功后的回调方法 - protected function _after_insert($data, $options = []) - { - // 关联写入 - if (!empty($options['link'])) { - $this->opRelation('ADD', $data, $options['link']); - } - - } - - // 更新成功后的回调方法 - protected function _after_update($data, $options = []) - { - // 关联更新 - if (!empty($options['link'])) { - $this->opRelation('SAVE', $data, $options['link']); - } - - } - - // 删除成功后的回调方法 - protected function _after_delete($data, $options = []) - { - // 关联删除 - if (!empty($options['link'])) { - $this->opRelation('DEL', $data, $options['link']); - } - - } - - // 表单验证成功后的回调方法 - protected function _after_create(&$data, $options = []) - { - // 获取关联数据 并附加到结果中 - if (!empty($options['link'])) { - $this->crRelation($data, $options['link']); - } - } - - /** - * 对保存到数据库的数据进行处理 - * @access protected - * @param mixed $data 要操作的数据 - * @return boolean - */ - protected function _write_data($data) - { - $this->_before_write($data); - return $data; - } - - /** - * 获取返回数据集的关联记录 - * @access protected - * @param array $resultSet 返回数据 - * @param string|array $name 关联名称 - * @return array - */ - protected function getRelations(&$resultSet, $name = '') - { - // 获取记录集的主键列表 - foreach ($resultSet as $key => $val) { - $val = $this->getRelation($val, $name); - $resultSet[$key] = $val; - } - return $resultSet; - } - - /** - * 获取返回数据的关联记录 - * @access protected - * @param mixed $result 返回数据 - * @param string|array $name 关联名称 - * @param boolean $return 是否返回关联数据本身 - * @return array - */ - protected function getRelation(&$result, $name = '', $return = false) - { - if (!empty($this->link)) { - foreach ($this->link as $key => $val) { - $mappingName = !empty($val['mapping_name']) ? $val['mapping_name'] : $key; // 映射名称 - if (empty($name) || true === $name || $mappingName == $name || (is_array($name) && in_array($mappingName, $name))) { - $mappingType = !empty($val['mapping_type']) ? $val['mapping_type'] : $val; // 关联类型 - $mappingClass = !empty($val['class_name']) ? $val['class_name'] : $key; // 关联类名 - $mappingFields = !empty($val['mapping_fields']) ? $val['mapping_fields'] : '*'; // 映射字段 - $mappingCondition = !empty($val['condition']) ? $val['condition'] : '1=1'; // 关联条件 - $mappingKey = !empty($val['mapping_key']) ? $val['mapping_key'] : $this->getPk(); // 关联键名 - if (strtoupper($mappingClass) == strtoupper($this->name)) { - // 自引用关联 获取父键名 - $mappingFk = !empty($val['parent_key']) ? $val['parent_key'] : 'parent_id'; - } else { - $mappingFk = !empty($val['foreign_key']) ? $val['foreign_key'] : strtolower($this->name) . '_id'; // 关联外键 - } - // 获取关联模型对象 - $model = D($mappingClass); - switch ($mappingType) { - case HAS_ONE: - $pk = $result[$mappingKey]; - $mappingCondition .= " AND {$mappingFk}='{$pk}'"; - $relationData = $model->where($mappingCondition)->field($mappingFields)->find(); - break; - case BELONGS_TO: - if (strtoupper($mappingClass) == strtoupper($this->name)) { - // 自引用关联 获取父键名 - $mappingFk = !empty($val['parent_key']) ? $val['parent_key'] : 'parent_id'; - } else { - $mappingFk = !empty($val['foreign_key']) ? $val['foreign_key'] : strtolower($model->getModelName()) . '_id'; // 关联外键 - } - $fk = $result[$mappingFk]; - $mappingCondition .= " AND {$model->getPk()}='{$fk}'"; - $relationData = $model->where($mappingCondition)->field($mappingFields)->find(); - break; - case HAS_MANY: - $pk = $result[$mappingKey]; - $mappingCondition .= " AND {$mappingFk}='{$pk}'"; - $mappingOrder = !empty($val['mapping_order']) ? $val['mapping_order'] : ''; - $mappingLimit = !empty($val['mapping_limit']) ? $val['mapping_limit'] : ''; - // 延时获取关联记录 - $relationData = $model->where($mappingCondition)->field($mappingFields)->order($mappingOrder)->limit($mappingLimit)->select(); - break; - case MANY_TO_MANY: - $pk = $result[$mappingKey]; - $mappingCondition = " {$mappingFk}='{$pk}'"; - $mappingOrder = $val['mapping_order']; - $mappingLimit = $val['mapping_limit']; - $mappingRelationFk = $val['relation_foreign_key'] ? $val['relation_foreign_key'] : $model->getModelName() . '_id'; - $mappingRelationTable = $val['relation_table'] ? $val['relation_table'] : $this->getRelationTableName($model); - $sql = "SELECT b.{$mappingFields} FROM {$mappingRelationTable} AS a, " . $model->getTableName() . " AS b WHERE a.{$mappingRelationFk} = b.{$model->getPk()} AND a.{$mappingCondition}"; - if (!empty($val['condition'])) { - $sql .= ' AND ' . $val['condition']; - } - if (!empty($mappingOrder)) { - $sql .= ' ORDER BY ' . $mappingOrder; - } - if (!empty($mappingLimit)) { - $sql .= ' LIMIT ' . $mappingLimit; - } - $relationData = $this->query($sql); - break; - } - if (!$return) { - if (isset($val['as_fields']) && in_array($mappingType, [HAS_ONE, BELONGS_TO])) { - // 支持直接把关联的字段值映射成数据对象中的某个字段 - // 仅仅支持HAS_ONE BELONGS_TO - $fields = explode(',', $val['as_fields']); - foreach ($fields as $field) { - if (strpos($field, ':')) { - list($relationName, $nick) = explode(':', $field); - $result[$nick] = $relationData[$relationName]; - } else { - $result[$field] = $relationData[$field]; - } - } - } else { - $result[$mappingName] = $relationData; - } - unset($relationData); - } else { - return $relationData; - } - } - } - } - return $result; - } - - /** - * 操作关联数据 - * @access protected - * @param string $opType 操作方式 ADD SAVE DEL - * @param mixed $data 数据对象 - * @param string $name 关联名称 - * @return mixed - */ - protected function opRelation($opType, $data = '', $name = '') - { - $result = false; - if (empty($data) && !empty($this->data)) { - $data = $this->data; - } elseif (!is_array($data)) { - // 数据无效返回 - return false; - } - if (!empty($this->link)) { - // 遍历关联定义 - foreach ($this->link as $key => $val) { - // 操作制定关联类型 - $mappingName = $val['mapping_name'] ? $val['mapping_name'] : $key; // 映射名称 - if (empty($name) || true === $name || $mappingName == $name || (is_array($name) && in_array($mappingName, $name))) { - // 操作制定的关联 - $mappingType = !empty($val['mapping_type']) ? $val['mapping_type'] : $val; // 关联类型 - $mappingClass = !empty($val['class_name']) ? $val['class_name'] : $key; // 关联类名 - $mappingKey = !empty($val['mapping_key']) ? $val['mapping_key'] : $this->getPk(); // 关联键名 - // 当前数据对象主键值 - $pk = $data[$mappingKey]; - if (strtoupper($mappingClass) == strtoupper($this->name)) { - // 自引用关联 获取父键名 - $mappingFk = !empty($val['parent_key']) ? $val['parent_key'] : 'parent_id'; - } else { - $mappingFk = !empty($val['foreign_key']) ? $val['foreign_key'] : strtolower($this->name) . '_id'; // 关联外键 - } - if (!empty($val['condition'])) { - $mappingCondition = $val['condition']; - } else { - $mappingCondition = []; - $mappingCondition[$mappingFk] = $pk; - } - // 获取关联model对象 - $model = D($mappingClass); - $mappingData = isset($data[$mappingName]) ? $data[$mappingName] : false; - if (!empty($mappingData) || 'DEL' == $opType) { - switch ($mappingType) { - case HAS_ONE: - switch (strtoupper($opType)) { - case 'ADD': // 增加关联数据 - $mappingData[$mappingFk] = $pk; - $result = $model->add($mappingData); - break; - case 'SAVE': // 更新关联数据 - $result = $model->where($mappingCondition)->save($mappingData); - break; - case 'DEL': // 根据外键删除关联数据 - $result = $model->where($mappingCondition)->delete(); - break; - } - break; - case BELONGS_TO: - break; - case HAS_MANY: - switch (strtoupper($opType)) { - case 'ADD': // 增加关联数据 - $model->startTrans(); - foreach ($mappingData as $val) { - $val[$mappingFk] = $pk; - $result = $model->add($val); - } - $model->commit(); - break; - case 'SAVE': // 更新关联数据 - $model->startTrans(); - $pk = $model->getPk(); - foreach ($mappingData as $vo) { - if (isset($vo[$pk])) { - // 更新数据 - $mappingCondition = "$pk ={$vo[$pk]}"; - $result = $model->where($mappingCondition)->save($vo); - } else { - // 新增数据 - $vo[$mappingFk] = $data[$mappingKey]; - $result = $model->add($vo); - } - } - $model->commit(); - break; - case 'DEL': // 删除关联数据 - $result = $model->where($mappingCondition)->delete(); - break; - } - break; - case MANY_TO_MANY: - $mappingRelationFk = $val['relation_foreign_key'] ? $val['relation_foreign_key'] : $model->getModelName() . '_id'; // 关联 - $mappingRelationTable = $val['relation_table'] ? $val['relation_table'] : $this->getRelationTableName($model); - if (is_array($mappingData)) { - $ids = []; - foreach ($mappingData as $vo) { - $ids[] = $vo[$mappingKey]; - } - - $relationId = implode(',', $ids); - } - switch (strtoupper($opType)) { - case 'ADD': // 增加关联数据 - case 'SAVE': // 更新关联数据 - if (isset($relationId)) { - $this->startTrans(); - // 删除关联表数据 - $this->table($mappingRelationTable)->where($mappingCondition)->delete(); - // 插入关联表数据 - $sql = 'INSERT INTO ' . $mappingRelationTable . ' (' . $mappingFk . ',' . $mappingRelationFk . ') SELECT a.' . $this->getPk() . ',b.' . $model->getPk() . ' FROM ' . $this->getTableName() . ' AS a ,' . $model->getTableName() . " AS b where a." . $this->getPk() . ' =' . $pk . ' AND b.' . $model->getPk() . ' IN (' . $relationId . ") "; - $result = $model->execute($sql); - if (false !== $result) - // 提交事务 - { - $this->commit(); - } else - // 事务回滚 - { - $this->rollback(); - } - - } - break; - case 'DEL': // 根据外键删除中间表关联数据 - $result = $this->table($mappingRelationTable)->where($mappingCondition)->delete(); - break; - } - break; - } - } - } - } - } - return $result; - } - - /** - * 关联数据验证 - * @access protected - * @param mixed $data 数据对象 - * @param string $name 关联名称 - * @return mixed - */ - protected function crRelation(&$data, $name = '') - { - if (empty($data) && !empty($this->data)) { - $data = $this->data; - } elseif(!is_array($data)) { - // 数据无效返回 - return false; - } - if (!empty($this->_link)) { - $fields = $this->getDbFields(); - // 遍历关联定义 - foreach ($this->_link as $key => $val) { - // 操作制定关联类型 - $mappingName = !empty($val['mapping_name']) ? $val['mapping_name'] : $key; // 映射名称 - if (empty($name) || true === $name || $mappingName == $name || (is_array($name) && in_array($mappingName,$name)) ) { - // 操作制定的关联 - $mappingType = !empty($val['mapping_type']) ? $val['mapping_type'] : $val; // 关联类型 - $mappingClass = !empty($val['class_name']) ? $val['class_name'] : $key; // 关联类名 - $mappingKey =!empty($val['mapping_key']) ? $val['mapping_key'] : $this->getPk(); // 关联键名 - if (strtoupper($mappingClass) == strtoupper($this->name) || !isset($data[$mappingName])) { - continue; // 自引用关联或提交关联数据跳过 - } - // 获取关联model对象 - $model = D($mappingClass); - $_data = $data[$mappingName]; - unset($data[$key]); - if ($_data = $model->token(false)->create($_data)) { - $data[$mappingName] = $_data; - $fields[] = $mappingName; - } else { - $error = $model->getError(); - if ($this->patchValidate) { - $this->error[$mappingName] = $error; - } else { - $this->error = $error; - return false; - } - } - } - } - - // 过滤非法字段数据 - $diff = array_diff(array_keys($data), $fields); - foreach ($diff as $key) { - unset($data[$key]); - } - } - } - - /** - * 进行关联查询 - * @access public - * @param mixed $name 关联名称 - * @return Model - */ - public function relation($name) - { - $this->options['link'] = $name; - $this->autoCheckFields = false; - return $this; - } - - /** - * 关联数据获取 仅用于查询后 - * @access public - * @param string $name 关联名称 - * @return array - */ - public function relationGet($name) - { - if (empty($this->data)) { - return false; - } - - return $this->getRelation($this->data, $name, true); - } -} diff --git a/thinkphp/library/traits/model/Transaction.php b/thinkphp/library/traits/model/Transaction.php deleted file mode 100644 index 8e9533bb2..000000000 --- a/thinkphp/library/traits/model/Transaction.php +++ /dev/null @@ -1,80 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace traits\model; - -trait Transaction -{ - - /** - * 启动事务 - * @access public - * @return void - */ - public function startTrans() - { - $this->commit(); - $this->db->startTrans(); - return; - } - - /** - * 提交事务 - * @access public - * @return boolean - */ - public function commit() - { - return $this->db->commit(); - } - - /** - * 事务回滚 - * @access public - * @return boolean - */ - public function rollback() - { - return $this->db->rollback(); - } - - /** - * 批处理执行SQL语句 - * 批处理的指令都认为是execute操作 - * @access public - * @param array $sql SQL批处理指令 - * @return boolean - */ - public function patchQuery($sql = []) - { - if (!is_array($sql)) { - return false; - } - // 自动启动事务支持 - $this->startTrans(); - try { - foreach ($sql as $_sql) { - $result = $this->execute($_sql); - if (false === $result) { - // 发生错误自动回滚事务 - $this->rollback(); - return false; - } - } - // 提交事务 - $this->commit(); - } catch (\think\exception $e) { - $this->rollback(); - return false; - } - return true; - } -} diff --git a/thinkphp/library/traits/model/View.php b/thinkphp/library/traits/model/View.php deleted file mode 100644 index 2a8b3d080..000000000 --- a/thinkphp/library/traits/model/View.php +++ /dev/null @@ -1,256 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace traits\model; - -trait View -{ - - protected $viewFields = []; - - /** - * 自动检测数据表信息 - * @access protected - * @return void - */ - protected function _checkTableInfo() - {} - - /** - * 得到完整的数据表名 - * @access public - * @return string - */ - public function getTableName() - { - if (empty($this->trueTableName)) { - $tableName = ''; - foreach ($this->viewFields as $key => $view) { - // 获取数据表名称 - if (isset($view['_table'])) { - // 2011/10/17 添加实际表名定义支持 可以实现同一个表的视图 - $tableName .= $view['_table']; - } else { - $class = $key . 'Model'; - $model = class_exists($class) ? new $class() : M($key); - $tableName .= $model->getTableName(); - } - // 表别名定义 - $tableName .= !empty($view['_as']) ? ' ' . $view['_as'] : ' ' . $key; - // 支持ON 条件定义 - $tableName .= !empty($view['_on']) ? ' ON ' . $view['_on'] : ''; - // 指定JOIN类型 例如 RIGHT INNER LEFT 下一个表有效 - $type = !empty($view['_type']) ? $view['_type'] : ''; - $tableName .= ' ' . strtoupper($type) . ' JOIN '; - $len = strlen($type . '_JOIN '); - } - $tableName = substr($tableName, 0, -$len); - $this->trueTableName = $tableName; - } - return $this->trueTableName; - } - - /** - * 表达式过滤方法 - * @access protected - * @param string $options 表达式 - * @return void - */ - protected function _options_filter(&$options) - { - if (isset($options['field'])) { - $options['field'] = $this->checkFields($options['field']); - } else { - $options['field'] = $this->checkFields(); - } - if (isset($options['group'])) { - $options['group'] = $this->checkGroup($options['group']); - } - if (isset($options['where'])) { - $options['where'] = $this->checkCondition($options['where']); - } - if (isset($options['order'])) { - $options['order'] = $this->checkOrder($options['order']); - } - } - - /** - * 检查是否定义了所有字段 - * @access protected - * @param string $name 模型名称 - * @param array $fields 字段数组 - * @return array - */ - private function _checkFields($name, $fields) - { - if (false !== $pos = array_search('*', $fields)) { - // 定义所有字段 - $fields = array_merge($fields, M($name)->getDbFields()); - unset($fields[$pos]); - } - return $fields; - } - - /** - * 检查条件中的视图字段 - * @access protected - * @param mixed $data 条件表达式 - * @return array - */ - protected function checkCondition($where) - { - if (is_array($where)) { - $view = []; - // 检查视图字段 - foreach ($this->viewFields as $key => $val) { - $k = isset($val['_as']) ? $val['_as'] : $key; - $val = $this->_checkFields($key, $val); - foreach ($where as $name => $value) { - if (false !== $field = array_search($name, $val, true)) { - // 存在视图字段 - $_key = is_numeric($field) ? $k . '.' . $name : $k . '.' . $field; - $view[$_key] = $value; - unset($where[$name]); - } - } - } - $where = array_merge($where, $view); - } - return $where; - } - - /** - * 检查Order表达式中的视图字段 - * @access protected - * @param string $order 字段 - * @return string - */ - protected function checkOrder($order = '') - { - if (is_string($order) && !empty($order)) { - $orders = explode(',', $order); - $_order = []; - foreach ($orders as $order) { - $array = explode(' ', $order); - $field = $array[0]; - $sort = isset($array[1]) ? $array[1] : 'ASC'; - // 解析成视图字段 - foreach ($this->viewFields as $name => $val) { - $k = isset($val['_as']) ? $val['_as'] : $name; - $val = $this->_checkFields($name, $val); - if (false !== $_field = array_search($field, $val, true)) { - // 存在视图字段 - $field = is_numeric($_field) ? $k . '.' . $field : $k . '.' . $_field; - break; - } - } - $_order[] = $field . ' ' . $sort; - } - $order = implode(',', $_order); - } - return $order; - } - - /** - * 检查Group表达式中的视图字段 - * @access protected - * @param string $group 字段 - * @return string - */ - protected function checkGroup($group = '') - { - if (!empty($group)) { - $groups = explode(',', $group); - $_group = []; - foreach ($groups as $field) { - // 解析成视图字段 - foreach ($this->viewFields as $name => $val) { - $k = isset($val['_as']) ? $val['_as'] : $name; - $val = $this->_checkFields($name, $val); - if (false !== $_field = array_search($field, $val, true)) { - // 存在视图字段 - $field = is_numeric($_field) ? $k . '.' . $field : $k . '.' . $_field; - break; - } - } - $_group[] = $field; - } - $group = implode(',', $_group); - } - return $group; - } - - /** - * 检查fields表达式中的视图字段 - * @access protected - * @param string $fields 字段 - * @return string - */ - protected function checkFields($fields = '') - { - if (empty($fields) || '*' == $fields) { - // 获取全部视图字段 - $fields = []; - foreach ($this->viewFields as $name => $val) { - $k = isset($val['_as']) ? $val['_as'] : $name; - $val = $this->_checkFields($name, $val); - foreach ($val as $key => $field) { - if (is_numeric($key)) { - $fields[] = $k . '.' . $field . ' AS ' . $field; - } elseif ('_' != substr($key, 0, 1)) { - // 以_开头的为特殊定义 - if (false !== strpos($key, '*') || false !== strpos($key, '(') || false !== strpos($key, '.')) { - //如果包含* 或者 使用了sql方法 则不再添加前面的表名 - $fields[] = $key . ' AS ' . $field; - } else { - $fields[] = $k . '.' . $key . ' AS ' . $field; - } - } - } - } - $fields = implode(',', $fields); - } else { - if (!is_array($fields)) { - $fields = explode(',', $fields); - } - // 解析成视图字段 - $array = []; - foreach ($fields as $key => $field) { - if (strpos($field, '(') || strpos(strtolower($field), ' as ')) { - // 使用了函数或者别名 - $array[] = $field; - unset($fields[$key]); - } - } - foreach ($this->viewFields as $name => $val) { - $k = isset($val['_as']) ? $val['_as'] : $name; - $val = $this->_checkFields($name, $val); - foreach ($fields as $key => $field) { - if (false !== $_field = array_search($field, $val, true)) { - // 存在视图字段 - if (is_numeric($_field)) { - $array[] = $k . '.' . $field . ' AS ' . $field; - } elseif ('_' != substr($_field, 0, 1)) { - if (false !== strpos($_field, '*') || false !== strpos($_field, '(') || false !== strpos($_field, '.')) { - //如果包含* 或者 使用了sql方法 则不再添加前面的表名 - $array[] = $_field . ' AS ' . $field; - } else { - $array[] = $k . '.' . $_field . ' AS ' . $field; - } - } - } - } - } - $fields = implode(',', $array); - } - return $fields; - } -} diff --git a/thinkphp/library/traits/think/Instance.php b/thinkphp/library/traits/think/Instance.php deleted file mode 100644 index 07aa45da2..000000000 --- a/thinkphp/library/traits/think/Instance.php +++ /dev/null @@ -1,40 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace traits\think; - -trait Instance -{ - protected static $instance = null; - - // 实例化(单例) - public static function instance($options = []) - { - if (is_null(self::$instance)) { - self::$instance = new self($options); - } - return self::$instance; - } - - // 静态调用 - public static function __callStatic($method, $params) - { - if (is_null(self::$instance)) { - self::$instance = new self(); - } - $call = substr($method, 1); - if (0 === strpos($method, '_') && is_callable([self::$instance, $call])) { - return call_user_func_array([self::$instance, $call], $params); - } else { - throw new \think\Exception("not exists method:" . $method); - } - } -} diff --git a/thinkphp/mode/common.php b/thinkphp/mode/common.php deleted file mode 100644 index 5f02d2d3c..000000000 --- a/thinkphp/mode/common.php +++ /dev/null @@ -1,50 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * ThinkPHP 普通模式定义 - */ - -return [ - // 配置文件 - 'config' => THINK_PATH . 'convention' . EXT, - - // 别名定义 - 'alias' => [ - 'think\App' => CORE_PATH . 'App' . EXT, - 'think\Build' => CORE_PATH . 'Build' . EXT, - 'think\Cache' => CORE_PATH . 'Cache' . EXT, - 'think\Config' => CORE_PATH . 'Config' . EXT, - 'think\Controller' => CORE_PATH . 'Controller' . EXT, - 'think\Cookie' => CORE_PATH . 'Cookie' . EXT, - 'think\Db' => CORE_PATH . 'Db' . EXT, - 'think\Debug' => CORE_PATH . 'Debug' . EXT, - 'think\Error' => CORE_PATH . 'Error' . EXT, - 'think\Exception' => CORE_PATH . 'Exception' . EXT, - 'think\Hook' => CORE_PATH . 'Hook' . EXT, - 'think\Input' => CORE_PATH . 'Input' . EXT, - 'think\Lang' => CORE_PATH . 'Lang' . EXT, - 'think\Log' => CORE_PATH . 'Log' . EXT, - 'think\Model' => CORE_PATH . 'Model' . EXT, - 'think\Response' => CORE_PATH . 'Response' . EXT, - 'think\Route' => CORE_PATH . 'Route' . EXT, - 'think\Session' => CORE_PATH . 'Session' . EXT, - 'think\Template' => CORE_PATH . 'Template' . EXT, - 'think\Url' => CORE_PATH . 'Url' . EXT, - 'think\View' => CORE_PATH . 'View' . EXT, - 'think\db\Driver' => CORE_PATH . 'db' . DS . 'Driver' . EXT, - 'think\view\driver\Think' => CORE_PATH . 'view' . DS . 'driver' . DS . 'Think' . EXT, - 'think\template\driver\File' => CORE_PATH . 'template' . DS . 'driver' . DS . 'File' . EXT, - 'think\log\driver\File' => CORE_PATH . 'log' . DS . 'driver' . DS . 'File' . EXT, - 'think\cache\driver\File' => CORE_PATH . 'cache' . DS . 'driver' . DS . 'File' . EXT, - ], - -]; diff --git a/thinkphp/mode/sae.php b/thinkphp/mode/sae.php deleted file mode 100644 index 2a1bdbe71..000000000 --- a/thinkphp/mode/sae.php +++ /dev/null @@ -1,99 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * ThinkPHP SAE应用模式定义文件 - */ -return [ - // 配置文件 - 'config' => array_merge(include THINK_PATH . 'convention' . EXT, [ - /* 数据库设置 */ - 'database' => [ - // 数据库类型 - 'type' => 'mysql', - 'dsn' => '', // - // 服务器地址 - 'hostname' => SAE_MYSQL_HOST_M . ',' . SAE_MYSQL_HOST_S, - // 数据库名 - 'database' => SAE_MYSQL_DB, - // 用户名 - 'username' => SAE_MYSQL_USER, - // 密码 - 'password' => SAE_MYSQL_PASS, - // 端口 - 'hostport' => SAE_MYSQL_PORT, - // 数据库连接参数 - 'params' => [], - // 数据库编码默认采用utf8 - 'charset' => 'utf8', - // 数据库表前缀 - 'prefix' => '', - // 数据库调试模式 - 'debug' => false, - // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) - 'deploy' => 1, - // 数据库读写是否分离 主从式有效 - 'rw_separate' => true, - // 读写分离后 主服务器数量 - 'master_num' => 1, - // 指定从服务器序号 - 'slave_no' => '', - ], - 'log' => [ - 'type' => 'Sae', - ], - 'cache' => [ - 'type' => 'Sae', - 'path' => CACHE_PATH, - 'prefix' => '', - 'expire' => 0, - ], - 'file_upload_type' => 'Sae', - 'template' => [ - 'compile_type' => 'Sae', - ], - 'compile_type' => 'Sae', - ]), - - // 别名定义 - 'alias' => [ - 'think\App' => CORE_PATH . 'App' . EXT, - 'think\Build' => CORE_PATH . 'Build' . EXT, - 'think\Cache' => CORE_PATH . 'Cache' . EXT, - 'think\Config' => CORE_PATH . 'Config' . EXT, - 'think\Controller' => CORE_PATH . 'Controller' . EXT, - 'think\Cookie' => CORE_PATH . 'Cookie' . EXT, - 'think\Db' => CORE_PATH . 'Db' . EXT, - 'think\Debug' => CORE_PATH . 'Debug' . EXT, - 'think\Error' => CORE_PATH . 'Error' . EXT, - 'think\Exception' => CORE_PATH . 'Exception' . EXT, - 'think\Hook' => CORE_PATH . 'Hook' . EXT, - 'think\Input' => CORE_PATH . 'Input' . EXT, - 'think\Lang' => CORE_PATH . 'Lang' . EXT, - 'think\Log' => CORE_PATH . 'Log' . EXT, - 'think\Model' => CORE_PATH . 'Model' . EXT, - 'think\Response' => CORE_PATH . 'Response' . EXT, - 'think\Route' => CORE_PATH . 'Route' . EXT, - 'think\Session' => CORE_PATH . 'Session' . EXT, - 'think\Template' => CORE_PATH . 'Template' . EXT, - 'think\Url' => CORE_PATH . 'Url' . EXT, - 'think\View' => CORE_PATH . 'View' . EXT, - 'think\db\Driver' => CORE_PATH . 'db' . DS . 'Driver' . EXT, - 'think\view\driver\Think' => CORE_PATH . 'view' . DS . 'driver' . DS . 'Think' . EXT, - 'think\template\driver\File' => CORE_PATH . 'template' . DS . 'driver' . DS . 'File' . EXT, - 'think\log\driver\File' => CORE_PATH . 'log' . DS . 'driver' . DS . 'File' . EXT, - 'think\cache\driver\File' => CORE_PATH . 'cache' . DS . 'driver' . DS . 'File' . EXT, - 'think\log\driver\Sae' => CORE_PATH . 'log' . DS . 'driver' . DS . 'Sae' . EXT, - 'think\cache\driver\Sae' => CORE_PATH . 'cache' . DS . 'driver' . DS . 'Sae' . EXT, - 'think\template\driver\Sae' => CORE_PATH . 'template' . DS . 'driver' . DS . 'Sae' . EXT, - ], - -]; diff --git a/thinkphp/phpunit.xml b/thinkphp/phpunit.xml deleted file mode 100644 index 7c6ef03ca..000000000 --- a/thinkphp/phpunit.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - ./tests/thinkphp/ - - - - - - - - ./ - - tests - vendor - - - - - - - - - - diff --git a/thinkphp/start.php b/thinkphp/start.php deleted file mode 100644 index 653b428f5..000000000 --- a/thinkphp/start.php +++ /dev/null @@ -1,53 +0,0 @@ - -// +---------------------------------------------------------------------- - -namespace think; - -// ThinkPHP 引导文件 -// 加载基础文件 -require __DIR__ . '/base.php'; -require CORE_PATH . 'Loader.php'; - -// 注册自动加载 -Loader::register(); - -// 注册错误和异常处理机制 -register_shutdown_function('think\Error::appShutdown'); -set_error_handler('think\Error::appError'); -set_exception_handler('think\Error::appException'); - -// 加载模式定义文件 -$mode = require MODE_PATH . APP_MODE . EXT; - -// 加载模式别名定义 -if (isset($mode['alias'])) { - Loader::addMap(is_array($mode['alias']) ? $mode['alias'] : include $mode['alias']); -} - -// 加载模式配置文件 -if (isset($mode['config'])) { - is_array($mode['config']) ? Config::set($mode['config']) : Config::load($mode['config']); -} - -// 加载模式行为定义 -if (APP_HOOK && isset($mode['tags'])) { - Hook::import(is_array($mode['tags']) ? $mode['tags'] : include $mode['tags']); -} - -// 自动生成 -if (APP_AUTO_BUILD && is_file(APP_PATH . 'build.php')) { - Build::run(include APP_PATH . 'build.php'); -} - -// 是否自动运行 -if (APP_AUTO_RUN) { - App::run(); -} \ No newline at end of file diff --git a/thinkphp/tests/README.md b/thinkphp/tests/README.md deleted file mode 100644 index 99aaae16d..000000000 --- a/thinkphp/tests/README.md +++ /dev/null @@ -1,131 +0,0 @@ -## 测试目录结构 - -测试文件主要在 tests 文件下面,主要有以下几个文件夹 - -- conf 测试环境配置文件。 -- script 测试环境配置脚本。 -- thinkphp 测试用例和相关文件,与项目文件夹机构一致。 -- mock.php 测试入口文件。 - -## 主要测试流程 - -thinkphp5 的测试的主要流程是跟 thinkphp 的系统流程是相似的,大体的流程为: - -1. 引用 mock.php 文件加载框架 - -2. 根据文件目录,添加测试文件 - -3. 执行单元测试,输出结果 - -## 测试举例 - -例如测试 thinkphp 里的 apc 缓存,将分为以下几个过程: - -1. 创建 apcTest.php 文件 - -该文件应与 apc.php 目录路径 `thinkphp/library/think/cache/driver` 一致,命名空间与目录所在一致,并引用 `PHPUnit_Framework_TestCase`。 - - ```php - markTestSkipped('apc扩展不可用!'); - }; - ``` - - - 编写测试用例 - - *具体写法参照 [PHPUnit 官方文档](https://phpunit.de/manual/4.8/zh_cn/index.html)* - - ```php - public function testGet() - { - App::run(); - $this->assertInstanceOf( - '\think\cache\driver\Apc', - Cache::connect(['type' => 'apc', 'expire' => 1]) - ); - $this->assertTrue(Cache::set('key', 'value')); - $this->assertEquals('value', Cache::get('key')); - $this->assertTrue(Cache::rm('key')); - $this->assertFalse(Cache::get('key')); - $this->assertTrue(Cache::clear('key')); - Config::reset(); - } - ``` - -3. 执行单元测试命令 - - 在项目根目录执行 - - ```bash - $ phpunit - ``` - - 若想看到所有结果,请添加-v参数 - - ```bash - $ phpunit -v - ``` - -4. 输出结果 - -## 相关文档 - -[各个部分单元测试说明](http://www.kancloud.cn/brother_simon/tp5_test/96971 "各部分单元测试说明") - -## 大家一起来 - -单元测试的内容会跟框架同步,测试内容方方面面,是一个相对复杂的模块,同时也是一个值得重视的部分。希望大家能够多多提出意见,多多参与。如果你有任何问题或想法,可以随时提 issue,我们期待着收到听大家的质疑和讨论。 - -## 任务进度 - -单元测试任务进度,请大家认领模块 - -|模块|认领人|进度| -|---|---|---| -|Base||| -|App|Haotong Lin|| -|Build||| -|Config|Haotong Lin|| -|Cache||| -|Controller|Haotong Lin|| -|Cookie|Haotong Lin|| -|Db||| -|Debug|大漠|√| -|Error|大漠|| -|Hook||| -|Input|Haotong Lin|| -|Lang||| -|Loader||| -|Log||| -|Model||| -|Response|大漠|√| -|Route||| -|Session|大漠|√| -|Template|Haotong Lin|| -|Url||| -|View|mahuan|| diff --git a/thinkphp/tests/conf/apc.ini b/thinkphp/tests/conf/apc.ini deleted file mode 100644 index 008bcabfe..000000000 --- a/thinkphp/tests/conf/apc.ini +++ /dev/null @@ -1 +0,0 @@ -apc.enable_cli=1 diff --git a/thinkphp/tests/conf/apcu_bc.ini b/thinkphp/tests/conf/apcu_bc.ini deleted file mode 100644 index acb9c7e64..000000000 --- a/thinkphp/tests/conf/apcu_bc.ini +++ /dev/null @@ -1,2 +0,0 @@ -extension=apcu.so -extension=apc.so diff --git a/thinkphp/tests/mock.php b/thinkphp/tests/mock.php deleted file mode 100644 index 849b72100..000000000 --- a/thinkphp/tests/mock.php +++ /dev/null @@ -1,25 +0,0 @@ - -// +---------------------------------------------------------------------- - -// 测试入口文件 -$_SERVER['REQUEST_METHOD'] = 'GET'; - -// 定义项目测试基础路径 -define('TEST_PATH', __DIR__ . '/'); - -// 定义项目路径 -define('APP_PATH', __DIR__ . '/../../application/'); -// 开启调试模式 -define('APP_DEBUG', true); - -// 加载框架引导文件 -require __DIR__ . '/../start.php'; -\think\Loader::addNamespace('tests', TEST_PATH); diff --git a/thinkphp/tests/script/install.sh b/thinkphp/tests/script/install.sh deleted file mode 100755 index 8944bbb55..000000000 --- a/thinkphp/tests/script/install.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -if [ $(phpenv version-name) != "hhvm" ]; then - pecl channel-update pecl.php.net - - if [ $(phpenv version-name) = "7.0" ]; then - pear config-set php_ini '' - pecl config-set php_ini '' - echo "yes\nno\n" | pecl install apcu-5.1.2 - pecl install apcu_bc-beta - phpenv config-add thinkphp/tests/conf/apcu_bc.ini - else - echo "yes\nno\n" | pecl install apcu-4.0.10 - fi - - phpenv config-add thinkphp/tests/conf/apc.ini -fi - -composer install --no-interaction --ignore-platform-reqs diff --git a/thinkphp/tests/thinkphp/baseTest.php b/thinkphp/tests/thinkphp/baseTest.php deleted file mode 100644 index d8d4941af..000000000 --- a/thinkphp/tests/thinkphp/baseTest.php +++ /dev/null @@ -1,60 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * 保证运行环境正常 - */ -class baseTest extends \PHPUnit_Framework_TestCase -{ - public function testConstants() - { - $this->assertNotEmpty(START_TIME); - $this->assertNotEmpty(START_MEM); - $this->assertNotEmpty(THINK_VERSION); - $this->assertNotEmpty(DS); - $this->assertNotEmpty(THINK_PATH); - $this->assertNotEmpty(LIB_PATH); - $this->assertNotEmpty(EXTEND_PATH); - $this->assertNotEmpty(MODE_PATH); - $this->assertNotEmpty(CORE_PATH); - $this->assertNotEmpty(ORG_PATH); - $this->assertNotEmpty(TRAIT_PATH); - $this->assertNotEmpty(APP_PATH); - $this->assertNotEmpty(APP_NAMESPACE); - $this->assertNotEmpty(COMMON_MODULE); - $this->assertNotEmpty(RUNTIME_PATH); - $this->assertNotEmpty(DATA_PATH); - $this->assertNotEmpty(LOG_PATH); - $this->assertNotEmpty(CACHE_PATH); - $this->assertNotEmpty(TEMP_PATH); - $this->assertNotEmpty(VENDOR_PATH); - $this->assertNotEmpty(EXT); - $this->assertNotEmpty(MODEL_LAYER); - $this->assertNotEmpty(VIEW_LAYER); - $this->assertNotEmpty(CONTROLLER_LAYER); - $this->assertTrue(is_bool(APP_DEBUG)); - $this->assertTrue(is_bool(APP_HOOK)); - $this->assertNotEmpty(ENV_PREFIX); - $this->assertTrue(is_bool(IS_API)); - $this->assertTrue(is_bool(APP_AUTO_BUILD)); - $this->assertNotEmpty(APP_MODE); - $this->assertTrue(!is_null(IS_CGI)); - $this->assertTrue(!is_null(IS_WIN)); - $this->assertTrue(!is_null(IS_CLI)); - $this->assertTrue(is_bool(IS_AJAX)); - $this->assertNotEmpty(NOW_TIME); - $this->assertNotEmpty(REQUEST_METHOD); - $this->assertTrue(is_bool(IS_GET)); - $this->assertTrue(is_bool(IS_POST)); - $this->assertTrue(is_bool(IS_PUT)); - $this->assertTrue(is_bool(IS_DELETE)); - } -} diff --git a/thinkphp/tests/thinkphp/library/think/appTest.php b/thinkphp/tests/thinkphp/library/think/appTest.php deleted file mode 100644 index 7a10f7d27..000000000 --- a/thinkphp/tests/thinkphp/library/think/appTest.php +++ /dev/null @@ -1,27 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * app类测试 - * @author Haotong Lin - */ - -namespace tests\thinkphp\library\think; - -class appTest extends \PHPUnit_Framework_TestCase -{ - public function testRun() - { - \think\App::run(); - $this->expectOutputString('

:)

欢迎使用 ThinkPHP5

'); - // todo... - } -} diff --git a/thinkphp/tests/thinkphp/library/think/cache/driver/apcTest.php b/thinkphp/tests/thinkphp/library/think/cache/driver/apcTest.php deleted file mode 100644 index 0557c412f..000000000 --- a/thinkphp/tests/thinkphp/library/think/cache/driver/apcTest.php +++ /dev/null @@ -1,52 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * Apc缓存驱动测试 - * @author mahuan - */ - -namespace tests\thinkphp\library\think\cache\driver; - -class apcTest extends cacheTestCase -{ - private $_cacheInstance = null; - /** - * 基境缓存类型 - */ - protected function setUp() - { - \think\Cache::connect(array('type' => 'apc', 'expire' => 2)); - } - /** - * @return ApcCache - */ - protected function getCacheInstance() - { - if (!extension_loaded("apc")) { - $this->markTestSkipped("APC没有安装,已跳过测试!"); - } elseif ('cli' === PHP_SAPI && !ini_get('apc.enable_cli')) { - $this->markTestSkipped("APC模块没有开启,已跳过测试!"); - } - if (null === $this->_cacheInstance) { - $this->_cacheInstance = new \think\cache\driver\Apc(); - } - return $this->_cacheInstance; - } - /** - * 缓存过期测试《提出来测试,因为目前看通不过缓存过期测试,所以还需研究》 - * @return mixed - * @access public - */ - public function testExpire() - { - } -} diff --git a/thinkphp/tests/thinkphp/library/think/cache/driver/cacheTestCase.php b/thinkphp/tests/thinkphp/library/think/cache/driver/cacheTestCase.php deleted file mode 100644 index 2bf87f589..000000000 --- a/thinkphp/tests/thinkphp/library/think/cache/driver/cacheTestCase.php +++ /dev/null @@ -1,145 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * 缓存抽象类,提供一些测试 - * @author simon - */ - -namespace tests\thinkphp\library\think\cache\driver; - -use think\cache; - -abstract class cacheTestCase extends \PHPUnit_Framework_TestCase -{ - - /** - * 获取缓存句柄,子类必须有 - * @access protected - */ - abstract protected function getCacheInstance(); - /** - * tearDown函数 - */ - protected function tearDown() - { - } - /** - * 设定一组测试值,包括测试字符串、整数、数组和对象 - * @return mixed - * @access public - */ - public function prepare() - { - $cache = $this->getCacheInstance(); - $cache->clear(); - $cache->set('string_test', 'string_test'); - $cache->set('number_test', 11); - $cache->set('array_test', ['array_test' => 'array_test']); - return $cache; - } - /** - * 测试缓存设置,包括测试字符串、整数、数组和对象 - * @return mixed - * @access public - */ - public function testSet() - { - $cache = $this->getCacheInstance(); - $this->assertTrue($cache->set('string_test', 'string_test')); - $this->assertTrue($cache->set('number_test', 11)); - $this->assertTrue($cache->set('array_test', ['array_test' => 'array_test'])); - } - /** - * 测试缓存读取,包括测试字符串、整数、数组和对象 - * @return mixed - * @access public - */ - public function testGet() - { - $cache = $this->prepare(); - $this->assertEquals('string_test', $cache->get('string_test')); - $this->assertEquals(11, $cache->get('number_test')); - $array = $cache->get('array_test'); - $this->assertArrayHasKey('array_test', $array); - $this->assertEquals('array_test', $array['array_test']); - } - /** - * 测试缓存存在情况,包括测试字符串、整数、数组和对象 - * @return mixed - * @access public - */ - public function testExists() - { - $cache = $this->prepare(); - $this->assertNotEmpty($cache->get('string_test')); - $this->assertNotEmpty($cache->get('number_test')); - $this->assertFalse($cache->get('not_exists')); - } - /** - * 测试缓存不存在情况,包括测试字符串、整数、数组和对象 - * @return mixed - * @access public - */ - public function testGetNonExistent() - { - $cache = $this->getCacheInstance(); - $this->assertFalse($cache->get('non_existent_key')); - } - /** - * 测试特殊值缓存,包括测试字符串、整数、数组和对象 - * @return mixed - * @access public - */ - public function testStoreSpecialValues() - { - $cache = $this->getCacheInstance(); - $cache->set('null_value', null); - //清空缓存后,返回null而不是false - $this->assertTrue(is_null($cache->get('null_value'))); - } - /** - * 缓存过期测试 - * @return mixed - * @access public - */ - public function testExpire() - { - $cache = $this->getCacheInstance(); - $this->assertTrue($cache->set('expire_test', 'expire_test', 2)); - usleep(500000); - $this->assertEquals('expire_test', $cache->get('expire_test')); - usleep(2500000); - $this->assertFalse($cache->get('expire_test')); - } - /** - * 删除缓存测试 - * @return mixed - * @access public - */ - public function testDelete() - { - $cache = $this->prepare(); - $this->assertNotNull($cache->rm('number_test')); - $this->assertFalse($cache->get('number_test')); - } - /** - * 清空缓存测试 - * @return mixed - * @access public - */ - public function testClear() - { - $cache = $this->prepare(); - $this->assertTrue($cache->clear()); - $this->assertFalse($cache->get('number_test')); - } -} diff --git a/thinkphp/tests/thinkphp/library/think/cache/driver/dbTest.php b/thinkphp/tests/thinkphp/library/think/cache/driver/dbTest.php deleted file mode 100644 index 9c896d4f7..000000000 --- a/thinkphp/tests/thinkphp/library/think/cache/driver/dbTest.php +++ /dev/null @@ -1,43 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * 数据库缓存驱动测试 - * @author mahuan - */ - -namespace tests\thinkphp\library\think\cache\driver; - -class dbTest extends cacheTestCase -{ - private $_cacheInstance = null; - - /** - * 基境缓存类型 - */ - protected function setUp() - { - //数据库缓存测试因为缺少数据库单元测试所以暂时跳过 - $this->markTestSkipped("暂时跳过测试。"); - \think\Cache::connect(array('type' => 'db', 'expire' => 2)); - } - - /** - * @return DbCache - */ - protected function getCacheInstance() - { - if (null === $this->_cacheInstance) { - $this->_cacheInstance = new \think\cache\driver\Db(); - } - return $this->_cacheInstance; - } -} diff --git a/thinkphp/tests/thinkphp/library/think/config/driver/fixtures/config.ini b/thinkphp/tests/thinkphp/library/think/config/driver/fixtures/config.ini deleted file mode 100644 index 2a17cc0de..000000000 --- a/thinkphp/tests/thinkphp/library/think/config/driver/fixtures/config.ini +++ /dev/null @@ -1 +0,0 @@ -inifile=1 \ No newline at end of file diff --git a/thinkphp/tests/thinkphp/library/think/config/driver/fixtures/config.xml b/thinkphp/tests/thinkphp/library/think/config/driver/fixtures/config.xml deleted file mode 100644 index 3c3266a17..000000000 --- a/thinkphp/tests/thinkphp/library/think/config/driver/fixtures/config.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - 1 - - \ No newline at end of file diff --git a/thinkphp/tests/thinkphp/library/think/config/driver/iniTest.php b/thinkphp/tests/thinkphp/library/think/config/driver/iniTest.php deleted file mode 100644 index 2575157c4..000000000 --- a/thinkphp/tests/thinkphp/library/think/config/driver/iniTest.php +++ /dev/null @@ -1,33 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * Ini配置测试 - * @author 7IN0SAN9 - */ - -namespace tests\thinkphp\library\think\config\driver; - -use think\config; - -class iniTest extends \PHPUnit_Framework_TestCase -{ - public function testParse() - { - Config::parse('inistring=1', 'ini'); - $this->assertEquals(1, Config::get('inistring')); - Config::reset(); - Config::parse(__DIR__ . '/fixtures/config.ini'); - $this->assertTrue(Config::has('inifile')); - $this->assertEquals(1, Config::get('inifile')); - Config::reset(); - } -} diff --git a/thinkphp/tests/thinkphp/library/think/config/driver/xmlTest.php b/thinkphp/tests/thinkphp/library/think/config/driver/xmlTest.php deleted file mode 100644 index 9ab1d257d..000000000 --- a/thinkphp/tests/thinkphp/library/think/config/driver/xmlTest.php +++ /dev/null @@ -1,33 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * Xml配置测试 - * @author 7IN0SAN9 - */ - -namespace tests\thinkphp\library\think\config\driver; - -use think\config; - -class xmlTest extends \PHPUnit_Framework_TestCase -{ - public function testParse() - { - Config::parse('1', 'xml'); - $this->assertEquals(1, Config::get('xmlstring')); - Config::reset(); - Config::parse(__DIR__ . '/fixtures/config.xml'); - $this->assertTrue(Config::has('xmlfile.istrue')); - $this->assertEquals(1, Config::get('xmlfile.istrue')); - Config::reset(); - } -} diff --git a/thinkphp/tests/thinkphp/library/think/configTest.php b/thinkphp/tests/thinkphp/library/think/configTest.php deleted file mode 100644 index e68868614..000000000 --- a/thinkphp/tests/thinkphp/library/think/configTest.php +++ /dev/null @@ -1,176 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * 配置测试 - * @author Haotong Lin - */ - -namespace tests\thinkphp\library\think; - -use ReflectionClass; -use think\Config; - -class configTest extends \PHPUnit_Framework_TestCase -{ - public function testRange() - { - $reflectedClass = new ReflectionClass('\think\config'); - $reflectedPropertyRange = $reflectedClass->getProperty('range'); - $reflectedPropertyRange->setAccessible(true); - $reflectedPropertyConfig = $reflectedClass->getProperty('config'); - $reflectedPropertyConfig->setAccessible(true); - // test default range - $this->assertEquals('_sys_', $reflectedPropertyRange->getValue()); - $config = $reflectedPropertyConfig->getValue(); - $this->assertTrue(is_array($config)); - // test range initialization - Config::range('_test_'); - $this->assertEquals('_test_', $reflectedPropertyRange->getValue()); - $config = $reflectedPropertyConfig->getValue(); - $this->assertEquals([], $config['_test_']); - } - - // public function testParse() - // { - // see \think\config\driver\...Test.php - // } - - public function testLoad() - { - $file = APP_PATH . 'config' . EXT; - $config = array_change_key_case(include $file); - $name = '_name_'; - $range = '_test_'; - - $reflectedClass = new ReflectionClass('\think\config'); - $reflectedPropertyConfig = $reflectedClass->getProperty('config'); - $reflectedPropertyConfig->setAccessible(true); - $reflectedPropertyConfig->setValue([]); - - $this->assertEquals($config, \think\config::load($file, $name, $range)); - $this->assertNotEquals(null, \think\config::load($file, $name, $range)); - } - - public function testHas() - { - $range = '_test_'; - $this->assertFalse(\think\config::has('abcd', $range)); - $reflectedClass = new ReflectionClass('\think\config'); - $reflectedPropertyConfig = $reflectedClass->getProperty('config'); - $reflectedPropertyConfig->setAccessible(true); - - // if (!strpos($name, '.')): - $reflectedPropertyConfig->setValue([ - $range => ['abcd' => 'value'], - ]); - $this->assertTrue(\think\config::has('abcd', $range)); - - // else ... - $this->assertFalse(\think\config::has('abcd.efg', $range)); - - $reflectedPropertyConfig->setValue([ - $range => ['abcd' => ['efg' => 'value']], - ]); - $this->assertTrue(\think\config::has('abcd.efg', $range)); - } - - public function testGet() - { - $range = '_test_'; - $reflectedClass = new ReflectionClass('\think\config'); - $reflectedPropertyConfig = $reflectedClass->getProperty('config'); - $reflectedPropertyConfig->setAccessible(true); - // test all configurations - $reflectedPropertyConfig->setValue([$range => []]); - $this->assertEquals([], \think\config::get(null, $range)); - $this->assertEquals(null, \think\config::get(null, 'does_not_exist')); - // test $_ENV configuration - defined('ENV_PREFIX') or define('ENV_PREFIX', '_TEST_'); - $name = 'test_name'; - $value = 'value'; - $_ENV[ENV_PREFIX . $name] = $value; - $this->assertEquals($value, \think\config::get($name, $range)); - // test getting configuration - $reflectedPropertyConfig->setValue([$range => ['abcd' => 'efg']]); - $this->assertEquals('efg', \think\config::get('abcd', $range)); - $this->assertEquals(null, \think\config::get('does_not_exist', $range)); - $this->assertEquals(null, \think\config::get('abcd', 'does_not_exist')); - // test $_ENV configuration with dot syntax - $this->assertEquals($value, \think\config::get('test.name', $range)); - // test getting configuration with dot syntax - $reflectedPropertyConfig->setValue([$range => [ - 'one' => ['two' => $value], - ]]); - $this->assertEquals($value, \think\config::get('one.two', $range)); - $this->assertEquals(null, \think\config::get('one.does_not_exist', $range)); - $this->assertEquals(null, \think\config::get('one.two', 'does_not_exist')); - } - - public function testSet() - { - $range = '_test_'; - $reflectedClass = new ReflectionClass('\think\config'); - $reflectedPropertyConfig = $reflectedClass->getProperty('config'); - $reflectedPropertyConfig->setAccessible(true); - $reflectedPropertyConfig->setValue([]); - // if (is_string($name)): - // without dot syntax - $name = 'name'; - $value = 'value'; - \think\config::set($name, $value, $range); - $config = $reflectedPropertyConfig->getValue(); - $this->assertEquals($value, $config[$range][$name]); - // with dot syntax - $name = 'one.two'; - $value = 'dot value'; - \think\config::set($name, $value, $range); - $config = $reflectedPropertyConfig->getValue(); - $this->assertEquals($value, $config[$range]['one']['two']); - // if (is_array($name)): - // see testLoad() - // ... - // test getting all configurations...? - // return self::$config[$range]; ?? - $value = ['all' => 'configuration']; - $reflectedPropertyConfig->setValue([$range => $value]); - $this->assertEquals($value, \think\config::set(null, null, $range)); - $this->assertNotEquals(null, \think\config::set(null, null, $range)); - } - - public function testReset() - { - $range = '_test_'; - $reflectedClass = new ReflectionClass('\think\config'); - $reflectedPropertyConfig = $reflectedClass->getProperty('config'); - $reflectedPropertyConfig->setAccessible(true); - $reflectedPropertyConfig->setValue([$range => ['abcd' => 'efg']]); - - // clear all configurations - \think\config::reset(true); - $config = $reflectedPropertyConfig->getValue(); - $this->assertEquals([], $config); - // clear the configuration in range of parameter. - $reflectedPropertyConfig->setValue([ - $range => [ - 'abcd' => 'efg', - 'hijk' => 'lmn', - ], - 'a' => 'b', - ]); - \think\config::reset($range); - $config = $reflectedPropertyConfig->getValue(); - $this->assertEquals([ - $range => [], - 'a' => 'b', - ], $config); - } -} diff --git a/thinkphp/tests/thinkphp/library/think/controllerTest.php b/thinkphp/tests/thinkphp/library/think/controllerTest.php deleted file mode 100644 index 00ad6c0da..000000000 --- a/thinkphp/tests/thinkphp/library/think/controllerTest.php +++ /dev/null @@ -1,104 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * 控制器测试 - * @author Haotong Lin - */ - -namespace tests\thinkphp\library\think; - -require_once CORE_PATH . '../../helper.php'; - -class Foo extends \think\Controller -{ - public $test = 'test'; - - public function _initialize() - { - $this->test = 'abcd'; - } -} - -class Bar extends \think\Controller -{ - public $test = 1; - - public $beforeActionList = ['action1', 'action2']; - - public function action1() - { - $this->test += 2; - return 'action1'; - } - - public function action2() - { - $this->test += 4; - return 'action2'; - } -} - -class Baz extends \think\Controller -{ - public $test = 1; - - public $beforeActionList = [ - 'action1' => ['only' => ['index']], - 'action2' => ['except' => ['index']], - 'action3' => ['only' => ['abcd']], - 'action4' => ['except' => ['abcd']], - ]; - - public function action1() - { - $this->test += 2; - return 'action1'; - } - - public function action2() - { - $this->test += 4; - return 'action2'; - } - - public function action3() - { - $this->test += 8; - return 'action2'; - } - - public function action4() - { - $this->test += 16; - return 'action2'; - } -} - -define('ACTION_NAME', 'index'); - -class controllerTest extends \PHPUnit_Framework_TestCase -{ - public function testInitialize() - { - $foo = new Foo; - $this->assertEquals('abcd', $foo->test); - } - - public function testBeforeAction() - { - $obj = new Bar; - $this->assertEquals(7, $obj->test); - - $obj = new Baz; - $this->assertEquals(19, $obj->test); - } -} diff --git a/thinkphp/tests/thinkphp/library/think/cookieTest.php b/thinkphp/tests/thinkphp/library/think/cookieTest.php deleted file mode 100644 index 2f379f73d..000000000 --- a/thinkphp/tests/thinkphp/library/think/cookieTest.php +++ /dev/null @@ -1,151 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * Cookie测试 - * @author Haotong Lin - */ - -namespace tests\thinkphp\library\think; - -use ReflectionClass; - -class cookieTest extends \PHPUnit_Framework_TestCase -{ - protected $ref; - - protected $default = [ - // cookie 名称前缀 - 'prefix' => '', - // cookie 保存时间 - 'expire' => 0, - // cookie 保存路径 - 'path' => '/', - // cookie 有效域名 - 'domain' => '', - // cookie 启用安全传输 - 'secure' => false, - // httponly设置 - 'httponly' => '', - ]; - - protected function setUp() - { - $reflectedClass = new ReflectionClass('\think\Cookie'); - $reflectedPropertyConfig = $reflectedClass->getProperty('config'); - $reflectedPropertyConfig->setAccessible(true); - $reflectedPropertyConfig->setValue($this->default); - $this->ref = $reflectedPropertyConfig; - } - - public function testInit() - { - $config = [ - // cookie 名称前缀 - 'prefix' => 'think_', - // cookie 保存时间 - 'expire' => 0, - // cookie 保存路径 - 'path' => '/path/to/test/', - // cookie 有效域名 - 'domain' => '.thinkphp.cn', - // cookie 启用安全传输 - 'secure' => true, - // httponly设置 - 'httponly' => '1', - ]; - \think\Cookie::init($config); - - $this->assertEquals( - array_merge($this->default, array_change_key_case($config)), - $this->ref->getValue() - ); - } - - public function testPrefix() - { - $this->assertEquals($this->default['prefix'], \think\Cookie::prefix()); - - $prefix = '_test_'; - $this->assertNotEquals($prefix, \think\Cookie::prefix()); - \think\Cookie::prefix($prefix); - - $config = $this->ref->getValue(); - $this->assertEquals($prefix, $config['prefix']); - } - - public function testSet() - { - $value = 'value'; - - $name = 'name1'; - \think\Cookie::set($name, $value, 10); - $this->assertEquals($value, $_COOKIE[$this->default['prefix'] . $name]); - - $name = 'name2'; - \think\Cookie::set($name, $value, null); - $this->assertEquals($value, $_COOKIE[$this->default['prefix'] . $name]); - - $name = 'name3'; - \think\Cookie::set($name, $value, 'expire=100&prefix=pre_'); - $this->assertEquals($value, $_COOKIE['pre_' . $name]); - - $name = 'name4'; - $value = ['_test_中文_']; - \think\Cookie::set($name, $value); - $this->assertEquals('think:' . json_encode([urlencode('_test_中文_')]), $_COOKIE[$name]); - } - - public function testGet() - { - $_COOKIE = [ - 'a' => 'b', - 'pre_abc' => 'c', - 'd' => 'think:' . json_encode([urlencode('_test_中文_')]), - ]; - $this->assertEquals('b', \think\Cookie::get('a')); - $this->assertEquals(null, \think\Cookie::get('does_not_exist')); - $this->assertEquals('c', \think\Cookie::get('abc', 'pre_')); - $this->assertEquals(['_test_中文_'], \think\Cookie::get('d')); - } - - public function testDelete() - { - $_COOKIE = [ - 'a' => 'b', - 'pre_abc' => 'c', - ]; - $this->assertEquals('b', \think\Cookie::get('a')); - \think\Cookie::delete('a'); - $this->assertEquals(null, \think\Cookie::get('a')); - - $this->assertEquals('c', \think\Cookie::get('abc', 'pre_')); - \think\Cookie::delete('abc', 'pre_'); - $this->assertEquals(null, \think\Cookie::get('abc', 'pre_')); - } - - public function testClear() - { - $_COOKIE = []; - $this->assertEquals(null, \think\Cookie::clear()); - - $_COOKIE = ['a' => 'b']; - \think\Cookie::clear(); - $this->assertEquals(null, $_COOKIE); - - $_COOKIE = [ - 'a' => 'b', - 'pre_abc' => 'c', - ]; - \think\Cookie::clear('pre_'); - $this->assertEquals(['a' => 'b'], $_COOKIE); - } -} diff --git a/thinkphp/tests/thinkphp/library/think/db/driver/.gitignore b/thinkphp/tests/thinkphp/library/think/db/driver/.gitignore deleted file mode 100644 index a3a0c8b5f..000000000 --- a/thinkphp/tests/thinkphp/library/think/db/driver/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/thinkphp/tests/thinkphp/library/think/debugTest.php b/thinkphp/tests/thinkphp/library/think/debugTest.php deleted file mode 100644 index 5b5f250e7..000000000 --- a/thinkphp/tests/thinkphp/library/think/debugTest.php +++ /dev/null @@ -1,177 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * Debug测试 - * @author 大漠 - */ - -namespace tests\thinkphp\library\think; - -use think\Debug; - -class debugTest extends \PHPUnit_Framework_TestCase -{ - - /** - * - * @var Debug - */ - protected $object; - - /** - * Sets up the fixture, for example, opens a network connection. - * This method is called before a test is executed. - */ - protected function setUp() - { - $this->object = new Debug(); - } - - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - */ - protected function tearDown() - {} - - /** - * @covers think\Debug::remark - * @todo Implement testRemark(). - */ - public function testRemark() - { - $name = "testremarkkey"; - $value = "testremarkval"; - \think\Debug::remark($name); - } - - /** - * @covers think\Debug::getRangeTime - * @todo Implement testGetRangeTime(). - */ - public function testGetRangeTime() - { - $start = "testGetRangeTimeStart"; - $end = "testGetRangeTimeEnd"; - \think\Debug::remark($start); - usleep(20000); - // \think\Debug::remark($end); - - $time = \think\Debug::getRangeTime($start, $end); - $this->assertLessThan(0.03, $time); - //$this->assertEquals(0.03, ceil($time)); - } - - /** - * @covers think\Debug::getUseTime - * @todo Implement testGetUseTime(). - */ - public function testGetUseTime() - { - $time = \think\Debug::getUseTime(); - $this->assertLessThan(3.5, $time); - } - - /** - * @covers think\Debug::getThroughputRate - * @todo Implement testGetThroughputRate(). - */ - public function testGetThroughputRate() - { - usleep(100000); - $throughputRate = \think\Debug::getThroughputRate(); - $this->assertLessThan(10, $throughputRate); - } - - /** - * @covers think\Debug::getRangeMem - * @todo Implement testGetRangeMem(). - */ - public function testGetRangeMem() - { - $start = "testGetRangeMemStart"; - $end = "testGetRangeMemEnd"; - \think\Debug::remark($start); - $str = ""; - for ($i = 0; $i < 10000; $i++) { - $str .= "mem"; - } - - $rangeMem = \think\Debug::getRangeMem($start, $end); - - $this->assertLessThan(33, explode(" ", $rangeMem)[0]); - } - - /** - * @covers think\Debug::getUseMem - * @todo Implement testGetUseMem(). - */ - public function testGetUseMem() - { - $useMem = \think\Debug::getUseMem(); - - $this->assertLessThan(13, explode(" ", $useMem)[0]); - } - - /** - * @covers think\Debug::getMemPeak - * @todo Implement testGetMemPeak(). - */ - public function testGetMemPeak() - { - $start = "testGetMemPeakStart"; - $end = "testGetMemPeakEnd"; - \think\Debug::remark($start); - $str = ""; - for ($i = 0; $i < 100000; $i++) { - $str .= "mem"; - } - $memPeak = \think\Debug::getMemPeak($start, $end); - - // echo "\r\n" . $memPeak . "\r\n"; - - $this->assertLessThan(238, explode(" ", $memPeak)[0]); - } - - /** - * @covers think\Debug::getFile - * @todo Implement testGetFile(). - */ - public function testGetFile() - { - $count = \think\Debug::getFile(); - - $this->assertEquals(count(get_included_files()), $count); - - $info = \think\Debug::getFile(true); - $this->assertEquals(count(get_included_files()), count($info)); - - $this->assertContains("KB", $info[0]); - } - - /** - * @covers think\Debug::dump - * @todo Implement testDump(). - */ - public function testDump() - { - $var = array(); - $var["key"] = "val"; - $output = \think\Debug::dump($var, false, $label = "label"); - - if (IS_WIN) { - $this->assertEquals("(1) {\\n 'key' =>\\n string(3) \\\"val\\\"\\n}\\n\\r\\n\"", end(explode("array", json_encode($output)))); - } else { - $this->assertEquals("(1) {\\n 'key' =>\\n string(3) \\\"val\\\"\\n}\\n\\n\"", end(explode("array", json_encode($output)))); - } - } -} diff --git a/thinkphp/tests/thinkphp/library/think/inputTest.php b/thinkphp/tests/thinkphp/library/think/inputTest.php deleted file mode 100644 index dc91b29e7..000000000 --- a/thinkphp/tests/thinkphp/library/think/inputTest.php +++ /dev/null @@ -1,195 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * Input测试 - * @author Haotong Lin - */ - -namespace tests\thinkphp\library\think; - -use think\Input; - -class inputTest extends \PHPUnit_Framework_TestCase -{ - - public function testInputName() - { - $input = ['a' => 'a', 'b' => ['c' => [' one ', 'two']]]; - $this->assertEquals($input, Input::data($input)); - $this->assertEquals($input['a'], Input::data($input['a'])); - $this->assertEquals('one', Input::data('b.c.0/s', 'default', 'trim', false, $input)); - } - - public function testDefaultValue() - { - $input = ['a' => 'test']; - $default = 'default'; - $this->assertEquals($default, Input::data($input['b'], $default)); - $this->assertEquals($default, Input::data($input, $default, '', false, $input)); - $this->assertEquals($default, Input::get('a', $default)); - } - - public function testStringFilter() - { - $input = ['a' => ' test ', 'b' => ' test<> ']; - $filters = 'trim'; - $this->assertEquals('test', Input::data('a', '', $filters, false, $input)); - $filters = 'trim,htmlspecialchars'; - $this->assertEquals('test<>', Input::data('b', '', $filters, false, $input)); - } - - public function testArrayFilter() - { - $input = ['a' => ' test ', 'b' => ' test<> ']; - $filters = ['trim']; - $this->assertEquals('test', Input::data('a', '', $filters, false, $input)); - $filters = ['trim', 'htmlspecialchars']; - $this->assertEquals('test<>', Input::data('b', '', $filters, false, $input)); - } - - public function testFilterExp() - { - $src = 'EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN'; - $regexs = explode('|', $src); - $data = Input::data($regexs); - foreach ($regexs as $key => $value) { - $expected = $value . ' '; - $this->assertEquals($expected, $data[$key]); - } - } - - public function testFiltrateWithRegex() - { - $input = ['a' => 'test1', 'b' => '_test2', 'c' => '']; - $filters = '/^test/'; - $this->assertEquals('test1', Input::data('a', '', $filters, false, $input)); - $default = 'default value'; - $this->assertEquals($default, Input::data('b', $default, $filters, false, $input)); - $filters = '/.+/'; - $this->assertEquals('default value', Input::data('c', $default, $filters, false, $input)); - } - - public function testFiltrateWithFilterVar() - { - $email = 'abc@gmail.com'; - $error = 'not email'; - $default = false; - $input = ['a' => $email, 'b' => $error]; - $filters = FILTER_VALIDATE_EMAIL; - $this->assertEquals($email, Input::data('a', '', $filters, false, $input)); - $this->assertFalse(Input::data('b', $default, $filters, false, $input)); - $filters = 'validate_email'; - $this->assertFalse(Input::data('b', $default, $filters, false, $input)); - } - - public function testAllInput() - { - $input = [ - 'a' => ' trim ', - 'b' => 'htmlspecialchars<>', - 'c' => ' trim htmlspecialchars<> ', - 'd' => 'eXp', - 'e' => 'NEQ', - 'f' => 'gt', - ]; - $filters = 'htmlspecialchars,trim'; - $excepted = [ - 'a' => 'trim', - 'b' => 'htmlspecialchars<>', - 'c' => 'trim htmlspecialchars<>', - 'd' => 'eXp ', - 'e' => 'NEQ ', - 'f' => 'gt ', - ]; - $this->assertEquals($excepted, Input::data($input, '', $filters)); - } - - public function testTypeCast() - { - $_POST = [ - 'a' => [1, 2, 3], - 'b' => '1000', - 'c' => '3.14', - 'd' => 'test boolean', - ]; - $this->assertEquals([1, 2, 3], Input::post('a/a')); - $this->assertEquals(1000, Input::post('b/d')); - $this->assertEquals(3.14, Input::post('c/f')); - $this->assertEquals(true, Input::post('d/b')); - } - - public function testHasValue() - { - $_GET['name'] = 'value'; - $_GET['config']['name'] = 'value'; - $this->assertEquals(true, Input::get('?name')); - $this->assertEquals(false, Input::get('?id')); - $this->assertEquals(true, Input::get('?config.name')); - $this->assertEquals(false, Input::get('?config.id')); - } - - public function testSuperglobals() - { - Input::setFilter('trim'); - $_GET['get'] = 'get value '; - $this->assertEquals('get value', Input::get('get')); - $_POST['post'] = 'post value '; - $this->assertEquals('post value', Input::post('post')); - - $_SERVER['REQUEST_METHOD'] = 'POST'; - $this->assertEquals('post value', Input::param('post')); - $this->assertEquals(null, Input::param('get')); - $_SERVER['REQUEST_METHOD'] = 'GET'; - $this->assertEquals('get value', Input::param('get')); - $this->assertEquals(null, Input::param('post')); - $this->assertEquals(null, Input::param('put')); - $_REQUEST = array_merge($_GET, $_POST); - $this->assertEquals('get value', Input::request('get')); - - session_start(); - $_SESSION['test'] = 'session value '; - $this->assertEquals('session value', Input::session('test')); - session_destroy(); - - $_COOKIE['cookie'] = 'cookie value '; - $this->assertEquals('cookie value', Input::cookie('cookie')); - - $_SERVER['REQUEST_METHOD'] = 'GET '; - $this->assertEquals('GET', Input::server('REQUEST_METHOD')); - - $GLOBALS['total'] = 1000; - $this->assertEquals(1000, Input::globals('total')); - - $this->assertEquals('testing', Input::env('APP_ENV')); - - //$_SERVER['PATH_INFO'] = 'path/info'; - //$path = $_SERVER['PATH_INFO'] ? explode('/', $_SERVER['PATH_INFO'])[0] : ''; - //$this->assertEquals($path, Input::path('0', '')); - - $_FILES = ['file' => ['name' => 'test.png', 'type' => 'image/png', 'tmp_name' => '/tmp/php5Wx0aJ', 'error' => 0, size => 15726]]; - $this->assertEquals('image/png', Input::file('file.type')); - - } - - public function testFilterMerge() - { - Input::setFilter('htmlspecialchars'); - $input = ['a' => ' test<> ', 'b' => '']; - $this->assertEquals(' test<> ', Input::data('a', '', '', false, $input)); - $filters = ['trim']; - $this->assertEquals('test<>', Input::data('a', '', $filters, false, $input)); - $this->assertEquals('test<>', Input::data('a', '', $filters, true, $input)); - $filters = 'stripslashes'; - $this->assertEquals("<bar />", Input::data('b', '', $filters, true, $input)); - } - -} diff --git a/thinkphp/tests/thinkphp/library/think/log/driver/.gitignore b/thinkphp/tests/thinkphp/library/think/log/driver/.gitignore deleted file mode 100644 index a3a0c8b5f..000000000 --- a/thinkphp/tests/thinkphp/library/think/log/driver/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/thinkphp/tests/thinkphp/library/think/model/.gitignore b/thinkphp/tests/thinkphp/library/think/model/.gitignore deleted file mode 100644 index a3a0c8b5f..000000000 --- a/thinkphp/tests/thinkphp/library/think/model/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/thinkphp/tests/thinkphp/library/think/responseTest.php b/thinkphp/tests/thinkphp/library/think/responseTest.php deleted file mode 100644 index ad7925f29..000000000 --- a/thinkphp/tests/thinkphp/library/think/responseTest.php +++ /dev/null @@ -1,307 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * Response测试 - * @author 大漠 - */ - -namespace tests\thinkphp\library\think; - -class responseTest extends \PHPUnit_Framework_TestCase -{ - - /** - * - * @var Response - */ - protected $object; - - protected $default_return_type; - - protected $default_ajax_return; - - /** - * Sets up the fixture, for example, opens a network connection. - * This method is called before a test is executed. - */ - protected function setUp() - { - // 1. - // restore_error_handler(); - // Warning: Cannot modify header information - headers already sent by (output started at PHPUnit\Util\Printer.php:173) - // more see in https://www.analysisandsolutions.com/blog/html/writing-phpunit-tests-for-wordpress-plugins-wp-redirect-and-continuing-after-php-errors.htm - - // 2. - // the Symfony used the HeaderMock.php - - // 3. - // not run the eclipse will held, and travis-ci.org Searching for coverage reports - // **> Python coverage not found - // **> No coverage report found. - // add the - // /** - // * @runInSeparateProcess - // */ - if (!$this->default_return_type) { - $this->default_return_type = \think\Config::get('default_return_type'); - } - if (!$this->default_ajax_return) { - $this->default_ajax_return = \think\Config::get('default_ajax_return'); - } - } - - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - */ - protected function tearDown() - { - \think\Config::set('default_ajax_return', $this->default_ajax_return); - \think\Config::set('default_return_type', $this->default_return_type); - \think\Response::type(\think\Config::get('default_return_type')); // 会影响其他测试 - } - - /** - * @covers think\Response::send - * @todo Implement testSend(). - */ - public function testSend() - { - $dataArr = array(); - $dataArr["key"] = "value"; - $dataArr->key = "val"; - - $result = \think\Response::send($dataArr, "", true); - $this->assertArrayHasKey("key", $result); - - $result = \think\Response::send($dataArr, "json", true); - $this->assertEquals('{"key":"value"}', $result); - - $handler = "callback"; - $_GET[\think\Config::get('var_jsonp_handler')] = $handler; - $result = \think\Response::send($dataArr, "jsonp", true); - $this->assertEquals('callback({"key":"value"});', $result); - - \think\Response::tramsform(function () { - - return "callbackreturndata"; - }); - - $result = \think\Response::send($dataArr, "", true); - $this->assertEquals("callbackreturndata", $result); - $_GET[\think\Config::get('var_jsonp_handler')] = ""; - } - - /** - * @covers think\Response::tramsform - * @todo Implement testTramsform(). - */ - public function testTramsform() - { - \think\Response::tramsform(function () { - - return "callbackreturndata"; - }); - - $result = \think\Response::send($dataArr, "", true); - $this->assertEquals("callbackreturndata", $result); - - \think\Response::tramsform(null); - } - - /** - * @covers think\Response::type - * @todo Implement testType(). - */ - public function testType() - { - $type = "json"; - \think\Response::type($type); - - $result = \think\Response::type(); - $this->assertEquals($type, $result); - \think\Response::type($type); - } - - /** - * @covers think\Response::data - * @todo Implement testData(). - */ - public function testData() - { - $data = "data"; - \think\Response::data($data); - \think\Response::data(null); - } - - /** - * @covers think\Response::isExit - * @todo Implement testIsExit(). - */ - public function testIsExit() - { - $isExit = true; - \think\Response::isExit($isExit); - - $result = \think\Response::isExit(); - $this->assertTrue($isExit, $result); - \think\Response::isExit(false); - } - - /** - * @covers think\Response::result - * @todo Implement testResult(). - */ - public function testResult() - { - $data = "data"; - $code = "1001"; - $msg = "the msg"; - $type = "json"; - $result = \think\Response::result($data, $code, $msg, $type); - - $this->assertEquals($code, $result["code"]); - $this->assertEquals($msg, $result["msg"]); - $this->assertEquals($data, $result["data"]); - $this->assertEquals($_SERVER['REQUEST_TIME'], $result["time"]); - $this->assertEquals($type, \think\Response::type()); - } - - /** - * @covers think\Response::success - * @todo Implement testSuccess(). - */ - public function testSuccess() - { - // round 1 - $msg = 1001; - $data = "data"; - - $url = "www.HTTP_REFERER.com"; - $HTTP_REFERER = $_SERVER["HTTP_REFERER"]; - $_SERVER["HTTP_REFERER"] = $url; - \think\Config::set('default_return_type', "json"); - - $result = \think\Response::success($msg, $data); - - $this->assertEquals($msg, $result["code"]); - - $this->assertEquals($data, $result["data"]); - $this->assertEquals($url, $result["url"]); - $this->assertEquals("json", \think\Response::type()); - $this->assertEquals(3, $result["wait"]); - - // round 2 - $msg = "the msg"; - $url = "www.thinkphptestsucess.com"; - - $result = \think\Response::success($msg, $data, $url); - - $this->assertEquals($msg, $result["msg"]); - $this->assertEquals($url, $result["url"]); - - // round 3 异常在travis-ci中未能重现 - // $this->setExpectedException('\think\Exception'); - // FIXME 静态方法mock - // $oMockView = $this->getMockBuilder('\think\View')->setMethods(array( - // 'fetch' - // ))->getMock(); - - // $oMockView->expects($this->any())->method('fetch')->will($this->returnValue('content')); - - // \think\Config::set('default_return_type', "html"); - // $result = \think\Response::success($msg, $data, $url); - - // FIXME 静态方法mock - // $this->assertEquals('content', $result); - - $_SERVER["HTTP_REFERER"] = $HTTP_REFERER; - } - - /** - * @covers think\Response::error - * @todo Implement testError(). - */ - public function testError() - { - // round 1 - $msg = 1001; - $data = "data"; - - \think\Config::set('default_return_type', "json"); - - $result = \think\Response::error($msg, $data); - - $this->assertEquals($msg, $result["code"]); - $this->assertEquals($data, $result["data"]); - $this->assertEquals('javascript:history.back(-1);', $result["url"]); - $this->assertEquals("json", \think\Response::type()); - $this->assertEquals(3, $result["wait"]); - - // round 2 - $msg = "the msg"; - $url = "www.thinkphptesterror.com"; - - $result = \think\Response::error($msg, $data, $url); - - $this->assertEquals($msg, $result["msg"]); - $this->assertEquals($url, $result["url"]); - - // round 3 异常在travis-ci中未能重现 - // $this->setExpectedException('\think\Exception'); - // FIXME 静态方法mock - // $oMockView = $this->getMockBuilder('\think\View')->setMethods(array( - // 'fetch' - // ))->getMock(); - - // $oMockView->expects($this->any())->method('fetch')->will($this->returnValue('content')); - - // \think\Config::set('default_return_type', "html"); - - // $result = \think\Response::error($msg, $data, $url); - - // FIXME 静态方法mock - // $this->assertEquals('content', $result); - } - - /** - * @#runInSeparateProcess - * @covers think\Response::redirect - * @todo Implement testRedirect(). - */ - public function testRedirect() - { - // $url = "http://www.testredirect.com"; - // $params = array(); - // $params[] = 301; - - // // FIXME 静态方法mock Url::build - // // echo "\r\n" . json_encode(xdebug_get_headers()) . "\r\n"; - // \think\Response::redirect($url, $params); - - // $this->assertContains('Location: ' . $url, xdebug_get_headers()); - } - - /** - * @#runInSeparateProcess - * @covers think\Response::header - * @todo Implement testHeader(). - */ - public function testHeader() - { - // $name = "Location"; - // $url = "http://www.testheader.com/"; - // \think\Response::header($name, $url); - // $this->assertContains($name . ': ' . $url, xdebug_get_headers()); - } - -} diff --git a/thinkphp/tests/thinkphp/library/think/session/.gitignore b/thinkphp/tests/thinkphp/library/think/session/.gitignore deleted file mode 100644 index a3a0c8b5f..000000000 --- a/thinkphp/tests/thinkphp/library/think/session/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/thinkphp/tests/thinkphp/library/think/sessionTest.php b/thinkphp/tests/thinkphp/library/think/sessionTest.php deleted file mode 100644 index 65b429064..000000000 --- a/thinkphp/tests/thinkphp/library/think/sessionTest.php +++ /dev/null @@ -1,306 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * Session测试 - * @author 大漠 - */ - -namespace tests\thinkphp\library\think; - -class sessionTest extends \PHPUnit_Framework_TestCase -{ - - /** - * - * @var Session - */ - protected $object; - - /** - * Sets up the fixture, for example, opens a network connection. - * This method is called before a test is executed. - */ - protected function setUp() - { - // $this->object = new Session (); - // register_shutdown_function ( function () { - // } ); // 此功能无法取消,需要回调函数配合。 - set_exception_handler(function () {}); - set_error_handler(function () {}); - } - - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - */ - protected function tearDown() - { - register_shutdown_function('think\Error::appShutdown'); - set_error_handler('think\Error::appError'); - set_exception_handler('think\Error::appException'); - } - - /** - * @covers think\Session::prefix - * - * @todo Implement testPrefix(). - */ - public function testPrefix() - { - \think\Session::prefix(null); - \think\Session::prefix('think_'); - - $this->assertEquals('think_', \think\Session::prefix()); - } - - /** - * @covers think\Session::init - * - * @todo Implement testInit(). - */ - public function testInit() - { - \think\Session::prefix(null); - $config = [ - // cookie 名称前缀 - 'prefix' => 'think_', - // cookie 保存时间 - 'expire' => 60, - // cookie 保存路径 - 'path' => '/path/to/test/session/', - // cookie 有效域名 - 'domain' => '.thinkphp.cn', - 'var_session_id' => 'sessionidtest', - 'id' => 'sess_8fhgkjuakhatbeg2fa14lo84q1', - 'name' => 'session_name', - 'use_trans_sid' => '1', - 'use_cookies' => '1', - 'cache_limiter' => '60', - 'cache_expire' => '60', - 'type' => '', // memcache - 'namespace' => '\\think\\session\\driver\\', // ? - 'auto_start' => '1', - ]; - - $_REQUEST[$config['var_session_id']] = $config['id']; - \think\Session::init($config); - - // 开始断言 - $this->assertEquals($config['prefix'], \think\Session::prefix()); - $this->assertEquals($config['id'], $_REQUEST[$config['var_session_id']]); - $this->assertEquals($config['name'], session_name()); - - $this->assertEquals($config['path'], session_save_path()); - $this->assertEquals($config['use_cookies'], ini_get('session.use_cookies')); - $this->assertEquals($config['domain'], ini_get('session.cookie_domain')); - $this->assertEquals($config['expire'], ini_get('session.gc_maxlifetime')); - $this->assertEquals($config['expire'], ini_get('session.cookie_lifetime')); - - $this->assertEquals($config['cache_limiter'], session_cache_limiter($config['cache_limiter'])); - $this->assertEquals($config['cache_expire'], session_cache_expire($config['cache_expire'])); - - // 检测分支 - $_REQUEST[$config['var_session_id']] = null; - session_write_close(); - session_destroy(); - - \think\Session::init($config); - - // 测试auto_start - // PHP_SESSION_DISABLED - // PHP_SESSION_NONE - // PHP_SESSION_ACTIVE - // session_status() - $this->assertEquals(0, ini_get('session.auto_start')); - - $this->assertEquals($config['use_trans_sid'], ini_get('session.use_trans_sid')); - - \think\Session::init($config); - $this->assertEquals($config['id'], session_id()); - } - - /** - * 单独重现异常 - * @expectedException \think\Exception - */ - public function testException() - { - $config = [ - // cookie 名称前缀 - 'prefix' => 'think_', - // cookie 保存时间 - 'expire' => 0, - // cookie 保存路径 - 'path' => '/path/to/test/session/', - // cookie 有效域名 - 'domain' => '.thinkphp.cn', - 'var_session_id' => 'sessionidtest', - 'id' => 'sess_8fhgkjuakhatbeg2fa14lo84q1', - 'name' => 'session_name', - 'use_trans_sid' => '1', - 'use_cookies' => '1', - 'cache_limiter' => '60', - 'cache_expire' => '60', - 'type' => 'memcache', // - 'namespace' => '\\think\\session\\driver\\', // ? - 'auto_start' => '1', - ]; - - // 测试session驱动是否存在 - // @expectedException 异常类名 - $this->setExpectedException('\think\Exception', 'error session handler', 11700); - - \think\Session::init($config); - } - - /** - * @covers think\Session::set - * - * @todo Implement testSet(). - */ - public function testSet() - { - \think\Session::prefix(null); - \think\Session::set('sessionname', 'sessionvalue'); - $this->assertEquals('sessionvalue', $_SESSION['sessionname']); - - \think\Session::set('sessionnamearr.subname', 'sessionvalue'); - $this->assertEquals('sessionvalue', $_SESSION['sessionnamearr']['subname']); - - \think\Session::set('sessionnameper', 'sessionvalue', 'think_'); - $this->assertEquals('sessionvalue', $_SESSION['think_']['sessionnameper']); - - \think\Session::set('sessionnamearrper.subname', 'sessionvalue', 'think_'); - $this->assertEquals('sessionvalue', $_SESSION['think_']['sessionnamearrper']['subname']); - } - - /** - * @covers think\Session::get - * - * @todo Implement testGet(). - */ - public function testGet() - { - \think\Session::prefix(null); - - \think\Session::set('sessionnameget', 'sessionvalue'); - $this->assertEquals(\think\Session::get('sessionnameget'), $_SESSION['sessionnameget']); - - \think\Session::set('sessionnamegetarr.subname', 'sessionvalue'); - $this->assertEquals(\think\Session::get('sessionnamegetarr.subname'), $_SESSION['sessionnamegetarr']['subname']); - - \think\Session::set('sessionnamegetarrperall', 'sessionvalue', 'think_'); - $this->assertEquals(\think\Session::get('', 'think_')['sessionnamegetarrperall'], $_SESSION['think_']['sessionnamegetarrperall']); - - \think\Session::set('sessionnamegetper', 'sessionvalue', 'think_'); - $this->assertEquals(\think\Session::get('sessionnamegetper', 'think_'), $_SESSION['think_']['sessionnamegetper']); - - \think\Session::set('sessionnamegetarrper.subname', 'sessionvalue', 'think_'); - $this->assertEquals(\think\Session::get('sessionnamegetarrper.subname', 'think_'), $_SESSION['think_']['sessionnamegetarrper']['subname']); - } - - /** - * @covers think\Session::delete - * - * @todo Implement testDelete(). - */ - public function testDelete() - { - \think\Session::prefix(null); - \think\Session::set('sessionnamedel', 'sessionvalue'); - \think\Session::delete('sessionnamedel'); - $this->assertEmpty($_SESSION['sessionnamedel']); - - \think\Session::set('sessionnamedelarr.subname', 'sessionvalue'); - \think\Session::delete('sessionnamedelarr.subname'); - $this->assertEmpty($_SESSION['sessionnamedelarr']['subname']); - - \think\Session::set('sessionnamedelper', 'sessionvalue', 'think_'); - \think\Session::delete('sessionnamedelper', 'think_'); - $this->assertEmpty($_SESSION['think_']['sessionnamedelper']); - - \think\Session::set('sessionnamedelperarr.subname', 'sessionvalue', 'think_'); - \think\Session::delete('sessionnamedelperarr.subname', 'think_'); - $this->assertEmpty($_SESSION['think_']['sessionnamedelperarr']['subname']); - } - - /** - * @covers think\Session::clear - * - * @todo Implement testClear(). - */ - public function testClear() - { - \think\Session::prefix(null); - - \think\Session::set('sessionnameclsper', 'sessionvalue1', 'think_'); - \think\Session::clear('think_'); - $this->assertNull($_SESSION['think_']); - - \think\Session::set('sessionnameclsper', 'sessionvalue1', 'think_'); - \think\Session::clear(); - $this->assertEmpty($_SESSION); - } - - /** - * @covers think\Session::has - * - * @todo Implement testHas(). - */ - public function testHas() - { - \think\Session::prefix(null); - \think\Session::set('sessionnamehas', 'sessionvalue'); - $this->assertTrue(\think\Session::has('sessionnamehas')); - - \think\Session::set('sessionnamehasarr.subname', 'sessionvalue'); - $this->assertTrue(\think\Session::has('sessionnamehasarr.subname')); - - \think\Session::set('sessionnamehasper', 'sessionvalue', 'think_'); - $this->assertTrue(\think\Session::has('sessionnamehasper', 'think_')); - - \think\Session::set('sessionnamehasarrper.subname', 'sessionvalue', 'think_'); - $this->assertTrue(\think\Session::has('sessionnamehasarrper.subname', 'think_')); - } - - /** - * @covers think\Session::pause - * - * @todo Implement testPause(). - */ - public function testPause() - { - \think\Session::pause(); - } - - /** - * @covers think\Session::start - * - * @todo Implement testStart(). - */ - public function testStart() - { - \think\Session::start(); - } - - /** - * @covers think\Session::destroy - * - * @todo Implement testDestroy(). - */ - public function testDestroy() - { - \think\Session::set('sessionnamedestroy', 'sessionvalue'); - \think\Session::destroy(); - $this->assertEmpty($_SESSION['sessionnamedestroy']); - } -} diff --git a/thinkphp/tests/thinkphp/library/think/template/driver/.gitignore b/thinkphp/tests/thinkphp/library/think/template/driver/.gitignore deleted file mode 100644 index a3a0c8b5f..000000000 --- a/thinkphp/tests/thinkphp/library/think/template/driver/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/thinkphp/tests/thinkphp/library/think/template/taglib/.gitignore b/thinkphp/tests/thinkphp/library/think/template/taglib/.gitignore deleted file mode 100644 index a3a0c8b5f..000000000 --- a/thinkphp/tests/thinkphp/library/think/template/taglib/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/thinkphp/tests/thinkphp/library/think/templateTest.php b/thinkphp/tests/thinkphp/library/think/templateTest.php deleted file mode 100644 index 86240afc3..000000000 --- a/thinkphp/tests/thinkphp/library/think/templateTest.php +++ /dev/null @@ -1,264 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * 模板测试 - * @author Haotong Lin - */ - -namespace tests\thinkphp\library\think; - -use think\Template; - -class templateTest extends \PHPUnit_Framework_TestCase -{ - public function testVar() - { - $template = new Template(); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($content, $data); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($content, $data); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($content, $data); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($content, $data); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($content, $data); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($content, $data); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($content, $data); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($content, $data); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($content, $data); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($content, $data); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($content, $data); - - $content = <<parse($content); - $this->assertEquals($content, $data); - - } - - public function testVarIdentify() - { - $config['tpl_begin'] = '<#'; - $config['tpl_end'] = '#>'; - $config['tpl_var_identify'] = ''; - $template = new Template($config); - - $content = << -EOF; - $data = <<a) ? (is_array(\$info)?\$info['a']:\$info->a) : 'test'; ?> -EOF; - - $template->parse($content); - $this->assertEquals($content, $data); - - $content = << -EOF; - $data = <<a)==(is_array(\$info)?\$info['b']:\$info->b)) echo 'test'; ?> -EOF; - - $template->parse($content); - $this->assertEquals($content, $data); - - $content = << -EOF; - $data = <<a) !== ''?(is_array(\$info)?\$info['a']:\$info->a):'test')?'yes':'no'; ?> -EOF; - - $template->parse($content); - $this->assertEquals($content, $data); - } - - public function testTag() - { - $template = new Template(); - - $content = << -one - -two - -default - -EOF; - $template->parse($content); - $this->assertEquals($content, $data); - - $content = << - -a - - -b - - -default - -EOF; - $template->parse($content); - $this->assertEquals($content, $data); - - $content = <<\$val} - -{/foreach} -EOF; - $data = <<\$val): ?> - - -EOF; - $template->parse($content); - $this->assertEquals($content, $data); - - $content = <<\$val): ?> - - -EOF; - $template->parse($content); - $this->assertEquals($content, $data); - - } -} diff --git a/thinkphp/tests/thinkphp/library/think/view/driver/.gitignore b/thinkphp/tests/thinkphp/library/think/view/driver/.gitignore deleted file mode 100644 index a3a0c8b5f..000000000 --- a/thinkphp/tests/thinkphp/library/think/view/driver/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/thinkphp/tests/thinkphp/library/think/viewTest.php b/thinkphp/tests/thinkphp/library/think/viewTest.php deleted file mode 100644 index f284e8829..000000000 --- a/thinkphp/tests/thinkphp/library/think/viewTest.php +++ /dev/null @@ -1,142 +0,0 @@ - -// +---------------------------------------------------------------------- - -/** - * view测试 - * @author mahuan - */ - -namespace tests\thinkphp\library\think; - -class viewTest extends \PHPUnit_Framework_TestCase -{ - - /** - * 句柄测试 - * @return mixed - * @access public - */ - public function testGetInstance() - { - \think\Cookie::get('a'); - $view_instance = \think\View::instance(); - $this->assertInstanceOf('\think\view', $view_instance, 'instance方法返回错误'); - } - - /** - * 测试变量赋值 - * @return mixed - * @access public - */ - public function testAssign() - { - $view_instance = \think\View::instance(); - $data = $view_instance->assign(array('key' => 'value')); - $data = $view_instance->assign('key2', 'value2'); - //测试私有属性 - $expect_data = array('key' => 'value', 'key2' => 'value2'); - $this->assertAttributeEquals($expect_data, 'data', $view_instance); - } - - /** - * 测试配置 - * @return mixed - * @access public - */ - public function testConfig() - { - $view_instance = \think\View::instance(); - $data = $view_instance->config('key2', 'value2'); - $data = $view_instance->config('key3', 'value3'); - $data = $view_instance->config('key3', 'value_cover'); - //不应包含value - $data = $view_instance->config(array('key' => 'value')); - //基础配置替换 - $data = $view_instance->config(array('view_path' => 'view_path')); - //目标结果 - $this->assertAttributeContains('value2', "config", $view_instance); - $this->assertAttributeContains('value_cover', "config", $view_instance); - $this->assertAttributeNotContains('value', "config", $view_instance); - $this->assertAttributeContains('view_path', "config", $view_instance); - } - - /** - * 测试引擎设置 - * @return mixed - * @access public - */ - public function testEngine() - { - $view_instance = \think\View::instance(); - $data = $view_instance->engine('php'); - $this->assertAttributeEquals('php', 'engine', $view_instance); - //测试模板引擎驱动 - $data = $view_instance->engine('think'); - $think_engine = new \think\view\driver\Think; - $this->assertAttributeEquals($think_engine, 'engine', $view_instance); - } - - /** - * 测试引擎设置 - * @return mixed - * @access public - */ - public function testTheme() - { - $view_instance = \think\View::instance(); - $data = $view_instance->theme(true); - //反射类取出私有属性的值 - $reflection = new \ReflectionClass('\think\View'); - $property = $reflection->getProperty('config'); - $property->setAccessible(true); - $config_value = $property->getValue($view_instance); - - $this->assertTrue($config_value['theme_on']); - $this->assertTrue($config_value['auto_detect_theme']); - - //关闭主题测试 - $data = $view_instance->theme(false); - $config_value = $property->getValue($view_instance); - $this->assertFalse($config_value['theme_on']); - - //指定主题测试 - $data = $view_instance->theme('theme_name'); - $config_value = $property->getValue($view_instance); - $this->assertTrue($config_value['theme_on']); - $this->assertAttributeEquals('theme_name', 'theme', $view_instance); - } - - /** - * 测试引擎设置 - * @return mixed - * @access public - */ - public function testParseTemplate() - { - $view_instance = \think\View::instance(); - $method = new \ReflectionMethod('\think\View', 'ParseTemplate'); - $method->setAccessible(true); - $this->assertEquals('/theme_name/index/template_name.html', $method->invoke($view_instance, 'template_name')); - } - - /** - * 测试引擎设置 - * @return mixed - * @access public - */ - public function testGetThemePath() - { - $view_instance = \think\View::instance(); - $method = new \ReflectionMethod('\think\View', 'getThemePath'); - $method->setAccessible(true); - $this->assertEquals('/theme_name/', $method->invoke($view_instance)); - } -} diff --git a/thinkphp/tests/thinkphp/library/traits/controller/.gitignore b/thinkphp/tests/thinkphp/library/traits/controller/.gitignore deleted file mode 100644 index a3a0c8b5f..000000000 --- a/thinkphp/tests/thinkphp/library/traits/controller/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/thinkphp/tests/thinkphp/library/traits/model/.gitignore b/thinkphp/tests/thinkphp/library/traits/model/.gitignore deleted file mode 100644 index a3a0c8b5f..000000000 --- a/thinkphp/tests/thinkphp/library/traits/model/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/thinkphp/tpl/default_index.tpl b/thinkphp/tpl/default_index.tpl deleted file mode 100644 index ad74ac029..000000000 --- a/thinkphp/tpl/default_index.tpl +++ /dev/null @@ -1,10 +0,0 @@ -*{ padding: 0; margin: 0; } div{ padding: 4px 48px;} body{ background: #fff; font-family: "微软雅黑"; color: #333;} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.8em; font-size: 36px }

:)

欢迎使用 ThinkPHP5

'; - } -} diff --git a/thinkphp/tpl/dispatch_jump.tpl b/thinkphp/tpl/dispatch_jump.tpl deleted file mode 100644 index 9b568fa11..000000000 --- a/thinkphp/tpl/dispatch_jump.tpl +++ /dev/null @@ -1,48 +0,0 @@ - - - - - 跳转提示 - - - -
- - -

:)

-

- - -

:(

-

- - -

-

- 页面自动 跳转 等待时间: -

-
- - - diff --git a/thinkphp/tpl/page_trace.tpl b/thinkphp/tpl/page_trace.tpl deleted file mode 100644 index c1c2f2489..000000000 --- a/thinkphp/tpl/page_trace.tpl +++ /dev/null @@ -1,71 +0,0 @@ -
- - -
-
-
- -
- - diff --git a/thinkphp/tpl/think_exception.tpl b/thinkphp/tpl/think_exception.tpl deleted file mode 100644 index 31b77249e..000000000 --- a/thinkphp/tpl/think_exception.tpl +++ /dev/null @@ -1,53 +0,0 @@ - - - -系统发生错误 - - - -
-

:(

-

[ '.$e['code'].' ] ';} echo strip_tags($e['message']);?>

-
- -
-
-

错误位置

-
-
-

FILE:  LINE:

-
-
- - -
-
-

追溯信息

-
-
-

-
-
- -
-
- - - diff --git a/thinkphp/tests/thinkphp/library/think/controller/.gitignore b/vendor/.gitignore similarity index 92% rename from thinkphp/tests/thinkphp/library/think/controller/.gitignore rename to vendor/.gitignore index a3a0c8b5f..c96a04f00 100644 --- a/thinkphp/tests/thinkphp/library/think/controller/.gitignore +++ b/vendor/.gitignore @@ -1,2 +1,2 @@ -* +* !.gitignore \ No newline at end of file