Showing
17 changed files
with
4808 additions
and
0 deletions
Too many changes to show.
To preserve performance only 17 of 17+ files are displayed.
thinkphp/.gitignore
0 → 100644
thinkphp/.htaccess
0 → 100644
| 1 | +deny from all |
thinkphp/CONTRIBUTING.md
0 → 100644
| 1 | +如何贡献我的源代码 | ||
| 2 | +=== | ||
| 3 | + | ||
| 4 | +此文档介绍了 ThinkPHP 团队的组成以及运转机制,您提交的代码将给 ThinkPHP 项目带来什么好处,以及如何才能加入我们的行列。 | ||
| 5 | + | ||
| 6 | +## 通过 Github 贡献代码 | ||
| 7 | + | ||
| 8 | +ThinkPHP 目前使用 Git 来控制程序版本,如果你想为 ThinkPHP 贡献源代码,请先大致了解 Git 的使用方法。我们目前把项目托管在 GitHub 上,任何 GitHub 用户都可以向我们贡献代码。 | ||
| 9 | + | ||
| 10 | +参与的方式很简单,`fork`一份 ThinkPHP 的代码到你的仓库中,修改后提交,并向我们发起`pull request`申请,我们会及时对代码进行审查并处理你的申请并。审查通过后,你的代码将被`merge`进我们的仓库中,这样你就会自动出现在贡献者名单里了,非常方便。 | ||
| 11 | + | ||
| 12 | +我们希望你贡献的代码符合: | ||
| 13 | + | ||
| 14 | +* ThinkPHP 的编码规范 | ||
| 15 | +* 适当的注释,能让其他人读懂 | ||
| 16 | +* 遵循 Apache2 开源协议 | ||
| 17 | + | ||
| 18 | +**如果想要了解更多细节或有任何疑问,请继续阅读下面的内容** | ||
| 19 | + | ||
| 20 | +### 注意事项 | ||
| 21 | + | ||
| 22 | +* 本项目代码格式化标准选用 [**PSR-2**](http://www.kancloud.cn/thinkphp/php-fig-psr/3141); | ||
| 23 | +* 类名和类文件名遵循 [**PSR-4**](http://www.kancloud.cn/thinkphp/php-fig-psr/3144); | ||
| 24 | +* 对于 Issues 的处理,请使用诸如 `fix #xxx(Issue ID)` 的 commit title 直接关闭 issue。 | ||
| 25 | +* 系统会自动在 PHP 5.4 5.5 5.6 7.0 和 HHVM 上测试修改,其中 HHVM 下的测试容许报错,请确保你的修改符合 PHP 5.4 ~ 5.6 和 PHP 7.0 的语法规范; | ||
| 26 | +* 管理员不会合并造成 CI faild 的修改,若出现 CI faild 请检查自己的源代码或修改相应的[单元测试文件](tests); | ||
| 27 | + | ||
| 28 | +## GitHub Issue | ||
| 29 | + | ||
| 30 | +GitHub 提供了 Issue 功能,该功能可以用于: | ||
| 31 | + | ||
| 32 | +* 提出 bug | ||
| 33 | +* 提出功能改进 | ||
| 34 | +* 反馈使用体验 | ||
| 35 | + | ||
| 36 | +该功能不应该用于: | ||
| 37 | + | ||
| 38 | + * 提出修改意见(涉及代码署名和修订追溯问题) | ||
| 39 | + * 不友善的言论 | ||
| 40 | + | ||
| 41 | +## 快速修改 | ||
| 42 | + | ||
| 43 | +**GitHub 提供了快速编辑文件的功能** | ||
| 44 | + | ||
| 45 | +1. 登录 GitHub 帐号; | ||
| 46 | +2. 浏览项目文件,找到要进行修改的文件; | ||
| 47 | +3. 点击右上角铅笔图标进行修改; | ||
| 48 | +4. 填写 `Commit changes` 相关内容(Title 必填); | ||
| 49 | +5. 提交修改,等待 CI 验证和管理员合并。 | ||
| 50 | + | ||
| 51 | +**若您需要一次提交大量修改,请继续阅读下面的内容** | ||
| 52 | + | ||
| 53 | +## 完整流程 | ||
| 54 | + | ||
| 55 | +1. `fork`本项目; | ||
| 56 | +2. 克隆(`clone`)你 `fork` 的项目到本地; | ||
| 57 | +3. 新建分支(`branch`)并检出(`checkout`)新分支; | ||
| 58 | +4. 添加本项目到你的本地 git 仓库作为上游(`upstream`); | ||
| 59 | +5. 进行修改,若你的修改包含方法或函数的增减,请记得修改[单元测试文件](tests); | ||
| 60 | +6. 变基(衍合 `rebase`)你的分支到上游 master 分支; | ||
| 61 | +7. `push` 你的本地仓库到 GitHub; | ||
| 62 | +8. 提交 `pull request`; | ||
| 63 | +9. 等待 CI 验证(若不通过则重复 5~7,GitHub 会自动更新你的 `pull request`); | ||
| 64 | +10. 等待管理员处理,并及时 `rebase` 你的分支到上游 master 分支(若上游 master 分支有修改)。 | ||
| 65 | + | ||
| 66 | +*若有必要,可以 `git push -f` 强行推送 rebase 后的分支到自己的 `fork`* | ||
| 67 | + | ||
| 68 | +*绝对不可以使用 `git push -f` 强行推送修改到上游* | ||
| 69 | + | ||
| 70 | +### 注意事项 | ||
| 71 | + | ||
| 72 | +* 若对上述流程有任何不清楚的地方,请查阅 GIT 教程,如 [这个](http://backlogtool.com/git-guide/cn/); | ||
| 73 | +* 对于代码**不同方面**的修改,请在自己 `fork` 的项目中**创建不同的分支**(原因参见`完整流程`第9条备注部分); | ||
| 74 | +* 变基及交互式变基操作参见 [Git 交互式变基](http://pakchoi.me/2015/03/17/git-interactive-rebase/) | ||
| 75 | + | ||
| 76 | +## 推荐资源 | ||
| 77 | + | ||
| 78 | +### 开发环境 | ||
| 79 | + | ||
| 80 | +* XAMPP for Windows 5.5.x | ||
| 81 | +* WampServer (for Windows) | ||
| 82 | +* upupw Apache PHP5.4 ( for Windows) | ||
| 83 | + | ||
| 84 | +或自行安装 | ||
| 85 | + | ||
| 86 | +- Apache / Nginx | ||
| 87 | +- PHP 5.4 ~ 5.6 | ||
| 88 | +- MySQL / MariaDB | ||
| 89 | + | ||
| 90 | +*Windows 用户推荐添加 PHP bin 目录到 PATH,方便使用 composer* | ||
| 91 | + | ||
| 92 | +*Linux 用户自行配置环境, Mac 用户推荐使用内置 Apache 配合 Homebrew 安装 PHP 和 MariaDB* | ||
| 93 | + | ||
| 94 | +### 编辑器 | ||
| 95 | + | ||
| 96 | +Sublime Text 3 + phpfmt 插件 | ||
| 97 | + | ||
| 98 | +phpfmt 插件参数 | ||
| 99 | + | ||
| 100 | +```json | ||
| 101 | +{ | ||
| 102 | + "autocomplete": true, | ||
| 103 | + "enable_auto_align": true, | ||
| 104 | + "format_on_save": true, | ||
| 105 | + "indent_with_space": true, | ||
| 106 | + "psr1_naming": false, | ||
| 107 | + "psr2": true, | ||
| 108 | + "version": 4 | ||
| 109 | +} | ||
| 110 | +``` | ||
| 111 | + | ||
| 112 | +或其他 编辑器 / IDE 配合 PSR2 自动格式化工具 | ||
| 113 | + | ||
| 114 | +### Git GUI | ||
| 115 | + | ||
| 116 | +* SourceTree | ||
| 117 | +* GitHub Desktop | ||
| 118 | + | ||
| 119 | +或其他 Git 图形界面客户端 |
thinkphp/LICENSE.txt
0 → 100644
| 1 | + | ||
| 2 | +ThinkPHP遵循Apache2开源协议发布,并提供免费使用。 | ||
| 3 | +版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn) | ||
| 4 | +All rights reserved。 | ||
| 5 | +ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。 | ||
| 6 | + | ||
| 7 | +Apache Licence是著名的非盈利开源组织Apache采用的协议。 | ||
| 8 | +该协议和BSD类似,鼓励代码共享和尊重原作者的著作权, | ||
| 9 | +允许代码修改,再作为开源或商业软件发布。需要满足 | ||
| 10 | +的条件: | ||
| 11 | +1. 需要给代码的用户一份Apache Licence ; | ||
| 12 | +2. 如果你修改了代码,需要在被修改的文件中说明; | ||
| 13 | +3. 在延伸的代码中(修改和有源代码衍生的代码中)需要 | ||
| 14 | +带有原来代码中的协议,商标,专利声明和其他原来作者规 | ||
| 15 | +定需要包含的说明; | ||
| 16 | +4. 如果再发布的产品中包含一个Notice文件,则在Notice文 | ||
| 17 | +件中需要带有本协议内容。你可以在Notice中增加自己的 | ||
| 18 | +许可,但不可以表现为对Apache Licence构成更改。 | ||
| 19 | +具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0 | ||
| 20 | + | ||
| 21 | +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 22 | +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 23 | +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||
| 24 | +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | ||
| 25 | +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
| 26 | +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
| 27 | +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
| 28 | +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
| 29 | +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 30 | +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | ||
| 31 | +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
| 32 | +POSSIBILITY OF SUCH DAMAGE. |
thinkphp/README.md
0 → 100644
| 1 | + | ||
| 2 | + | ||
| 3 | +ThinkPHP 5.1 —— 12载初心,你值得信赖的PHP框架 | ||
| 4 | +=============== | ||
| 5 | + | ||
| 6 | +[](https://scrutinizer-ci.com/g/top-think/framework/?branch=5.1) | ||
| 7 | +[](https://travis-ci.org/top-think/framework) | ||
| 8 | +[](https://packagist.org/packages/topthink/framework) | ||
| 9 | +[](https://packagist.org/packages/topthink/framework) | ||
| 10 | +[](http://www.php.net/) | ||
| 11 | +[](https://packagist.org/packages/topthink/framework) | ||
| 12 | + | ||
| 13 | +ThinkPHP5.1对底层架构做了进一步的改进,减少依赖,其主要特性包括: | ||
| 14 | + | ||
| 15 | + + 采用容器统一管理对象 | ||
| 16 | + + 支持Facade | ||
| 17 | + + 更易用的路由 | ||
| 18 | + + 注解路由支持 | ||
| 19 | + + 路由跨域请求支持 | ||
| 20 | + + 验证类增强 | ||
| 21 | + + 配置和路由目录独立 | ||
| 22 | + + 取消系统常量 | ||
| 23 | + + 类库别名机制 | ||
| 24 | + + 模型和数据库增强 | ||
| 25 | + + 依赖注入完善 | ||
| 26 | + + 支持PSR-3日志规范 | ||
| 27 | + + 中间件支持(`V5.1.6+`) | ||
| 28 | + + 支持`Swoole`/`Workerman`运行(`V5.1.18+`) | ||
| 29 | + | ||
| 30 | + | ||
| 31 | +### 废除的功能: | ||
| 32 | + | ||
| 33 | + + 聚合模型 | ||
| 34 | + + 内置控制器扩展类 | ||
| 35 | + + 模型自动验证 | ||
| 36 | + | ||
| 37 | +> ThinkPHP5.1的运行环境要求PHP5.6+。 | ||
| 38 | + | ||
| 39 | +## 安装 | ||
| 40 | + | ||
| 41 | +使用composer安装 | ||
| 42 | + | ||
| 43 | +~~~ | ||
| 44 | +composer create-project topthink/think tp | ||
| 45 | +~~~ | ||
| 46 | + | ||
| 47 | +启动服务 | ||
| 48 | + | ||
| 49 | +~~~ | ||
| 50 | +cd tp | ||
| 51 | +php think run | ||
| 52 | +~~~ | ||
| 53 | + | ||
| 54 | +然后就可以在浏览器中访问 | ||
| 55 | + | ||
| 56 | +~~~ | ||
| 57 | +http://localhost:8000 | ||
| 58 | +~~~ | ||
| 59 | + | ||
| 60 | +更新框架 | ||
| 61 | +~~~ | ||
| 62 | +composer update topthink/framework | ||
| 63 | +~~~ | ||
| 64 | + | ||
| 65 | + | ||
| 66 | +## 在线手册 | ||
| 67 | + | ||
| 68 | ++ [完全开发手册](https://www.kancloud.cn/manual/thinkphp5_1/content) | ||
| 69 | ++ [升级指导](https://www.kancloud.cn/manual/thinkphp5_1/354155) | ||
| 70 | + | ||
| 71 | +## 命名规范 | ||
| 72 | + | ||
| 73 | +`ThinkPHP5.1`遵循PSR-2命名规范和PSR-4自动加载规范。 | ||
| 74 | + | ||
| 75 | +## 参与开发 | ||
| 76 | + | ||
| 77 | +请参阅 [ThinkPHP5 核心框架包](https://github.com/top-think/framework)。 | ||
| 78 | + | ||
| 79 | +## 版权信息 | ||
| 80 | + | ||
| 81 | +ThinkPHP遵循Apache2开源协议发布,并提供免费使用。 | ||
| 82 | + | ||
| 83 | +本项目包含的第三方源码和二进制文件之版权信息另行标注。 | ||
| 84 | + | ||
| 85 | +版权所有Copyright © 2006-2018 by ThinkPHP (http://thinkphp.cn) | ||
| 86 | + | ||
| 87 | +All rights reserved。 | ||
| 88 | + | ||
| 89 | +ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。 | ||
| 90 | + | ||
| 91 | +更多细节参阅 [LICENSE.txt](LICENSE.txt) |
thinkphp/base.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// +---------------------------------------------------------------------- | ||
| 3 | +// | ThinkPHP [ WE CAN DO IT JUST THINK ] | ||
| 4 | +// +---------------------------------------------------------------------- | ||
| 5 | +// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved. | ||
| 6 | +// +---------------------------------------------------------------------- | ||
| 7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
| 8 | +// +---------------------------------------------------------------------- | ||
| 9 | +// | Author: liu21st <liu21st@gmail.com> | ||
| 10 | +// +---------------------------------------------------------------------- | ||
| 11 | +namespace think; | ||
| 12 | + | ||
| 13 | +// 载入Loader类 | ||
| 14 | +require __DIR__ . '/library/think/Loader.php'; | ||
| 15 | + | ||
| 16 | +// 注册自动加载 | ||
| 17 | +Loader::register(); | ||
| 18 | + | ||
| 19 | +// 注册错误和异常处理机制 | ||
| 20 | +Error::register(); | ||
| 21 | + | ||
| 22 | +// 实现日志接口 | ||
| 23 | +if (interface_exists('Psr\Log\LoggerInterface')) { | ||
| 24 | + interface LoggerInterface extends \Psr\Log\LoggerInterface | ||
| 25 | + {} | ||
| 26 | +} else { | ||
| 27 | + interface LoggerInterface | ||
| 28 | + {} | ||
| 29 | +} | ||
| 30 | + | ||
| 31 | +// 注册类库别名 | ||
| 32 | +Loader::addClassAlias([ | ||
| 33 | + 'App' => facade\App::class, | ||
| 34 | + 'Build' => facade\Build::class, | ||
| 35 | + 'Cache' => facade\Cache::class, | ||
| 36 | + 'Config' => facade\Config::class, | ||
| 37 | + 'Cookie' => facade\Cookie::class, | ||
| 38 | + 'Db' => Db::class, | ||
| 39 | + 'Debug' => facade\Debug::class, | ||
| 40 | + 'Env' => facade\Env::class, | ||
| 41 | + 'Facade' => Facade::class, | ||
| 42 | + 'Hook' => facade\Hook::class, | ||
| 43 | + 'Lang' => facade\Lang::class, | ||
| 44 | + 'Log' => facade\Log::class, | ||
| 45 | + 'Request' => facade\Request::class, | ||
| 46 | + 'Response' => facade\Response::class, | ||
| 47 | + 'Route' => facade\Route::class, | ||
| 48 | + 'Session' => facade\Session::class, | ||
| 49 | + 'Url' => facade\Url::class, | ||
| 50 | + 'Validate' => facade\Validate::class, | ||
| 51 | + 'View' => facade\View::class, | ||
| 52 | +]); |
thinkphp/composer.json
0 → 100644
| 1 | +{ | ||
| 2 | + "name": "topthink/framework", | ||
| 3 | + "description": "the new thinkphp framework", | ||
| 4 | + "type": "think-framework", | ||
| 5 | + "keywords": [ | ||
| 6 | + "framework", | ||
| 7 | + "thinkphp", | ||
| 8 | + "ORM" | ||
| 9 | + ], | ||
| 10 | + "homepage": "http://thinkphp.cn/", | ||
| 11 | + "license": "Apache-2.0", | ||
| 12 | + "authors": [ | ||
| 13 | + { | ||
| 14 | + "name": "liu21st", | ||
| 15 | + "email": "liu21st@gmail.com" | ||
| 16 | + }, | ||
| 17 | + { | ||
| 18 | + "name": "yunwuxin", | ||
| 19 | + "email": "448901948@qq.com" | ||
| 20 | + } | ||
| 21 | + ], | ||
| 22 | + "require": { | ||
| 23 | + "php": ">=5.6.0", | ||
| 24 | + "topthink/think-installer": "2.*" | ||
| 25 | + }, | ||
| 26 | + "require-dev": { | ||
| 27 | + "phpunit/phpunit": "^5.0|^6.0", | ||
| 28 | + "johnkary/phpunit-speedtrap": "^1.0", | ||
| 29 | + "mikey179/vfsStream": "~1.6", | ||
| 30 | + "phploc/phploc": "2.*", | ||
| 31 | + "sebastian/phpcpd": "2.*", | ||
| 32 | + "squizlabs/php_codesniffer": "2.*", | ||
| 33 | + "phpdocumentor/reflection-docblock": "^2.0" | ||
| 34 | + } | ||
| 35 | +} |
thinkphp/convention.php
0 → 100644
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +return [ | ||
| 4 | + // +---------------------------------------------------------------------- | ||
| 5 | + // | 应用设置 | ||
| 6 | + // +---------------------------------------------------------------------- | ||
| 7 | + 'app' => [ | ||
| 8 | + // 应用名称 | ||
| 9 | + 'app_name' => '', | ||
| 10 | + // 应用地址 | ||
| 11 | + 'app_host' => '', | ||
| 12 | + // 应用调试模式 | ||
| 13 | + 'app_debug' => false, | ||
| 14 | + // 应用Trace | ||
| 15 | + 'app_trace' => false, | ||
| 16 | + // 应用模式状态 | ||
| 17 | + 'app_status' => '', | ||
| 18 | + // 是否HTTPS | ||
| 19 | + 'is_https' => false, | ||
| 20 | + // 入口自动绑定模块 | ||
| 21 | + 'auto_bind_module' => false, | ||
| 22 | + // 注册的根命名空间 | ||
| 23 | + 'root_namespace' => [], | ||
| 24 | + // 默认输出类型 | ||
| 25 | + 'default_return_type' => 'html', | ||
| 26 | + // 默认AJAX 数据返回格式,可选json xml ... | ||
| 27 | + 'default_ajax_return' => 'json', | ||
| 28 | + // 默认JSONP格式返回的处理方法 | ||
| 29 | + 'default_jsonp_handler' => 'jsonpReturn', | ||
| 30 | + // 默认JSONP处理方法 | ||
| 31 | + 'var_jsonp_handler' => 'callback', | ||
| 32 | + // 默认时区 | ||
| 33 | + 'default_timezone' => 'Asia/Shanghai', | ||
| 34 | + // 是否开启多语言 | ||
| 35 | + 'lang_switch_on' => false, | ||
| 36 | + // 默认验证器 | ||
| 37 | + 'default_validate' => '', | ||
| 38 | + // 默认语言 | ||
| 39 | + 'default_lang' => 'zh-cn', | ||
| 40 | + | ||
| 41 | + // +---------------------------------------------------------------------- | ||
| 42 | + // | 模块设置 | ||
| 43 | + // +---------------------------------------------------------------------- | ||
| 44 | + | ||
| 45 | + // 自动搜索控制器 | ||
| 46 | + 'controller_auto_search' => false, | ||
| 47 | + // 操作方法前缀 | ||
| 48 | + 'use_action_prefix' => false, | ||
| 49 | + // 操作方法后缀 | ||
| 50 | + 'action_suffix' => '', | ||
| 51 | + // 默认的空控制器名 | ||
| 52 | + 'empty_controller' => 'Error', | ||
| 53 | + // 默认的空模块名 | ||
| 54 | + 'empty_module' => '', | ||
| 55 | + // 默认模块名 | ||
| 56 | + 'default_module' => 'index', | ||
| 57 | + // 是否支持多模块 | ||
| 58 | + 'app_multi_module' => true, | ||
| 59 | + // 禁止访问模块 | ||
| 60 | + 'deny_module_list' => ['common'], | ||
| 61 | + // 默认控制器名 | ||
| 62 | + 'default_controller' => 'Index', | ||
| 63 | + // 默认操作名 | ||
| 64 | + 'default_action' => 'index', | ||
| 65 | + // 是否自动转换URL中的控制器和操作名 | ||
| 66 | + 'url_convert' => true, | ||
| 67 | + // 默认的访问控制器层 | ||
| 68 | + 'url_controller_layer' => 'controller', | ||
| 69 | + // 应用类库后缀 | ||
| 70 | + 'class_suffix' => false, | ||
| 71 | + // 控制器类后缀 | ||
| 72 | + 'controller_suffix' => false, | ||
| 73 | + | ||
| 74 | + // +---------------------------------------------------------------------- | ||
| 75 | + // | URL请求设置 | ||
| 76 | + // +---------------------------------------------------------------------- | ||
| 77 | + | ||
| 78 | + // 默认全局过滤方法 用逗号分隔多个 | ||
| 79 | + 'default_filter' => '', | ||
| 80 | + // PATHINFO变量名 用于兼容模式 | ||
| 81 | + 'var_pathinfo' => 's', | ||
| 82 | + // 兼容PATH_INFO获取 | ||
| 83 | + 'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'], | ||
| 84 | + // HTTPS代理标识 | ||
| 85 | + 'https_agent_name' => '', | ||
| 86 | + // IP代理获取标识 | ||
| 87 | + 'http_agent_ip' => 'HTTP_X_REAL_IP', | ||
| 88 | + // URL伪静态后缀 | ||
| 89 | + 'url_html_suffix' => 'html', | ||
| 90 | + // 域名根,如thinkphp.cn | ||
| 91 | + 'url_domain_root' => '', | ||
| 92 | + // 表单请求类型伪装变量 | ||
| 93 | + 'var_method' => '_method', | ||
| 94 | + // 表单ajax伪装变量 | ||
| 95 | + 'var_ajax' => '_ajax', | ||
| 96 | + // 表单pjax伪装变量 | ||
| 97 | + 'var_pjax' => '_pjax', | ||
| 98 | + // 是否开启请求缓存 true自动缓存 支持设置请求缓存规则 | ||
| 99 | + 'request_cache' => false, | ||
| 100 | + // 请求缓存有效期 | ||
| 101 | + 'request_cache_expire' => null, | ||
| 102 | + // 全局请求缓存排除规则 | ||
| 103 | + 'request_cache_except' => [], | ||
| 104 | + | ||
| 105 | + // +---------------------------------------------------------------------- | ||
| 106 | + // | 路由设置 | ||
| 107 | + // +---------------------------------------------------------------------- | ||
| 108 | + | ||
| 109 | + // pathinfo分隔符 | ||
| 110 | + 'pathinfo_depr' => '/', | ||
| 111 | + // URL普通方式参数 用于自动生成 | ||
| 112 | + 'url_common_param' => false, | ||
| 113 | + // URL参数方式 0 按名称成对解析 1 按顺序解析 | ||
| 114 | + 'url_param_type' => 0, | ||
| 115 | + // 是否开启路由延迟解析 | ||
| 116 | + 'url_lazy_route' => false, | ||
| 117 | + // 是否强制使用路由 | ||
| 118 | + 'url_route_must' => false, | ||
| 119 | + // 合并路由规则 | ||
| 120 | + 'route_rule_merge' => false, | ||
| 121 | + // 路由是否完全匹配 | ||
| 122 | + 'route_complete_match' => false, | ||
| 123 | + // 使用注解路由 | ||
| 124 | + 'route_annotation' => false, | ||
| 125 | + // 默认的路由变量规则 | ||
| 126 | + 'default_route_pattern' => '\w+', | ||
| 127 | + // 是否开启路由缓存 | ||
| 128 | + 'route_check_cache' => false, | ||
| 129 | + // 路由缓存的Key自定义设置(闭包),默认为当前URL和请求类型的md5 | ||
| 130 | + 'route_check_cache_key' => '', | ||
| 131 | + | ||
| 132 | + // +---------------------------------------------------------------------- | ||
| 133 | + // | 异常及错误设置 | ||
| 134 | + // +---------------------------------------------------------------------- | ||
| 135 | + | ||
| 136 | + // 默认跳转页面对应的模板文件 | ||
| 137 | + 'dispatch_success_tmpl' => __DIR__ . '/tpl/dispatch_jump.tpl', | ||
| 138 | + 'dispatch_error_tmpl' => __DIR__ . '/tpl/dispatch_jump.tpl', | ||
| 139 | + // 异常页面的模板文件 | ||
| 140 | + 'exception_tmpl' => __DIR__ . '/tpl/think_exception.tpl', | ||
| 141 | + // 错误显示信息,非调试模式有效 | ||
| 142 | + 'error_message' => '页面错误!请稍后再试~', | ||
| 143 | + // 显示错误信息 | ||
| 144 | + 'show_error_msg' => false, | ||
| 145 | + // 异常处理handle类 留空使用 \think\exception\Handle | ||
| 146 | + 'exception_handle' => '', | ||
| 147 | + ], | ||
| 148 | + | ||
| 149 | + // +---------------------------------------------------------------------- | ||
| 150 | + // | 模板设置 | ||
| 151 | + // +---------------------------------------------------------------------- | ||
| 152 | + | ||
| 153 | + 'template' => [ | ||
| 154 | + // 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 | ||
| 155 | + 'auto_rule' => 1, | ||
| 156 | + // 模板引擎类型 支持 php think 支持扩展 | ||
| 157 | + 'type' => 'Think', | ||
| 158 | + // 视图基础目录,配置目录为所有模块的视图起始目录 | ||
| 159 | + 'view_base' => '', | ||
| 160 | + // 当前模板的视图目录 留空为自动获取 | ||
| 161 | + 'view_path' => '', | ||
| 162 | + // 模板后缀 | ||
| 163 | + 'view_suffix' => 'html', | ||
| 164 | + // 模板文件名分隔符 | ||
| 165 | + 'view_depr' => DIRECTORY_SEPARATOR, | ||
| 166 | + // 模板引擎普通标签开始标记 | ||
| 167 | + 'tpl_begin' => '{', | ||
| 168 | + // 模板引擎普通标签结束标记 | ||
| 169 | + 'tpl_end' => '}', | ||
| 170 | + // 标签库标签开始标记 | ||
| 171 | + 'taglib_begin' => '{', | ||
| 172 | + // 标签库标签结束标记 | ||
| 173 | + 'taglib_end' => '}', | ||
| 174 | + ], | ||
| 175 | + | ||
| 176 | + // +---------------------------------------------------------------------- | ||
| 177 | + // | 日志设置 | ||
| 178 | + // +---------------------------------------------------------------------- | ||
| 179 | + | ||
| 180 | + 'log' => [ | ||
| 181 | + // 日志记录方式,内置 file socket 支持扩展 | ||
| 182 | + 'type' => 'File', | ||
| 183 | + // 日志保存目录 | ||
| 184 | + //'path' => LOG_PATH, | ||
| 185 | + // 日志记录级别 | ||
| 186 | + 'level' => [], | ||
| 187 | + // 是否记录trace信息到日志 | ||
| 188 | + 'record_trace' => false, | ||
| 189 | + // 是否JSON格式记录 | ||
| 190 | + 'json' => false, | ||
| 191 | + ], | ||
| 192 | + | ||
| 193 | + // +---------------------------------------------------------------------- | ||
| 194 | + // | Trace设置 开启 app_trace 后 有效 | ||
| 195 | + // +---------------------------------------------------------------------- | ||
| 196 | + | ||
| 197 | + 'trace' => [ | ||
| 198 | + // 内置Html Console 支持扩展 | ||
| 199 | + 'type' => 'Html', | ||
| 200 | + 'file' => __DIR__ . '/tpl/page_trace.tpl', | ||
| 201 | + ], | ||
| 202 | + | ||
| 203 | + // +---------------------------------------------------------------------- | ||
| 204 | + // | 缓存设置 | ||
| 205 | + // +---------------------------------------------------------------------- | ||
| 206 | + | ||
| 207 | + 'cache' => [ | ||
| 208 | + // 驱动方式 | ||
| 209 | + 'type' => 'File', | ||
| 210 | + // 缓存保存目录 | ||
| 211 | + //'path' => CACHE_PATH, | ||
| 212 | + // 缓存前缀 | ||
| 213 | + 'prefix' => '', | ||
| 214 | + // 缓存有效期 0表示永久缓存 | ||
| 215 | + 'expire' => 0, | ||
| 216 | + ], | ||
| 217 | + | ||
| 218 | + // +---------------------------------------------------------------------- | ||
| 219 | + // | 会话设置 | ||
| 220 | + // +---------------------------------------------------------------------- | ||
| 221 | + | ||
| 222 | + 'session' => [ | ||
| 223 | + 'id' => '', | ||
| 224 | + // SESSION_ID的提交变量,解决flash上传跨域 | ||
| 225 | + 'var_session_id' => '', | ||
| 226 | + // SESSION 前缀 | ||
| 227 | + 'prefix' => 'think', | ||
| 228 | + // 驱动方式 支持redis memcache memcached | ||
| 229 | + 'type' => '', | ||
| 230 | + // 是否自动开启 SESSION | ||
| 231 | + 'auto_start' => true, | ||
| 232 | + 'httponly' => true, | ||
| 233 | + 'secure' => false, | ||
| 234 | + ], | ||
| 235 | + | ||
| 236 | + // +---------------------------------------------------------------------- | ||
| 237 | + // | Cookie设置 | ||
| 238 | + // +---------------------------------------------------------------------- | ||
| 239 | + | ||
| 240 | + 'cookie' => [ | ||
| 241 | + // cookie 名称前缀 | ||
| 242 | + 'prefix' => '', | ||
| 243 | + // cookie 保存时间 | ||
| 244 | + 'expire' => 0, | ||
| 245 | + // cookie 保存路径 | ||
| 246 | + 'path' => '/', | ||
| 247 | + // cookie 有效域名 | ||
| 248 | + 'domain' => '', | ||
| 249 | + // cookie 启用安全传输 | ||
| 250 | + 'secure' => false, | ||
| 251 | + // httponly设置 | ||
| 252 | + 'httponly' => '', | ||
| 253 | + // 是否使用 setcookie | ||
| 254 | + 'setcookie' => true, | ||
| 255 | + ], | ||
| 256 | + | ||
| 257 | + // +---------------------------------------------------------------------- | ||
| 258 | + // | 数据库设置 | ||
| 259 | + // +---------------------------------------------------------------------- | ||
| 260 | + | ||
| 261 | + 'database' => [ | ||
| 262 | + // 数据库类型 | ||
| 263 | + 'type' => 'mysql', | ||
| 264 | + // 数据库连接DSN配置 | ||
| 265 | + 'dsn' => '', | ||
| 266 | + // 服务器地址 | ||
| 267 | + 'hostname' => '127.0.0.1', | ||
| 268 | + // 数据库名 | ||
| 269 | + 'database' => '', | ||
| 270 | + // 数据库用户名 | ||
| 271 | + 'username' => 'root', | ||
| 272 | + // 数据库密码 | ||
| 273 | + 'password' => '', | ||
| 274 | + // 数据库连接端口 | ||
| 275 | + 'hostport' => '', | ||
| 276 | + // 数据库连接参数 | ||
| 277 | + 'params' => [], | ||
| 278 | + // 数据库编码默认采用utf8 | ||
| 279 | + 'charset' => 'utf8', | ||
| 280 | + // 数据库表前缀 | ||
| 281 | + 'prefix' => '', | ||
| 282 | + // 数据库调试模式 | ||
| 283 | + 'debug' => false, | ||
| 284 | + // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) | ||
| 285 | + 'deploy' => 0, | ||
| 286 | + // 数据库读写是否分离 主从式有效 | ||
| 287 | + 'rw_separate' => false, | ||
| 288 | + // 读写分离后 主服务器数量 | ||
| 289 | + 'master_num' => 1, | ||
| 290 | + // 指定从服务器序号 | ||
| 291 | + 'slave_no' => '', | ||
| 292 | + // 是否严格检查字段是否存在 | ||
| 293 | + 'fields_strict' => true, | ||
| 294 | + // 数据集返回类型 | ||
| 295 | + 'resultset_type' => 'array', | ||
| 296 | + // 自动写入时间戳字段 | ||
| 297 | + 'auto_timestamp' => false, | ||
| 298 | + // 时间字段取出后的默认时间格式 | ||
| 299 | + 'datetime_format' => 'Y-m-d H:i:s', | ||
| 300 | + // 是否需要进行SQL性能分析 | ||
| 301 | + 'sql_explain' => false, | ||
| 302 | + // 查询对象 | ||
| 303 | + 'query' => '\\think\\db\\Query', | ||
| 304 | + ], | ||
| 305 | + | ||
| 306 | + //分页配置 | ||
| 307 | + 'paginate' => [ | ||
| 308 | + 'type' => 'bootstrap', | ||
| 309 | + 'var_page' => 'page', | ||
| 310 | + 'list_rows' => 15, | ||
| 311 | + ], | ||
| 312 | + | ||
| 313 | + //控制台配置 | ||
| 314 | + 'console' => [ | ||
| 315 | + 'name' => 'Think Console', | ||
| 316 | + 'version' => '0.1', | ||
| 317 | + 'user' => null, | ||
| 318 | + ], | ||
| 319 | + | ||
| 320 | + // 中间件配置 | ||
| 321 | + 'middleware' => [ | ||
| 322 | + 'default_namespace' => 'app\\http\\middleware\\', | ||
| 323 | + ], | ||
| 324 | +]; |
thinkphp/helper.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// +---------------------------------------------------------------------- | ||
| 3 | +// | ThinkPHP [ WE CAN DO IT JUST THINK ] | ||
| 4 | +// +---------------------------------------------------------------------- | ||
| 5 | +// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved. | ||
| 6 | +// +---------------------------------------------------------------------- | ||
| 7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
| 8 | +// +---------------------------------------------------------------------- | ||
| 9 | +// | Author: liu21st <liu21st@gmail.com> | ||
| 10 | +// +---------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +//------------------------ | ||
| 13 | +// ThinkPHP 助手函数 | ||
| 14 | +//------------------------- | ||
| 15 | + | ||
| 16 | +use think\Container; | ||
| 17 | +use think\Db; | ||
| 18 | +use think\exception\HttpException; | ||
| 19 | +use think\exception\HttpResponseException; | ||
| 20 | +use think\facade\Cache; | ||
| 21 | +use think\facade\Config; | ||
| 22 | +use think\facade\Cookie; | ||
| 23 | +use think\facade\Debug; | ||
| 24 | +use think\facade\Env; | ||
| 25 | +use think\facade\Hook; | ||
| 26 | +use think\facade\Lang; | ||
| 27 | +use think\facade\Log; | ||
| 28 | +use think\facade\Request; | ||
| 29 | +use think\facade\Route; | ||
| 30 | +use think\facade\Session; | ||
| 31 | +use think\facade\Url; | ||
| 32 | +use think\Response; | ||
| 33 | +use think\route\RuleItem; | ||
| 34 | + | ||
| 35 | +if (!function_exists('abort')) { | ||
| 36 | + /** | ||
| 37 | + * 抛出HTTP异常 | ||
| 38 | + * @param integer|Response $code 状态码 或者 Response对象实例 | ||
| 39 | + * @param string $message 错误信息 | ||
| 40 | + * @param array $header 参数 | ||
| 41 | + */ | ||
| 42 | + function abort($code, $message = null, $header = []) | ||
| 43 | + { | ||
| 44 | + if ($code instanceof Response) { | ||
| 45 | + throw new HttpResponseException($code); | ||
| 46 | + } else { | ||
| 47 | + throw new HttpException($code, $message, null, $header); | ||
| 48 | + } | ||
| 49 | + } | ||
| 50 | +} | ||
| 51 | + | ||
| 52 | +if (!function_exists('action')) { | ||
| 53 | + /** | ||
| 54 | + * 调用模块的操作方法 参数格式 [模块/控制器/]操作 | ||
| 55 | + * @param string $url 调用地址 | ||
| 56 | + * @param string|array $vars 调用参数 支持字符串和数组 | ||
| 57 | + * @param string $layer 要调用的控制层名称 | ||
| 58 | + * @param bool $appendSuffix 是否添加类名后缀 | ||
| 59 | + * @return mixed | ||
| 60 | + */ | ||
| 61 | + function action($url, $vars = [], $layer = 'controller', $appendSuffix = false) | ||
| 62 | + { | ||
| 63 | + return app()->action($url, $vars, $layer, $appendSuffix); | ||
| 64 | + } | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +if (!function_exists('app')) { | ||
| 68 | + /** | ||
| 69 | + * 快速获取容器中的实例 支持依赖注入 | ||
| 70 | + * @param string $name 类名或标识 默认获取当前应用实例 | ||
| 71 | + * @param array $args 参数 | ||
| 72 | + * @param bool $newInstance 是否每次创建新的实例 | ||
| 73 | + * @return mixed|\think\App | ||
| 74 | + */ | ||
| 75 | + function app($name = 'think\App', $args = [], $newInstance = false) | ||
| 76 | + { | ||
| 77 | + return Container::get($name, $args, $newInstance); | ||
| 78 | + } | ||
| 79 | +} | ||
| 80 | + | ||
| 81 | +if (!function_exists('behavior')) { | ||
| 82 | + /** | ||
| 83 | + * 执行某个行为(run方法) 支持依赖注入 | ||
| 84 | + * @param mixed $behavior 行为类名或者别名 | ||
| 85 | + * @param mixed $args 参数 | ||
| 86 | + * @return mixed | ||
| 87 | + */ | ||
| 88 | + function behavior($behavior, $args = null) | ||
| 89 | + { | ||
| 90 | + return Hook::exec($behavior, $args); | ||
| 91 | + } | ||
| 92 | +} | ||
| 93 | + | ||
| 94 | +if (!function_exists('bind')) { | ||
| 95 | + /** | ||
| 96 | + * 绑定一个类到容器 | ||
| 97 | + * @access public | ||
| 98 | + * @param string $abstract 类标识、接口 | ||
| 99 | + * @param mixed $concrete 要绑定的类、闭包或者实例 | ||
| 100 | + * @return Container | ||
| 101 | + */ | ||
| 102 | + function bind($abstract, $concrete = null) | ||
| 103 | + { | ||
| 104 | + return Container::getInstance()->bindTo($abstract, $concrete); | ||
| 105 | + } | ||
| 106 | +} | ||
| 107 | + | ||
| 108 | +if (!function_exists('cache')) { | ||
| 109 | + /** | ||
| 110 | + * 缓存管理 | ||
| 111 | + * @param mixed $name 缓存名称,如果为数组表示进行缓存设置 | ||
| 112 | + * @param mixed $value 缓存值 | ||
| 113 | + * @param mixed $options 缓存参数 | ||
| 114 | + * @param string $tag 缓存标签 | ||
| 115 | + * @return mixed | ||
| 116 | + */ | ||
| 117 | + function cache($name, $value = '', $options = null, $tag = null) | ||
| 118 | + { | ||
| 119 | + if (is_array($options)) { | ||
| 120 | + // 缓存操作的同时初始化 | ||
| 121 | + Cache::connect($options); | ||
| 122 | + } elseif (is_array($name)) { | ||
| 123 | + // 缓存初始化 | ||
| 124 | + return Cache::connect($name); | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + if ('' === $value) { | ||
| 128 | + // 获取缓存 | ||
| 129 | + return 0 === strpos($name, '?') ? Cache::has(substr($name, 1)) : Cache::get($name); | ||
| 130 | + } elseif (is_null($value)) { | ||
| 131 | + // 删除缓存 | ||
| 132 | + return Cache::rm($name); | ||
| 133 | + } else { | ||
| 134 | + // 缓存数据 | ||
| 135 | + if (is_array($options)) { | ||
| 136 | + $expire = isset($options['expire']) ? $options['expire'] : null; //修复查询缓存无法设置过期时间 | ||
| 137 | + } else { | ||
| 138 | + $expire = is_numeric($options) ? $options : null; //默认快捷缓存设置过期时间 | ||
| 139 | + } | ||
| 140 | + | ||
| 141 | + if (is_null($tag)) { | ||
| 142 | + return Cache::set($name, $value, $expire); | ||
| 143 | + } else { | ||
| 144 | + return Cache::tag($tag)->set($name, $value, $expire); | ||
| 145 | + } | ||
| 146 | + } | ||
| 147 | + } | ||
| 148 | +} | ||
| 149 | + | ||
| 150 | +if (!function_exists('call')) { | ||
| 151 | + /** | ||
| 152 | + * 调用反射执行callable 支持依赖注入 | ||
| 153 | + * @param mixed $callable 支持闭包等callable写法 | ||
| 154 | + * @param array $args 参数 | ||
| 155 | + * @return mixed | ||
| 156 | + */ | ||
| 157 | + function call($callable, $args = []) | ||
| 158 | + { | ||
| 159 | + return Container::getInstance()->invoke($callable, $args); | ||
| 160 | + } | ||
| 161 | +} | ||
| 162 | + | ||
| 163 | +if (!function_exists('class_basename')) { | ||
| 164 | + /** | ||
| 165 | + * 获取类名(不包含命名空间) | ||
| 166 | + * | ||
| 167 | + * @param string|object $class | ||
| 168 | + * @return string | ||
| 169 | + */ | ||
| 170 | + function class_basename($class) | ||
| 171 | + { | ||
| 172 | + $class = is_object($class) ? get_class($class) : $class; | ||
| 173 | + return basename(str_replace('\\', '/', $class)); | ||
| 174 | + } | ||
| 175 | +} | ||
| 176 | + | ||
| 177 | +if (!function_exists('class_uses_recursive')) { | ||
| 178 | + /** | ||
| 179 | + *获取一个类里所有用到的trait,包括父类的 | ||
| 180 | + * | ||
| 181 | + * @param $class | ||
| 182 | + * @return array | ||
| 183 | + */ | ||
| 184 | + function class_uses_recursive($class) | ||
| 185 | + { | ||
| 186 | + if (is_object($class)) { | ||
| 187 | + $class = get_class($class); | ||
| 188 | + } | ||
| 189 | + | ||
| 190 | + $results = []; | ||
| 191 | + $classes = array_merge([$class => $class], class_parents($class)); | ||
| 192 | + foreach ($classes as $class) { | ||
| 193 | + $results += trait_uses_recursive($class); | ||
| 194 | + } | ||
| 195 | + | ||
| 196 | + return array_unique($results); | ||
| 197 | + } | ||
| 198 | +} | ||
| 199 | + | ||
| 200 | +if (!function_exists('config')) { | ||
| 201 | + /** | ||
| 202 | + * 获取和设置配置参数 | ||
| 203 | + * @param string|array $name 参数名 | ||
| 204 | + * @param mixed $value 参数值 | ||
| 205 | + * @return mixed | ||
| 206 | + */ | ||
| 207 | + function config($name = '', $value = null) | ||
| 208 | + { | ||
| 209 | + if (is_null($value) && is_string($name)) { | ||
| 210 | + if ('.' == substr($name, -1)) { | ||
| 211 | + return Config::pull(substr($name, 0, -1)); | ||
| 212 | + } | ||
| 213 | + | ||
| 214 | + return 0 === strpos($name, '?') ? Config::has(substr($name, 1)) : Config::get($name); | ||
| 215 | + } else { | ||
| 216 | + return Config::set($name, $value); | ||
| 217 | + } | ||
| 218 | + } | ||
| 219 | +} | ||
| 220 | + | ||
| 221 | +if (!function_exists('container')) { | ||
| 222 | + /** | ||
| 223 | + * 获取容器对象实例 | ||
| 224 | + * @return Container | ||
| 225 | + */ | ||
| 226 | + function container() | ||
| 227 | + { | ||
| 228 | + return Container::getInstance(); | ||
| 229 | + } | ||
| 230 | +} | ||
| 231 | + | ||
| 232 | +if (!function_exists('controller')) { | ||
| 233 | + /** | ||
| 234 | + * 实例化控制器 格式:[模块/]控制器 | ||
| 235 | + * @param string $name 资源地址 | ||
| 236 | + * @param string $layer 控制层名称 | ||
| 237 | + * @param bool $appendSuffix 是否添加类名后缀 | ||
| 238 | + * @return \think\Controller | ||
| 239 | + */ | ||
| 240 | + function controller($name, $layer = 'controller', $appendSuffix = false) | ||
| 241 | + { | ||
| 242 | + return app()->controller($name, $layer, $appendSuffix); | ||
| 243 | + } | ||
| 244 | +} | ||
| 245 | + | ||
| 246 | +if (!function_exists('cookie')) { | ||
| 247 | + /** | ||
| 248 | + * Cookie管理 | ||
| 249 | + * @param string|array $name cookie名称,如果为数组表示进行cookie设置 | ||
| 250 | + * @param mixed $value cookie值 | ||
| 251 | + * @param mixed $option 参数 | ||
| 252 | + * @return mixed | ||
| 253 | + */ | ||
| 254 | + function cookie($name, $value = '', $option = null) | ||
| 255 | + { | ||
| 256 | + if (is_array($name)) { | ||
| 257 | + // 初始化 | ||
| 258 | + Cookie::init($name); | ||
| 259 | + } elseif (is_null($name)) { | ||
| 260 | + // 清除 | ||
| 261 | + Cookie::clear($value); | ||
| 262 | + } elseif ('' === $value) { | ||
| 263 | + // 获取 | ||
| 264 | + return 0 === strpos($name, '?') ? Cookie::has(substr($name, 1), $option) : Cookie::get($name); | ||
| 265 | + } elseif (is_null($value)) { | ||
| 266 | + // 删除 | ||
| 267 | + return Cookie::delete($name); | ||
| 268 | + } else { | ||
| 269 | + // 设置 | ||
| 270 | + return Cookie::set($name, $value, $option); | ||
| 271 | + } | ||
| 272 | + } | ||
| 273 | +} | ||
| 274 | + | ||
| 275 | +if (!function_exists('db')) { | ||
| 276 | + /** | ||
| 277 | + * 实例化数据库类 | ||
| 278 | + * @param string $name 操作的数据表名称(不含前缀) | ||
| 279 | + * @param array|string $config 数据库配置参数 | ||
| 280 | + * @param bool $force 是否强制重新连接 | ||
| 281 | + * @return \think\db\Query | ||
| 282 | + */ | ||
| 283 | + function db($name = '', $config = [], $force = true) | ||
| 284 | + { | ||
| 285 | + return Db::connect($config, $force)->name($name); | ||
| 286 | + } | ||
| 287 | +} | ||
| 288 | + | ||
| 289 | +if (!function_exists('debug')) { | ||
| 290 | + /** | ||
| 291 | + * 记录时间(微秒)和内存使用情况 | ||
| 292 | + * @param string $start 开始标签 | ||
| 293 | + * @param string $end 结束标签 | ||
| 294 | + * @param integer|string $dec 小数位 如果是m 表示统计内存占用 | ||
| 295 | + * @return mixed | ||
| 296 | + */ | ||
| 297 | + function debug($start, $end = '', $dec = 6) | ||
| 298 | + { | ||
| 299 | + if ('' == $end) { | ||
| 300 | + Debug::remark($start); | ||
| 301 | + } else { | ||
| 302 | + return 'm' == $dec ? Debug::getRangeMem($start, $end) : Debug::getRangeTime($start, $end, $dec); | ||
| 303 | + } | ||
| 304 | + } | ||
| 305 | +} | ||
| 306 | + | ||
| 307 | +if (!function_exists('download')) { | ||
| 308 | + /** | ||
| 309 | + * 获取\think\response\Download对象实例 | ||
| 310 | + * @param string $filename 要下载的文件 | ||
| 311 | + * @param string $name 显示文件名 | ||
| 312 | + * @param bool $content 是否为内容 | ||
| 313 | + * @param integer $expire 有效期(秒) | ||
| 314 | + * @return \think\response\Download | ||
| 315 | + */ | ||
| 316 | + function download($filename, $name = '', $content = false, $expire = 180) | ||
| 317 | + { | ||
| 318 | + return Response::create($filename, 'download')->name($name)->isContent($content)->expire($expire); | ||
| 319 | + } | ||
| 320 | +} | ||
| 321 | + | ||
| 322 | +if (!function_exists('dump')) { | ||
| 323 | + /** | ||
| 324 | + * 浏览器友好的变量输出 | ||
| 325 | + * @param mixed $var 变量 | ||
| 326 | + * @param boolean $echo 是否输出 默认为true 如果为false 则返回输出字符串 | ||
| 327 | + * @param string $label 标签 默认为空 | ||
| 328 | + * @return void|string | ||
| 329 | + */ | ||
| 330 | + function dump($var, $echo = true, $label = null) | ||
| 331 | + { | ||
| 332 | + return Debug::dump($var, $echo, $label); | ||
| 333 | + } | ||
| 334 | +} | ||
| 335 | + | ||
| 336 | +if (!function_exists('env')) { | ||
| 337 | + /** | ||
| 338 | + * 获取环境变量值 | ||
| 339 | + * @access public | ||
| 340 | + * @param string $name 环境变量名(支持二级 .号分割) | ||
| 341 | + * @param string $default 默认值 | ||
| 342 | + * @return mixed | ||
| 343 | + */ | ||
| 344 | + function env($name = null, $default = null) | ||
| 345 | + { | ||
| 346 | + return Env::get($name, $default); | ||
| 347 | + } | ||
| 348 | +} | ||
| 349 | + | ||
| 350 | +if (!function_exists('exception')) { | ||
| 351 | + /** | ||
| 352 | + * 抛出异常处理 | ||
| 353 | + * | ||
| 354 | + * @param string $msg 异常消息 | ||
| 355 | + * @param integer $code 异常代码 默认为0 | ||
| 356 | + * @param string $exception 异常类 | ||
| 357 | + * | ||
| 358 | + * @throws Exception | ||
| 359 | + */ | ||
| 360 | + function exception($msg, $code = 0, $exception = '') | ||
| 361 | + { | ||
| 362 | + $e = $exception ?: '\think\Exception'; | ||
| 363 | + throw new $e($msg, $code); | ||
| 364 | + } | ||
| 365 | +} | ||
| 366 | + | ||
| 367 | +if (!function_exists('halt')) { | ||
| 368 | + /** | ||
| 369 | + * 调试变量并且中断输出 | ||
| 370 | + * @param mixed $var 调试变量或者信息 | ||
| 371 | + */ | ||
| 372 | + function halt($var) | ||
| 373 | + { | ||
| 374 | + dump($var); | ||
| 375 | + | ||
| 376 | + throw new HttpResponseException(new Response); | ||
| 377 | + } | ||
| 378 | +} | ||
| 379 | + | ||
| 380 | +if (!function_exists('input')) { | ||
| 381 | + /** | ||
| 382 | + * 获取输入数据 支持默认值和过滤 | ||
| 383 | + * @param string $key 获取的变量名 | ||
| 384 | + * @param mixed $default 默认值 | ||
| 385 | + * @param string $filter 过滤方法 | ||
| 386 | + * @return mixed | ||
| 387 | + */ | ||
| 388 | + function input($key = '', $default = null, $filter = '') | ||
| 389 | + { | ||
| 390 | + if (0 === strpos($key, '?')) { | ||
| 391 | + $key = substr($key, 1); | ||
| 392 | + $has = true; | ||
| 393 | + } | ||
| 394 | + | ||
| 395 | + if ($pos = strpos($key, '.')) { | ||
| 396 | + // 指定参数来源 | ||
| 397 | + $method = substr($key, 0, $pos); | ||
| 398 | + if (in_array($method, ['get', 'post', 'put', 'patch', 'delete', 'route', 'param', 'request', 'session', 'cookie', 'server', 'env', 'path', 'file'])) { | ||
| 399 | + $key = substr($key, $pos + 1); | ||
| 400 | + } else { | ||
| 401 | + $method = 'param'; | ||
| 402 | + } | ||
| 403 | + } else { | ||
| 404 | + // 默认为自动判断 | ||
| 405 | + $method = 'param'; | ||
| 406 | + } | ||
| 407 | + | ||
| 408 | + if (isset($has)) { | ||
| 409 | + return request()->has($key, $method, $default); | ||
| 410 | + } else { | ||
| 411 | + return request()->$method($key, $default, $filter); | ||
| 412 | + } | ||
| 413 | + } | ||
| 414 | +} | ||
| 415 | + | ||
| 416 | +if (!function_exists('json')) { | ||
| 417 | + /** | ||
| 418 | + * 获取\think\response\Json对象实例 | ||
| 419 | + * @param mixed $data 返回的数据 | ||
| 420 | + * @param integer $code 状态码 | ||
| 421 | + * @param array $header 头部 | ||
| 422 | + * @param array $options 参数 | ||
| 423 | + * @return \think\response\Json | ||
| 424 | + */ | ||
| 425 | + function json($data = [], $code = 200, $header = [], $options = []) | ||
| 426 | + { | ||
| 427 | + return Response::create($data, 'json', $code, $header, $options); | ||
| 428 | + } | ||
| 429 | +} | ||
| 430 | + | ||
| 431 | +if (!function_exists('jsonp')) { | ||
| 432 | + /** | ||
| 433 | + * 获取\think\response\Jsonp对象实例 | ||
| 434 | + * @param mixed $data 返回的数据 | ||
| 435 | + * @param integer $code 状态码 | ||
| 436 | + * @param array $header 头部 | ||
| 437 | + * @param array $options 参数 | ||
| 438 | + * @return \think\response\Jsonp | ||
| 439 | + */ | ||
| 440 | + function jsonp($data = [], $code = 200, $header = [], $options = []) | ||
| 441 | + { | ||
| 442 | + return Response::create($data, 'jsonp', $code, $header, $options); | ||
| 443 | + } | ||
| 444 | +} | ||
| 445 | + | ||
| 446 | +if (!function_exists('lang')) { | ||
| 447 | + /** | ||
| 448 | + * 获取语言变量值 | ||
| 449 | + * @param string $name 语言变量名 | ||
| 450 | + * @param array $vars 动态变量值 | ||
| 451 | + * @param string $lang 语言 | ||
| 452 | + * @return mixed | ||
| 453 | + */ | ||
| 454 | + function lang($name, $vars = [], $lang = '') | ||
| 455 | + { | ||
| 456 | + return Lang::get($name, $vars, $lang); | ||
| 457 | + } | ||
| 458 | +} | ||
| 459 | + | ||
| 460 | +if (!function_exists('model')) { | ||
| 461 | + /** | ||
| 462 | + * 实例化Model | ||
| 463 | + * @param string $name Model名称 | ||
| 464 | + * @param string $layer 业务层名称 | ||
| 465 | + * @param bool $appendSuffix 是否添加类名后缀 | ||
| 466 | + * @return \think\Model | ||
| 467 | + */ | ||
| 468 | + function model($name = '', $layer = 'model', $appendSuffix = false) | ||
| 469 | + { | ||
| 470 | + return app()->model($name, $layer, $appendSuffix); | ||
| 471 | + } | ||
| 472 | +} | ||
| 473 | + | ||
| 474 | +if (!function_exists('parse_name')) { | ||
| 475 | + /** | ||
| 476 | + * 字符串命名风格转换 | ||
| 477 | + * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格 | ||
| 478 | + * @param string $name 字符串 | ||
| 479 | + * @param integer $type 转换类型 | ||
| 480 | + * @param bool $ucfirst 首字母是否大写(驼峰规则) | ||
| 481 | + * @return string | ||
| 482 | + */ | ||
| 483 | + function parse_name($name, $type = 0, $ucfirst = true) | ||
| 484 | + { | ||
| 485 | + if ($type) { | ||
| 486 | + $name = preg_replace_callback('/_([a-zA-Z])/', function ($match) { | ||
| 487 | + return strtoupper($match[1]); | ||
| 488 | + }, $name); | ||
| 489 | + | ||
| 490 | + return $ucfirst ? ucfirst($name) : lcfirst($name); | ||
| 491 | + } else { | ||
| 492 | + return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_")); | ||
| 493 | + } | ||
| 494 | + } | ||
| 495 | +} | ||
| 496 | + | ||
| 497 | +if (!function_exists('redirect')) { | ||
| 498 | + /** | ||
| 499 | + * 获取\think\response\Redirect对象实例 | ||
| 500 | + * @param mixed $url 重定向地址 支持Url::build方法的地址 | ||
| 501 | + * @param array|integer $params 额外参数 | ||
| 502 | + * @param integer $code 状态码 | ||
| 503 | + * @return \think\response\Redirect | ||
| 504 | + */ | ||
| 505 | + function redirect($url = [], $params = [], $code = 302) | ||
| 506 | + { | ||
| 507 | + if (is_integer($params)) { | ||
| 508 | + $code = $params; | ||
| 509 | + $params = []; | ||
| 510 | + } | ||
| 511 | + | ||
| 512 | + return Response::create($url, 'redirect', $code)->params($params); | ||
| 513 | + } | ||
| 514 | +} | ||
| 515 | + | ||
| 516 | +if (!function_exists('request')) { | ||
| 517 | + /** | ||
| 518 | + * 获取当前Request对象实例 | ||
| 519 | + * @return Request | ||
| 520 | + */ | ||
| 521 | + function request() | ||
| 522 | + { | ||
| 523 | + return app('request'); | ||
| 524 | + } | ||
| 525 | +} | ||
| 526 | + | ||
| 527 | +if (!function_exists('response')) { | ||
| 528 | + /** | ||
| 529 | + * 创建普通 Response 对象实例 | ||
| 530 | + * @param mixed $data 输出数据 | ||
| 531 | + * @param int|string $code 状态码 | ||
| 532 | + * @param array $header 头信息 | ||
| 533 | + * @param string $type | ||
| 534 | + * @return Response | ||
| 535 | + */ | ||
| 536 | + function response($data = [], $code = 200, $header = [], $type = 'html') | ||
| 537 | + { | ||
| 538 | + return Response::create($data, $type, $code, $header); | ||
| 539 | + } | ||
| 540 | +} | ||
| 541 | + | ||
| 542 | +if (!function_exists('route')) { | ||
| 543 | + /** | ||
| 544 | + * 路由注册 | ||
| 545 | + * @param string $rule 路由规则 | ||
| 546 | + * @param mixed $route 路由地址 | ||
| 547 | + * @param array $option 路由参数 | ||
| 548 | + * @param array $pattern 变量规则 | ||
| 549 | + * @return RuleItem | ||
| 550 | + */ | ||
| 551 | + function route($rule, $route, $option = [], $pattern = []) | ||
| 552 | + { | ||
| 553 | + return Route::rule($rule, $route, '*', $option, $pattern); | ||
| 554 | + } | ||
| 555 | +} | ||
| 556 | + | ||
| 557 | +if (!function_exists('session')) { | ||
| 558 | + /** | ||
| 559 | + * Session管理 | ||
| 560 | + * @param string|array $name session名称,如果为数组表示进行session设置 | ||
| 561 | + * @param mixed $value session值 | ||
| 562 | + * @param string $prefix 前缀 | ||
| 563 | + * @return mixed | ||
| 564 | + */ | ||
| 565 | + function session($name, $value = '', $prefix = null) | ||
| 566 | + { | ||
| 567 | + if (is_array($name)) { | ||
| 568 | + // 初始化 | ||
| 569 | + Session::init($name); | ||
| 570 | + } elseif (is_null($name)) { | ||
| 571 | + // 清除 | ||
| 572 | + Session::clear($value); | ||
| 573 | + } elseif ('' === $value) { | ||
| 574 | + // 判断或获取 | ||
| 575 | + return 0 === strpos($name, '?') ? Session::has(substr($name, 1), $prefix) : Session::get($name, $prefix); | ||
| 576 | + } elseif (is_null($value)) { | ||
| 577 | + // 删除 | ||
| 578 | + return Session::delete($name, $prefix); | ||
| 579 | + } else { | ||
| 580 | + // 设置 | ||
| 581 | + return Session::set($name, $value, $prefix); | ||
| 582 | + } | ||
| 583 | + } | ||
| 584 | +} | ||
| 585 | + | ||
| 586 | +if (!function_exists('token')) { | ||
| 587 | + /** | ||
| 588 | + * 生成表单令牌 | ||
| 589 | + * @param string $name 令牌名称 | ||
| 590 | + * @param mixed $type 令牌生成方法 | ||
| 591 | + * @return string | ||
| 592 | + */ | ||
| 593 | + function token($name = '__token__', $type = 'md5') | ||
| 594 | + { | ||
| 595 | + $token = Request::token($name, $type); | ||
| 596 | + | ||
| 597 | + return '<input type="hidden" name="' . $name . '" value="' . $token . '" />'; | ||
| 598 | + } | ||
| 599 | +} | ||
| 600 | + | ||
| 601 | +if (!function_exists('trace')) { | ||
| 602 | + /** | ||
| 603 | + * 记录日志信息 | ||
| 604 | + * @param mixed $log log信息 支持字符串和数组 | ||
| 605 | + * @param string $level 日志级别 | ||
| 606 | + * @return array|void | ||
| 607 | + */ | ||
| 608 | + function trace($log = '[think]', $level = 'log') | ||
| 609 | + { | ||
| 610 | + if ('[think]' === $log) { | ||
| 611 | + return Log::getLog(); | ||
| 612 | + } else { | ||
| 613 | + Log::record($log, $level); | ||
| 614 | + } | ||
| 615 | + } | ||
| 616 | +} | ||
| 617 | + | ||
| 618 | +if (!function_exists('trait_uses_recursive')) { | ||
| 619 | + /** | ||
| 620 | + * 获取一个trait里所有引用到的trait | ||
| 621 | + * | ||
| 622 | + * @param string $trait | ||
| 623 | + * @return array | ||
| 624 | + */ | ||
| 625 | + function trait_uses_recursive($trait) | ||
| 626 | + { | ||
| 627 | + $traits = class_uses($trait); | ||
| 628 | + foreach ($traits as $trait) { | ||
| 629 | + $traits += trait_uses_recursive($trait); | ||
| 630 | + } | ||
| 631 | + | ||
| 632 | + return $traits; | ||
| 633 | + } | ||
| 634 | +} | ||
| 635 | + | ||
| 636 | +if (!function_exists('url')) { | ||
| 637 | + /** | ||
| 638 | + * Url生成 | ||
| 639 | + * @param string $url 路由地址 | ||
| 640 | + * @param string|array $vars 变量 | ||
| 641 | + * @param bool|string $suffix 生成的URL后缀 | ||
| 642 | + * @param bool|string $domain 域名 | ||
| 643 | + * @return string | ||
| 644 | + */ | ||
| 645 | + function url($url = '', $vars = '', $suffix = true, $domain = false) | ||
| 646 | + { | ||
| 647 | + return Url::build($url, $vars, $suffix, $domain); | ||
| 648 | + } | ||
| 649 | +} | ||
| 650 | + | ||
| 651 | +if (!function_exists('validate')) { | ||
| 652 | + /** | ||
| 653 | + * 实例化验证器 | ||
| 654 | + * @param string $name 验证器名称 | ||
| 655 | + * @param string $layer 业务层名称 | ||
| 656 | + * @param bool $appendSuffix 是否添加类名后缀 | ||
| 657 | + * @return \think\Validate | ||
| 658 | + */ | ||
| 659 | + function validate($name = '', $layer = 'validate', $appendSuffix = false) | ||
| 660 | + { | ||
| 661 | + return app()->validate($name, $layer, $appendSuffix); | ||
| 662 | + } | ||
| 663 | +} | ||
| 664 | + | ||
| 665 | +if (!function_exists('view')) { | ||
| 666 | + /** | ||
| 667 | + * 渲染模板输出 | ||
| 668 | + * @param string $template 模板文件 | ||
| 669 | + * @param array $vars 模板变量 | ||
| 670 | + * @param integer $code 状态码 | ||
| 671 | + * @param callable $filter 内容过滤 | ||
| 672 | + * @return \think\response\View | ||
| 673 | + */ | ||
| 674 | + function view($template = '', $vars = [], $code = 200, $filter = null) | ||
| 675 | + { | ||
| 676 | + return Response::create($template, 'view', $code)->assign($vars)->filter($filter); | ||
| 677 | + } | ||
| 678 | +} | ||
| 679 | + | ||
| 680 | +if (!function_exists('widget')) { | ||
| 681 | + /** | ||
| 682 | + * 渲染输出Widget | ||
| 683 | + * @param string $name Widget名称 | ||
| 684 | + * @param array $data 传入的参数 | ||
| 685 | + * @return mixed | ||
| 686 | + */ | ||
| 687 | + function widget($name, $data = []) | ||
| 688 | + { | ||
| 689 | + return app()->action($name, $data, 'widget'); | ||
| 690 | + } | ||
| 691 | +} | ||
| 692 | + | ||
| 693 | +if (!function_exists('xml')) { | ||
| 694 | + /** | ||
| 695 | + * 获取\think\response\Xml对象实例 | ||
| 696 | + * @param mixed $data 返回的数据 | ||
| 697 | + * @param integer $code 状态码 | ||
| 698 | + * @param array $header 头部 | ||
| 699 | + * @param array $options 参数 | ||
| 700 | + * @return \think\response\Xml | ||
| 701 | + */ | ||
| 702 | + function xml($data = [], $code = 200, $header = [], $options = []) | ||
| 703 | + { | ||
| 704 | + return Response::create($data, 'xml', $code, $header, $options); | ||
| 705 | + } | ||
| 706 | +} |
thinkphp/lang/zh-cn.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// +---------------------------------------------------------------------- | ||
| 3 | +// | ThinkPHP [ WE CAN DO IT JUST THINK ] | ||
| 4 | +// +---------------------------------------------------------------------- | ||
| 5 | +// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved. | ||
| 6 | +// +---------------------------------------------------------------------- | ||
| 7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
| 8 | +// +---------------------------------------------------------------------- | ||
| 9 | +// | Author: liu21st <liu21st@gmail.com> | ||
| 10 | +// +---------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +// 核心中文语言包 | ||
| 13 | +return [ | ||
| 14 | + // 系统错误提示 | ||
| 15 | + 'Undefined variable' => '未定义变量', | ||
| 16 | + 'Undefined index' => '未定义数组索引', | ||
| 17 | + 'Undefined offset' => '未定义数组下标', | ||
| 18 | + 'Parse error' => '语法解析错误', | ||
| 19 | + 'Type error' => '类型错误', | ||
| 20 | + 'Fatal error' => '致命错误', | ||
| 21 | + 'syntax error' => '语法错误', | ||
| 22 | + | ||
| 23 | + // 框架核心错误提示 | ||
| 24 | + 'dispatch type not support' => '不支持的调度类型', | ||
| 25 | + 'method param miss' => '方法参数错误', | ||
| 26 | + 'method not exists' => '方法不存在', | ||
| 27 | + 'function not exists' => '函数不存在', | ||
| 28 | + 'file not exists' => '文件不存在', | ||
| 29 | + 'module not exists' => '模块不存在', | ||
| 30 | + 'controller not exists' => '控制器不存在', | ||
| 31 | + 'class not exists' => '类不存在', | ||
| 32 | + 'property not exists' => '类的属性不存在', | ||
| 33 | + 'template not exists' => '模板文件不存在', | ||
| 34 | + 'illegal controller name' => '非法的控制器名称', | ||
| 35 | + 'illegal action name' => '非法的操作名称', | ||
| 36 | + 'url suffix deny' => '禁止的URL后缀访问', | ||
| 37 | + 'Route Not Found' => '当前访问路由未定义或不匹配', | ||
| 38 | + 'Undefined db type' => '未定义数据库类型', | ||
| 39 | + 'variable type error' => '变量类型错误', | ||
| 40 | + 'PSR-4 error' => 'PSR-4 规范错误', | ||
| 41 | + 'not support total' => '简洁模式下不能获取数据总数', | ||
| 42 | + 'not support last' => '简洁模式下不能获取最后一页', | ||
| 43 | + 'error session handler' => '错误的SESSION处理器类', | ||
| 44 | + 'not allow php tag' => '模板不允许使用PHP语法', | ||
| 45 | + 'not support' => '不支持', | ||
| 46 | + 'redisd master' => 'Redisd 主服务器错误', | ||
| 47 | + 'redisd slave' => 'Redisd 从服务器错误', | ||
| 48 | + 'must run at sae' => '必须在SAE运行', | ||
| 49 | + 'memcache init error' => '未开通Memcache服务,请在SAE管理平台初始化Memcache服务', | ||
| 50 | + 'KVDB init error' => '没有初始化KVDB,请在SAE管理平台初始化KVDB服务', | ||
| 51 | + 'fields not exists' => '数据表字段不存在', | ||
| 52 | + 'where express error' => '查询表达式错误', | ||
| 53 | + 'no data to update' => '没有任何数据需要更新', | ||
| 54 | + 'miss data to insert' => '缺少需要写入的数据', | ||
| 55 | + 'not support data' => '不支持的数据表达式', | ||
| 56 | + 'miss complex primary data' => '缺少复合主键数据', | ||
| 57 | + 'miss update condition' => '缺少更新条件', | ||
| 58 | + 'model data Not Found' => '模型数据不存在', | ||
| 59 | + 'table data not Found' => '表数据不存在', | ||
| 60 | + 'delete without condition' => '没有条件不会执行删除操作', | ||
| 61 | + 'miss relation data' => '缺少关联表数据', | ||
| 62 | + 'tag attr must' => '模板标签属性必须', | ||
| 63 | + 'tag error' => '模板标签错误', | ||
| 64 | + 'cache write error' => '缓存写入失败', | ||
| 65 | + 'sae mc write error' => 'SAE mc 写入错误', | ||
| 66 | + 'route name not exists' => '路由标识不存在(或参数不够)', | ||
| 67 | + 'invalid request' => '非法请求', | ||
| 68 | + 'bind attr has exists' => '模型的属性已经存在', | ||
| 69 | + 'relation data not exists' => '关联数据不存在', | ||
| 70 | + 'relation not support' => '关联不支持', | ||
| 71 | + 'chunk not support order' => 'Chunk不支持调用order方法', | ||
| 72 | + 'route pattern error' => '路由变量规则定义错误', | ||
| 73 | + 'route behavior will not support' => '路由行为废弃(使用中间件替代)', | ||
| 74 | + 'closure not support cache(true)' => '使用闭包查询不支持cache(true),请指定缓存Key', | ||
| 75 | + | ||
| 76 | + // 上传错误信息 | ||
| 77 | + 'unknown upload error' => '未知上传错误!', | ||
| 78 | + 'file write error' => '文件写入失败!', | ||
| 79 | + 'upload temp dir not found' => '找不到临时文件夹!', | ||
| 80 | + 'no file to uploaded' => '没有文件被上传!', | ||
| 81 | + 'only the portion of file is uploaded' => '文件只有部分被上传!', | ||
| 82 | + 'upload File size exceeds the maximum value' => '上传文件大小超过了最大值!', | ||
| 83 | + 'upload write error' => '文件上传保存错误!', | ||
| 84 | + 'has the same filename: {:filename}' => '存在同名文件:{:filename}', | ||
| 85 | + 'upload illegal files' => '非法上传文件', | ||
| 86 | + 'illegal image files' => '非法图片文件', | ||
| 87 | + 'extensions to upload is not allowed' => '上传文件后缀不允许', | ||
| 88 | + 'mimetype to upload is not allowed' => '上传文件MIME类型不允许!', | ||
| 89 | + 'filesize not match' => '上传文件大小不符!', | ||
| 90 | + 'directory {:path} creation failed' => '目录 {:path} 创建失败!', | ||
| 91 | + | ||
| 92 | + 'The middleware must return Response instance' => '中间件方法必须返回Response对象实例', | ||
| 93 | + 'The queue was exhausted, with no response returned' => '中间件队列为空', | ||
| 94 | + // Validate Error Message | ||
| 95 | + ':attribute require' => ':attribute不能为空', | ||
| 96 | + ':attribute must' => ':attribute必须', | ||
| 97 | + ':attribute must be numeric' => ':attribute必须是数字', | ||
| 98 | + ':attribute must be integer' => ':attribute必须是整数', | ||
| 99 | + ':attribute must be float' => ':attribute必须是浮点数', | ||
| 100 | + ':attribute must be bool' => ':attribute必须是布尔值', | ||
| 101 | + ':attribute not a valid email address' => ':attribute格式不符', | ||
| 102 | + ':attribute not a valid mobile' => ':attribute格式不符', | ||
| 103 | + ':attribute must be a array' => ':attribute必须是数组', | ||
| 104 | + ':attribute must be yes,on or 1' => ':attribute必须是yes、on或者1', | ||
| 105 | + ':attribute not a valid datetime' => ':attribute不是一个有效的日期或时间格式', | ||
| 106 | + ':attribute not a valid file' => ':attribute不是有效的上传文件', | ||
| 107 | + ':attribute not a valid image' => ':attribute不是有效的图像文件', | ||
| 108 | + ':attribute must be alpha' => ':attribute只能是字母', | ||
| 109 | + ':attribute must be alpha-numeric' => ':attribute只能是字母和数字', | ||
| 110 | + ':attribute must be alpha-numeric, dash, underscore' => ':attribute只能是字母、数字和下划线_及破折号-', | ||
| 111 | + ':attribute not a valid domain or ip' => ':attribute不是有效的域名或者IP', | ||
| 112 | + ':attribute must be chinese' => ':attribute只能是汉字', | ||
| 113 | + ':attribute must be chinese or alpha' => ':attribute只能是汉字、字母', | ||
| 114 | + ':attribute must be chinese,alpha-numeric' => ':attribute只能是汉字、字母和数字', | ||
| 115 | + ':attribute must be chinese,alpha-numeric,underscore, dash' => ':attribute只能是汉字、字母、数字和下划线_及破折号-', | ||
| 116 | + ':attribute not a valid url' => ':attribute不是有效的URL地址', | ||
| 117 | + ':attribute not a valid ip' => ':attribute不是有效的IP地址', | ||
| 118 | + ':attribute must be dateFormat of :rule' => ':attribute必须使用日期格式 :rule', | ||
| 119 | + ':attribute must be in :rule' => ':attribute必须在 :rule 范围内', | ||
| 120 | + ':attribute be notin :rule' => ':attribute不能在 :rule 范围内', | ||
| 121 | + ':attribute must between :1 - :2' => ':attribute只能在 :1 - :2 之间', | ||
| 122 | + ':attribute not between :1 - :2' => ':attribute不能在 :1 - :2 之间', | ||
| 123 | + 'size of :attribute must be :rule' => ':attribute长度不符合要求 :rule', | ||
| 124 | + 'max size of :attribute must be :rule' => ':attribute长度不能超过 :rule', | ||
| 125 | + 'min size of :attribute must be :rule' => ':attribute长度不能小于 :rule', | ||
| 126 | + ':attribute cannot be less than :rule' => ':attribute日期不能小于 :rule', | ||
| 127 | + ':attribute cannot exceed :rule' => ':attribute日期不能超过 :rule', | ||
| 128 | + ':attribute not within :rule' => '不在有效期内 :rule', | ||
| 129 | + 'access IP is not allowed' => '不允许的IP访问', | ||
| 130 | + 'access IP denied' => '禁止的IP访问', | ||
| 131 | + ':attribute out of accord with :2' => ':attribute和确认字段:2不一致', | ||
| 132 | + ':attribute cannot be same with :2' => ':attribute和比较字段:2不能相同', | ||
| 133 | + ':attribute must greater than or equal :rule' => ':attribute必须大于等于 :rule', | ||
| 134 | + ':attribute must greater than :rule' => ':attribute必须大于 :rule', | ||
| 135 | + ':attribute must less than or equal :rule' => ':attribute必须小于等于 :rule', | ||
| 136 | + ':attribute must less than :rule' => ':attribute必须小于 :rule', | ||
| 137 | + ':attribute must equal :rule' => ':attribute必须等于 :rule', | ||
| 138 | + ':attribute has exists' => ':attribute已存在', | ||
| 139 | + ':attribute not conform to the rules' => ':attribute不符合指定规则', | ||
| 140 | + 'invalid Request method' => '无效的请求类型', | ||
| 141 | + 'invalid token' => '令牌数据无效', | ||
| 142 | + 'not conform to the rules' => '规则错误', | ||
| 143 | +]; |
thinkphp/library/think/App.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// +---------------------------------------------------------------------- | ||
| 3 | +// | ThinkPHP [ WE CAN DO IT JUST THINK ] | ||
| 4 | +// +---------------------------------------------------------------------- | ||
| 5 | +// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved. | ||
| 6 | +// +---------------------------------------------------------------------- | ||
| 7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
| 8 | +// +---------------------------------------------------------------------- | ||
| 9 | +// | Author: liu21st <liu21st@gmail.com> | ||
| 10 | +// +---------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +namespace think; | ||
| 13 | + | ||
| 14 | +use think\exception\ClassNotFoundException; | ||
| 15 | +use think\exception\HttpResponseException; | ||
| 16 | +use think\route\Dispatch; | ||
| 17 | + | ||
| 18 | +/** | ||
| 19 | + * App 应用管理 | ||
| 20 | + */ | ||
| 21 | +class App extends Container | ||
| 22 | +{ | ||
| 23 | + const VERSION = '5.1.22'; | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 当前模块路径 | ||
| 27 | + * @var string | ||
| 28 | + */ | ||
| 29 | + protected $modulePath; | ||
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * 应用调试模式 | ||
| 33 | + * @var bool | ||
| 34 | + */ | ||
| 35 | + protected $appDebug = true; | ||
| 36 | + | ||
| 37 | + /** | ||
| 38 | + * 应用开始时间 | ||
| 39 | + * @var float | ||
| 40 | + */ | ||
| 41 | + protected $beginTime; | ||
| 42 | + | ||
| 43 | + /** | ||
| 44 | + * 应用内存初始占用 | ||
| 45 | + * @var integer | ||
| 46 | + */ | ||
| 47 | + protected $beginMem; | ||
| 48 | + | ||
| 49 | + /** | ||
| 50 | + * 应用类库命名空间 | ||
| 51 | + * @var string | ||
| 52 | + */ | ||
| 53 | + protected $namespace = 'app'; | ||
| 54 | + | ||
| 55 | + /** | ||
| 56 | + * 应用类库后缀 | ||
| 57 | + * @var bool | ||
| 58 | + */ | ||
| 59 | + protected $suffix = false; | ||
| 60 | + | ||
| 61 | + /** | ||
| 62 | + * 严格路由检测 | ||
| 63 | + * @var bool | ||
| 64 | + */ | ||
| 65 | + protected $routeMust; | ||
| 66 | + | ||
| 67 | + /** | ||
| 68 | + * 应用类库目录 | ||
| 69 | + * @var string | ||
| 70 | + */ | ||
| 71 | + protected $appPath; | ||
| 72 | + | ||
| 73 | + /** | ||
| 74 | + * 框架目录 | ||
| 75 | + * @var string | ||
| 76 | + */ | ||
| 77 | + protected $thinkPath; | ||
| 78 | + | ||
| 79 | + /** | ||
| 80 | + * 应用根目录 | ||
| 81 | + * @var string | ||
| 82 | + */ | ||
| 83 | + protected $rootPath; | ||
| 84 | + | ||
| 85 | + /** | ||
| 86 | + * 运行时目录 | ||
| 87 | + * @var string | ||
| 88 | + */ | ||
| 89 | + protected $runtimePath; | ||
| 90 | + | ||
| 91 | + /** | ||
| 92 | + * 配置目录 | ||
| 93 | + * @var string | ||
| 94 | + */ | ||
| 95 | + protected $configPath; | ||
| 96 | + | ||
| 97 | + /** | ||
| 98 | + * 路由目录 | ||
| 99 | + * @var string | ||
| 100 | + */ | ||
| 101 | + protected $routePath; | ||
| 102 | + | ||
| 103 | + /** | ||
| 104 | + * 配置后缀 | ||
| 105 | + * @var string | ||
| 106 | + */ | ||
| 107 | + protected $configExt; | ||
| 108 | + | ||
| 109 | + /** | ||
| 110 | + * 应用调度实例 | ||
| 111 | + * @var Dispatch | ||
| 112 | + */ | ||
| 113 | + protected $dispatch; | ||
| 114 | + | ||
| 115 | + /** | ||
| 116 | + * 绑定模块(控制器) | ||
| 117 | + * @var string | ||
| 118 | + */ | ||
| 119 | + protected $bindModule; | ||
| 120 | + | ||
| 121 | + /** | ||
| 122 | + * 初始化 | ||
| 123 | + * @var bool | ||
| 124 | + */ | ||
| 125 | + protected $initialized = false; | ||
| 126 | + | ||
| 127 | + public function __construct($appPath = '') | ||
| 128 | + { | ||
| 129 | + $this->appPath = $appPath ? realpath($appPath) . DIRECTORY_SEPARATOR : $this->getAppPath(); | ||
| 130 | + | ||
| 131 | + $this->thinkPath = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR; | ||
| 132 | + $this->rootPath = dirname($this->appPath) . DIRECTORY_SEPARATOR; | ||
| 133 | + $this->runtimePath = $this->rootPath . 'runtime' . DIRECTORY_SEPARATOR; | ||
| 134 | + $this->routePath = $this->rootPath . 'route' . DIRECTORY_SEPARATOR; | ||
| 135 | + $this->configPath = $this->rootPath . 'config' . DIRECTORY_SEPARATOR; | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + /** | ||
| 139 | + * 绑定模块或者控制器 | ||
| 140 | + * @access public | ||
| 141 | + * @param string $bind | ||
| 142 | + * @return $this | ||
| 143 | + */ | ||
| 144 | + public function bind($bind) | ||
| 145 | + { | ||
| 146 | + $this->bindModule = $bind; | ||
| 147 | + return $this; | ||
| 148 | + } | ||
| 149 | + | ||
| 150 | + /** | ||
| 151 | + * 设置应用类库目录 | ||
| 152 | + * @access public | ||
| 153 | + * @param string $path 路径 | ||
| 154 | + * @return $this | ||
| 155 | + */ | ||
| 156 | + public function path($path) | ||
| 157 | + { | ||
| 158 | + $this->appPath = $path; | ||
| 159 | + return $this; | ||
| 160 | + } | ||
| 161 | + | ||
| 162 | + /** | ||
| 163 | + * 初始化应用 | ||
| 164 | + * @access public | ||
| 165 | + * @return void | ||
| 166 | + */ | ||
| 167 | + public function initialize() | ||
| 168 | + { | ||
| 169 | + if ($this->initialized) { | ||
| 170 | + return; | ||
| 171 | + } | ||
| 172 | + | ||
| 173 | + $this->initialized = true; | ||
| 174 | + $this->beginTime = microtime(true); | ||
| 175 | + $this->beginMem = memory_get_usage(); | ||
| 176 | + | ||
| 177 | + static::setInstance($this); | ||
| 178 | + | ||
| 179 | + $this->instance('app', $this); | ||
| 180 | + | ||
| 181 | + $this->configExt = $this->env->get('config_ext', '.php'); | ||
| 182 | + | ||
| 183 | + // 加载惯例配置文件 | ||
| 184 | + $this->config->set(include $this->thinkPath . 'convention.php'); | ||
| 185 | + | ||
| 186 | + // 设置路径环境变量 | ||
| 187 | + $this->env->set([ | ||
| 188 | + 'think_path' => $this->thinkPath, | ||
| 189 | + 'root_path' => $this->rootPath, | ||
| 190 | + 'app_path' => $this->appPath, | ||
| 191 | + 'config_path' => $this->configPath, | ||
| 192 | + 'route_path' => $this->routePath, | ||
| 193 | + 'runtime_path' => $this->runtimePath, | ||
| 194 | + 'extend_path' => $this->rootPath . 'extend' . DIRECTORY_SEPARATOR, | ||
| 195 | + 'vendor_path' => $this->rootPath . 'vendor' . DIRECTORY_SEPARATOR, | ||
| 196 | + ]); | ||
| 197 | + | ||
| 198 | + // 加载环境变量配置文件 | ||
| 199 | + if (is_file($this->rootPath . '.env')) { | ||
| 200 | + $this->env->load($this->rootPath . '.env'); | ||
| 201 | + } | ||
| 202 | + | ||
| 203 | + $this->namespace = $this->env->get('app_namespace', $this->namespace); | ||
| 204 | + $this->env->set('app_namespace', $this->namespace); | ||
| 205 | + | ||
| 206 | + // 注册应用命名空间 | ||
| 207 | + Loader::addNamespace($this->namespace, $this->appPath); | ||
| 208 | + | ||
| 209 | + // 初始化应用 | ||
| 210 | + $this->init(); | ||
| 211 | + | ||
| 212 | + // 开启类名后缀 | ||
| 213 | + $this->suffix = $this->config('app.class_suffix'); | ||
| 214 | + | ||
| 215 | + // 应用调试模式 | ||
| 216 | + $this->appDebug = $this->env->get('app_debug', $this->config('app.app_debug')); | ||
| 217 | + $this->env->set('app_debug', $this->appDebug); | ||
| 218 | + | ||
| 219 | + if (!$this->appDebug) { | ||
| 220 | + ini_set('display_errors', 'Off'); | ||
| 221 | + } elseif (PHP_SAPI != 'cli') { | ||
| 222 | + //重新申请一块比较大的buffer | ||
| 223 | + if (ob_get_level() > 0) { | ||
| 224 | + $output = ob_get_clean(); | ||
| 225 | + } | ||
| 226 | + ob_start(); | ||
| 227 | + if (!empty($output)) { | ||
| 228 | + echo $output; | ||
| 229 | + } | ||
| 230 | + } | ||
| 231 | + | ||
| 232 | + // 注册异常处理类 | ||
| 233 | + if ($this->config('app.exception_handle')) { | ||
| 234 | + Error::setExceptionHandler($this->config('app.exception_handle')); | ||
| 235 | + } | ||
| 236 | + | ||
| 237 | + // 注册根命名空间 | ||
| 238 | + if (!empty($this->config('app.root_namespace'))) { | ||
| 239 | + Loader::addNamespace($this->config('app.root_namespace')); | ||
| 240 | + } | ||
| 241 | + | ||
| 242 | + // 加载composer autofile文件 | ||
| 243 | + Loader::loadComposerAutoloadFiles(); | ||
| 244 | + | ||
| 245 | + // 注册类库别名 | ||
| 246 | + Loader::addClassAlias($this->config->pull('alias')); | ||
| 247 | + | ||
| 248 | + // 数据库配置初始化 | ||
| 249 | + Db::init($this->config->pull('database')); | ||
| 250 | + | ||
| 251 | + // 设置系统时区 | ||
| 252 | + date_default_timezone_set($this->config('app.default_timezone')); | ||
| 253 | + | ||
| 254 | + // 读取语言包 | ||
| 255 | + $this->loadLangPack(); | ||
| 256 | + | ||
| 257 | + // 路由初始化 | ||
| 258 | + $this->routeInit(); | ||
| 259 | + } | ||
| 260 | + | ||
| 261 | + /** | ||
| 262 | + * 初始化应用或模块 | ||
| 263 | + * @access public | ||
| 264 | + * @param string $module 模块名 | ||
| 265 | + * @return void | ||
| 266 | + */ | ||
| 267 | + public function init($module = '') | ||
| 268 | + { | ||
| 269 | + // 定位模块目录 | ||
| 270 | + $module = $module ? $module . DIRECTORY_SEPARATOR : ''; | ||
| 271 | + $path = $this->appPath . $module; | ||
| 272 | + | ||
| 273 | + // 加载初始化文件 | ||
| 274 | + if (is_file($path . 'init.php')) { | ||
| 275 | + include $path . 'init.php'; | ||
| 276 | + } elseif (is_file($this->runtimePath . $module . 'init.php')) { | ||
| 277 | + include $this->runtimePath . $module . 'init.php'; | ||
| 278 | + } else { | ||
| 279 | + // 加载行为扩展文件 | ||
| 280 | + if (is_file($path . 'tags.php')) { | ||
| 281 | + $tags = include $path . 'tags.php'; | ||
| 282 | + if (is_array($tags)) { | ||
| 283 | + $this->hook->import($tags); | ||
| 284 | + } | ||
| 285 | + } | ||
| 286 | + | ||
| 287 | + // 加载公共文件 | ||
| 288 | + if (is_file($path . 'common.php')) { | ||
| 289 | + include_once $path . 'common.php'; | ||
| 290 | + } | ||
| 291 | + | ||
| 292 | + if ('' == $module) { | ||
| 293 | + // 加载系统助手函数 | ||
| 294 | + include $this->thinkPath . 'helper.php'; | ||
| 295 | + } | ||
| 296 | + | ||
| 297 | + // 加载中间件 | ||
| 298 | + if (is_file($path . 'middleware.php')) { | ||
| 299 | + $middleware = include $path . 'middleware.php'; | ||
| 300 | + if (is_array($middleware)) { | ||
| 301 | + $this->middleware->import($middleware); | ||
| 302 | + } | ||
| 303 | + } | ||
| 304 | + | ||
| 305 | + // 注册服务的容器对象实例 | ||
| 306 | + if (is_file($path . 'provider.php')) { | ||
| 307 | + $provider = include $path . 'provider.php'; | ||
| 308 | + if (is_array($provider)) { | ||
| 309 | + $this->bindTo($provider); | ||
| 310 | + } | ||
| 311 | + } | ||
| 312 | + | ||
| 313 | + // 自动读取配置文件 | ||
| 314 | + if (is_dir($path . 'config')) { | ||
| 315 | + $dir = $path . 'config'.DIRECTORY_SEPARATOR; | ||
| 316 | + } elseif (is_dir($this->configPath . $module)) { | ||
| 317 | + $dir = $this->configPath . $module; | ||
| 318 | + } | ||
| 319 | + | ||
| 320 | + $files = isset($dir) ? scandir($dir) : []; | ||
| 321 | + | ||
| 322 | + foreach ($files as $file) { | ||
| 323 | + if ('.' . pathinfo($file, PATHINFO_EXTENSION) === $this->configExt) { | ||
| 324 | + $this->config->load($dir . $file, pathinfo($file, PATHINFO_FILENAME)); | ||
| 325 | + } | ||
| 326 | + } | ||
| 327 | + } | ||
| 328 | + | ||
| 329 | + $this->setModulePath($path); | ||
| 330 | + | ||
| 331 | + if ($module) { | ||
| 332 | + // 对容器中的对象实例进行配置更新 | ||
| 333 | + $this->containerConfigUpdate($module); | ||
| 334 | + } | ||
| 335 | + } | ||
| 336 | + | ||
| 337 | + protected function containerConfigUpdate($module) | ||
| 338 | + { | ||
| 339 | + $config = $this->config->get(); | ||
| 340 | + | ||
| 341 | + // 注册异常处理类 | ||
| 342 | + if ($config['app']['exception_handle']) { | ||
| 343 | + Error::setExceptionHandler($config['app']['exception_handle']); | ||
| 344 | + } | ||
| 345 | + | ||
| 346 | + Db::init($config['database']); | ||
| 347 | + $this->middleware->setConfig($config['middleware']); | ||
| 348 | + $this->route->setConfig($config['app']); | ||
| 349 | + $this->request->init($config['app']); | ||
| 350 | + $this->cookie->init($config['cookie']); | ||
| 351 | + $this->view->init($config['template']); | ||
| 352 | + $this->log->init($config['log']); | ||
| 353 | + $this->session->setConfig($config['session']); | ||
| 354 | + $this->debug->setConfig($config['trace']); | ||
| 355 | + $this->cache->init($config['cache'], true); | ||
| 356 | + | ||
| 357 | + // 加载当前模块语言包 | ||
| 358 | + $this->lang->load($this->appPath . $module . DIRECTORY_SEPARATOR . 'lang' . DIRECTORY_SEPARATOR . $this->request->langset() . '.php'); | ||
| 359 | + | ||
| 360 | + // 模块请求缓存检查 | ||
| 361 | + $this->checkRequestCache( | ||
| 362 | + $config['app']['request_cache'], | ||
| 363 | + $config['app']['request_cache_expire'], | ||
| 364 | + $config['app']['request_cache_except'] | ||
| 365 | + ); | ||
| 366 | + } | ||
| 367 | + | ||
| 368 | + /** | ||
| 369 | + * 执行应用程序 | ||
| 370 | + * @access public | ||
| 371 | + * @return Response | ||
| 372 | + * @throws Exception | ||
| 373 | + */ | ||
| 374 | + public function run() | ||
| 375 | + { | ||
| 376 | + try { | ||
| 377 | + // 初始化应用 | ||
| 378 | + $this->initialize(); | ||
| 379 | + | ||
| 380 | + // 监听app_init | ||
| 381 | + $this->hook->listen('app_init'); | ||
| 382 | + | ||
| 383 | + if ($this->bindModule) { | ||
| 384 | + // 模块/控制器绑定 | ||
| 385 | + $this->route->bind($this->bindModule); | ||
| 386 | + } elseif ($this->config('app.auto_bind_module')) { | ||
| 387 | + // 入口自动绑定 | ||
| 388 | + $name = pathinfo($this->request->baseFile(), PATHINFO_FILENAME); | ||
| 389 | + if ($name && 'index' != $name && is_dir($this->appPath . $name)) { | ||
| 390 | + $this->route->bind($name); | ||
| 391 | + } | ||
| 392 | + } | ||
| 393 | + | ||
| 394 | + // 监听app_dispatch | ||
| 395 | + $this->hook->listen('app_dispatch'); | ||
| 396 | + | ||
| 397 | + $dispatch = $this->dispatch; | ||
| 398 | + | ||
| 399 | + if (empty($dispatch)) { | ||
| 400 | + // 路由检测 | ||
| 401 | + $dispatch = $this->routeCheck()->init(); | ||
| 402 | + } | ||
| 403 | + | ||
| 404 | + // 记录当前调度信息 | ||
| 405 | + $this->request->dispatch($dispatch); | ||
| 406 | + | ||
| 407 | + // 记录路由和请求信息 | ||
| 408 | + if ($this->appDebug) { | ||
| 409 | + $this->log('[ ROUTE ] ' . var_export($this->request->routeInfo(), true)); | ||
| 410 | + $this->log('[ HEADER ] ' . var_export($this->request->header(), true)); | ||
| 411 | + $this->log('[ PARAM ] ' . var_export($this->request->param(), true)); | ||
| 412 | + } | ||
| 413 | + | ||
| 414 | + // 监听app_begin | ||
| 415 | + $this->hook->listen('app_begin'); | ||
| 416 | + | ||
| 417 | + // 请求缓存检查 | ||
| 418 | + $this->checkRequestCache( | ||
| 419 | + $this->config('request_cache'), | ||
| 420 | + $this->config('request_cache_expire'), | ||
| 421 | + $this->config('request_cache_except') | ||
| 422 | + ); | ||
| 423 | + | ||
| 424 | + $data = null; | ||
| 425 | + } catch (HttpResponseException $exception) { | ||
| 426 | + $dispatch = null; | ||
| 427 | + $data = $exception->getResponse(); | ||
| 428 | + } | ||
| 429 | + | ||
| 430 | + $this->middleware->add(function (Request $request, $next) use ($dispatch, $data) { | ||
| 431 | + return is_null($data) ? $dispatch->run() : $data; | ||
| 432 | + }); | ||
| 433 | + | ||
| 434 | + $response = $this->middleware->dispatch($this->request); | ||
| 435 | + | ||
| 436 | + // 监听app_end | ||
| 437 | + $this->hook->listen('app_end', $response); | ||
| 438 | + | ||
| 439 | + return $response; | ||
| 440 | + } | ||
| 441 | + | ||
| 442 | + protected function getRouteCacheKey() | ||
| 443 | + { | ||
| 444 | + if ($this->config->get('route_check_cache_key')) { | ||
| 445 | + $closure = $this->config->get('route_check_cache_key'); | ||
| 446 | + $routeKey = $closure($this->request); | ||
| 447 | + } else { | ||
| 448 | + $routeKey = md5($this->request->baseUrl(true) . ':' . $this->request->method()); | ||
| 449 | + } | ||
| 450 | + | ||
| 451 | + return $routeKey; | ||
| 452 | + } | ||
| 453 | + | ||
| 454 | + protected function loadLangPack() | ||
| 455 | + { | ||
| 456 | + // 读取默认语言 | ||
| 457 | + $this->lang->range($this->config('app.default_lang')); | ||
| 458 | + | ||
| 459 | + if ($this->config('app.lang_switch_on')) { | ||
| 460 | + // 开启多语言机制 检测当前语言 | ||
| 461 | + $this->lang->detect(); | ||
| 462 | + } | ||
| 463 | + | ||
| 464 | + $this->request->setLangset($this->lang->range()); | ||
| 465 | + | ||
| 466 | + // 加载系统语言包 | ||
| 467 | + $this->lang->load([ | ||
| 468 | + $this->thinkPath . 'lang' . DIRECTORY_SEPARATOR . $this->request->langset() . '.php', | ||
| 469 | + $this->appPath . 'lang' . DIRECTORY_SEPARATOR . $this->request->langset() . '.php', | ||
| 470 | + ]); | ||
| 471 | + } | ||
| 472 | + | ||
| 473 | + /** | ||
| 474 | + * 设置当前地址的请求缓存 | ||
| 475 | + * @access public | ||
| 476 | + * @param string $key 缓存标识,支持变量规则 ,例如 item/:name/:id | ||
| 477 | + * @param mixed $expire 缓存有效期 | ||
| 478 | + * @param array $except 缓存排除 | ||
| 479 | + * @param string $tag 缓存标签 | ||
| 480 | + * @return void | ||
| 481 | + */ | ||
| 482 | + public function checkRequestCache($key, $expire = null, $except = [], $tag = null) | ||
| 483 | + { | ||
| 484 | + $cache = $this->request->cache($key, $expire, $except, $tag); | ||
| 485 | + | ||
| 486 | + if ($cache) { | ||
| 487 | + list($key, $expire, $tag) = $cache; | ||
| 488 | + if (strtotime($this->request->server('HTTP_IF_MODIFIED_SINCE')) + $expire > $this->request->server('REQUEST_TIME')) { | ||
| 489 | + // 读取缓存 | ||
| 490 | + $response = Response::create()->code(304); | ||
| 491 | + throw new HttpResponseException($response); | ||
| 492 | + } elseif ($this->cache->has($key)) { | ||
| 493 | + list($content, $header) = $this->cache->get($key); | ||
| 494 | + | ||
| 495 | + $response = Response::create($content)->header($header); | ||
| 496 | + throw new HttpResponseException($response); | ||
| 497 | + } | ||
| 498 | + } | ||
| 499 | + } | ||
| 500 | + | ||
| 501 | + /** | ||
| 502 | + * 设置当前请求的调度信息 | ||
| 503 | + * @access public | ||
| 504 | + * @param Dispatch $dispatch 调度信息 | ||
| 505 | + * @return $this | ||
| 506 | + */ | ||
| 507 | + public function dispatch(Dispatch $dispatch) | ||
| 508 | + { | ||
| 509 | + $this->dispatch = $dispatch; | ||
| 510 | + return $this; | ||
| 511 | + } | ||
| 512 | + | ||
| 513 | + /** | ||
| 514 | + * 记录调试信息 | ||
| 515 | + * @access public | ||
| 516 | + * @param mixed $msg 调试信息 | ||
| 517 | + * @param string $type 信息类型 | ||
| 518 | + * @return void | ||
| 519 | + */ | ||
| 520 | + public function log($msg, $type = 'info') | ||
| 521 | + { | ||
| 522 | + $this->appDebug && $this->log->record($msg, $type); | ||
| 523 | + } | ||
| 524 | + | ||
| 525 | + /** | ||
| 526 | + * 获取配置参数 为空则获取所有配置 | ||
| 527 | + * @access public | ||
| 528 | + * @param string $name 配置参数名(支持二级配置 .号分割) | ||
| 529 | + * @return mixed | ||
| 530 | + */ | ||
| 531 | + public function config($name = '') | ||
| 532 | + { | ||
| 533 | + return $this->config->get($name); | ||
| 534 | + } | ||
| 535 | + | ||
| 536 | + /** | ||
| 537 | + * 路由初始化 导入路由定义规则 | ||
| 538 | + * @access public | ||
| 539 | + * @return void | ||
| 540 | + */ | ||
| 541 | + public function routeInit() | ||
| 542 | + { | ||
| 543 | + // 路由检测 | ||
| 544 | + $files = scandir($this->routePath); | ||
| 545 | + foreach ($files as $file) { | ||
| 546 | + if (strpos($file, '.php')) { | ||
| 547 | + $filename = $this->routePath . $file; | ||
| 548 | + // 导入路由配置 | ||
| 549 | + $rules = include $filename; | ||
| 550 | + if (is_array($rules)) { | ||
| 551 | + $this->route->import($rules); | ||
| 552 | + } | ||
| 553 | + } | ||
| 554 | + } | ||
| 555 | + | ||
| 556 | + if ($this->route->config('route_annotation')) { | ||
| 557 | + // 自动生成路由定义 | ||
| 558 | + if ($this->appDebug) { | ||
| 559 | + $suffix = $this->route->config('controller_suffix') || $this->route->config('class_suffix'); | ||
| 560 | + $this->build->buildRoute($suffix); | ||
| 561 | + } | ||
| 562 | + | ||
| 563 | + $filename = $this->runtimePath . 'build_route.php'; | ||
| 564 | + | ||
| 565 | + if (is_file($filename)) { | ||
| 566 | + include $filename; | ||
| 567 | + } | ||
| 568 | + } | ||
| 569 | + } | ||
| 570 | + | ||
| 571 | + /** | ||
| 572 | + * URL路由检测(根据PATH_INFO) | ||
| 573 | + * @access public | ||
| 574 | + * @return Dispatch | ||
| 575 | + */ | ||
| 576 | + public function routeCheck() | ||
| 577 | + { | ||
| 578 | + // 检测路由缓存 | ||
| 579 | + if (!$this->appDebug && $this->config->get('route_check_cache')) { | ||
| 580 | + $routeKey = $this->getRouteCacheKey(); | ||
| 581 | + $option = $this->config->get('route_cache_option') ?: $this->cache->getConfig(); | ||
| 582 | + | ||
| 583 | + if ($this->cache->connect($option)->has($routeKey)) { | ||
| 584 | + return $this->cache->connect($option)->get($routeKey); | ||
| 585 | + } | ||
| 586 | + } | ||
| 587 | + | ||
| 588 | + // 获取应用调度信息 | ||
| 589 | + $path = $this->request->path(); | ||
| 590 | + | ||
| 591 | + // 是否强制路由模式 | ||
| 592 | + $must = !is_null($this->routeMust) ? $this->routeMust : $this->route->config('url_route_must'); | ||
| 593 | + | ||
| 594 | + // 路由检测 返回一个Dispatch对象 | ||
| 595 | + $dispatch = $this->route->check($path, $must); | ||
| 596 | + | ||
| 597 | + if (!empty($routeKey)) { | ||
| 598 | + try { | ||
| 599 | + $this->cache | ||
| 600 | + ->connect($option) | ||
| 601 | + ->tag('route_cache') | ||
| 602 | + ->set($routeKey, $dispatch); | ||
| 603 | + } catch (\Exception $e) { | ||
| 604 | + // 存在闭包的时候缓存无效 | ||
| 605 | + } | ||
| 606 | + } | ||
| 607 | + | ||
| 608 | + return $dispatch; | ||
| 609 | + } | ||
| 610 | + | ||
| 611 | + /** | ||
| 612 | + * 设置应用的路由检测机制 | ||
| 613 | + * @access public | ||
| 614 | + * @param bool $must 是否强制检测路由 | ||
| 615 | + * @return $this | ||
| 616 | + */ | ||
| 617 | + public function routeMust($must = false) | ||
| 618 | + { | ||
| 619 | + $this->routeMust = $must; | ||
| 620 | + return $this; | ||
| 621 | + } | ||
| 622 | + | ||
| 623 | + /** | ||
| 624 | + * 解析模块和类名 | ||
| 625 | + * @access protected | ||
| 626 | + * @param string $name 资源地址 | ||
| 627 | + * @param string $layer 验证层名称 | ||
| 628 | + * @param bool $appendSuffix 是否添加类名后缀 | ||
| 629 | + * @return array | ||
| 630 | + */ | ||
| 631 | + protected function parseModuleAndClass($name, $layer, $appendSuffix) | ||
| 632 | + { | ||
| 633 | + if (false !== strpos($name, '\\')) { | ||
| 634 | + $class = $name; | ||
| 635 | + $module = $this->request->module(); | ||
| 636 | + } else { | ||
| 637 | + if (strpos($name, '/')) { | ||
| 638 | + list($module, $name) = explode('/', $name, 2); | ||
| 639 | + } else { | ||
| 640 | + $module = $this->request->module(); | ||
| 641 | + } | ||
| 642 | + | ||
| 643 | + $class = $this->parseClass($module, $layer, $name, $appendSuffix); | ||
| 644 | + } | ||
| 645 | + | ||
| 646 | + return [$module, $class]; | ||
| 647 | + } | ||
| 648 | + | ||
| 649 | + /** | ||
| 650 | + * 实例化应用类库 | ||
| 651 | + * @access public | ||
| 652 | + * @param string $name 类名称 | ||
| 653 | + * @param string $layer 业务层名称 | ||
| 654 | + * @param bool $appendSuffix 是否添加类名后缀 | ||
| 655 | + * @param string $common 公共模块名 | ||
| 656 | + * @return object | ||
| 657 | + * @throws ClassNotFoundException | ||
| 658 | + */ | ||
| 659 | + public function create($name, $layer, $appendSuffix = false, $common = 'common') | ||
| 660 | + { | ||
| 661 | + $guid = $name . $layer; | ||
| 662 | + | ||
| 663 | + if ($this->__isset($guid)) { | ||
| 664 | + return $this->__get($guid); | ||
| 665 | + } | ||
| 666 | + | ||
| 667 | + list($module, $class) = $this->parseModuleAndClass($name, $layer, $appendSuffix); | ||
| 668 | + | ||
| 669 | + if (class_exists($class)) { | ||
| 670 | + $object = $this->__get($class); | ||
| 671 | + } else { | ||
| 672 | + $class = str_replace('\\' . $module . '\\', '\\' . $common . '\\', $class); | ||
| 673 | + if (class_exists($class)) { | ||
| 674 | + $object = $this->__get($class); | ||
| 675 | + } else { | ||
| 676 | + throw new ClassNotFoundException('class not exists:' . $class, $class); | ||
| 677 | + } | ||
| 678 | + } | ||
| 679 | + | ||
| 680 | + $this->__set($guid, $class); | ||
| 681 | + | ||
| 682 | + return $object; | ||
| 683 | + } | ||
| 684 | + | ||
| 685 | + /** | ||
| 686 | + * 实例化(分层)模型 | ||
| 687 | + * @access public | ||
| 688 | + * @param string $name Model名称 | ||
| 689 | + * @param string $layer 业务层名称 | ||
| 690 | + * @param bool $appendSuffix 是否添加类名后缀 | ||
| 691 | + * @param string $common 公共模块名 | ||
| 692 | + * @return Model | ||
| 693 | + * @throws ClassNotFoundException | ||
| 694 | + */ | ||
| 695 | + public function model($name = '', $layer = 'model', $appendSuffix = false, $common = 'common') | ||
| 696 | + { | ||
| 697 | + return $this->create($name, $layer, $appendSuffix, $common); | ||
| 698 | + } | ||
| 699 | + | ||
| 700 | + /** | ||
| 701 | + * 实例化(分层)控制器 格式:[模块名/]控制器名 | ||
| 702 | + * @access public | ||
| 703 | + * @param string $name 资源地址 | ||
| 704 | + * @param string $layer 控制层名称 | ||
| 705 | + * @param bool $appendSuffix 是否添加类名后缀 | ||
| 706 | + * @param string $empty 空控制器名称 | ||
| 707 | + * @return object | ||
| 708 | + * @throws ClassNotFoundException | ||
| 709 | + */ | ||
| 710 | + public function controller($name, $layer = 'controller', $appendSuffix = false, $empty = '') | ||
| 711 | + { | ||
| 712 | + list($module, $class) = $this->parseModuleAndClass($name, $layer, $appendSuffix); | ||
| 713 | + | ||
| 714 | + if (class_exists($class)) { | ||
| 715 | + return $this->__get($class); | ||
| 716 | + } elseif ($empty && class_exists($emptyClass = $this->parseClass($module, $layer, $empty, $appendSuffix))) { | ||
| 717 | + return $this->__get($emptyClass); | ||
| 718 | + } | ||
| 719 | + | ||
| 720 | + throw new ClassNotFoundException('class not exists:' . $class, $class); | ||
| 721 | + } | ||
| 722 | + | ||
| 723 | + /** | ||
| 724 | + * 实例化验证类 格式:[模块名/]验证器名 | ||
| 725 | + * @access public | ||
| 726 | + * @param string $name 资源地址 | ||
| 727 | + * @param string $layer 验证层名称 | ||
| 728 | + * @param bool $appendSuffix 是否添加类名后缀 | ||
| 729 | + * @param string $common 公共模块名 | ||
| 730 | + * @return Validate | ||
| 731 | + * @throws ClassNotFoundException | ||
| 732 | + */ | ||
| 733 | + public function validate($name = '', $layer = 'validate', $appendSuffix = false, $common = 'common') | ||
| 734 | + { | ||
| 735 | + $name = $name ?: $this->config('default_validate'); | ||
| 736 | + | ||
| 737 | + if (empty($name)) { | ||
| 738 | + return new Validate; | ||
| 739 | + } | ||
| 740 | + | ||
| 741 | + return $this->create($name, $layer, $appendSuffix, $common); | ||
| 742 | + } | ||
| 743 | + | ||
| 744 | + /** | ||
| 745 | + * 数据库初始化 | ||
| 746 | + * @access public | ||
| 747 | + * @param mixed $config 数据库配置 | ||
| 748 | + * @param bool|string $name 连接标识 true 强制重新连接 | ||
| 749 | + * @return \think\db\Query | ||
| 750 | + */ | ||
| 751 | + public function db($config = [], $name = false) | ||
| 752 | + { | ||
| 753 | + return Db::connect($config, $name); | ||
| 754 | + } | ||
| 755 | + | ||
| 756 | + /** | ||
| 757 | + * 远程调用模块的操作方法 参数格式 [模块/控制器/]操作 | ||
| 758 | + * @access public | ||
| 759 | + * @param string $url 调用地址 | ||
| 760 | + * @param string|array $vars 调用参数 支持字符串和数组 | ||
| 761 | + * @param string $layer 要调用的控制层名称 | ||
| 762 | + * @param bool $appendSuffix 是否添加类名后缀 | ||
| 763 | + * @return mixed | ||
| 764 | + * @throws ClassNotFoundException | ||
| 765 | + */ | ||
| 766 | + public function action($url, $vars = [], $layer = 'controller', $appendSuffix = false) | ||
| 767 | + { | ||
| 768 | + $info = pathinfo($url); | ||
| 769 | + $action = $info['basename']; | ||
| 770 | + $module = '.' != $info['dirname'] ? $info['dirname'] : $this->request->controller(); | ||
| 771 | + $class = $this->controller($module, $layer, $appendSuffix); | ||
| 772 | + | ||
| 773 | + if (is_scalar($vars)) { | ||
| 774 | + if (strpos($vars, '=')) { | ||
| 775 | + parse_str($vars, $vars); | ||
| 776 | + } else { | ||
| 777 | + $vars = [$vars]; | ||
| 778 | + } | ||
| 779 | + } | ||
| 780 | + | ||
| 781 | + return $this->invokeMethod([$class, $action . $this->config('action_suffix')], $vars); | ||
| 782 | + } | ||
| 783 | + | ||
| 784 | + /** | ||
| 785 | + * 解析应用类的类名 | ||
| 786 | + * @access public | ||
| 787 | + * @param string $module 模块名 | ||
| 788 | + * @param string $layer 层名 controller model ... | ||
| 789 | + * @param string $name 类名 | ||
| 790 | + * @param bool $appendSuffix | ||
| 791 | + * @return string | ||
| 792 | + */ | ||
| 793 | + public function parseClass($module, $layer, $name, $appendSuffix = false) | ||
| 794 | + { | ||
| 795 | + $name = str_replace(['/', '.'], '\\', $name); | ||
| 796 | + $array = explode('\\', $name); | ||
| 797 | + $class = Loader::parseName(array_pop($array), 1) . ($this->suffix || $appendSuffix ? ucfirst($layer) : ''); | ||
| 798 | + $path = $array ? implode('\\', $array) . '\\' : ''; | ||
| 799 | + | ||
| 800 | + return $this->namespace . '\\' . ($module ? $module . '\\' : '') . $layer . '\\' . $path . $class; | ||
| 801 | + } | ||
| 802 | + | ||
| 803 | + /** | ||
| 804 | + * 获取框架版本 | ||
| 805 | + * @access public | ||
| 806 | + * @return string | ||
| 807 | + */ | ||
| 808 | + public function version() | ||
| 809 | + { | ||
| 810 | + return static::VERSION; | ||
| 811 | + } | ||
| 812 | + | ||
| 813 | + /** | ||
| 814 | + * 是否为调试模式 | ||
| 815 | + * @access public | ||
| 816 | + * @return bool | ||
| 817 | + */ | ||
| 818 | + public function isDebug() | ||
| 819 | + { | ||
| 820 | + return $this->appDebug; | ||
| 821 | + } | ||
| 822 | + | ||
| 823 | + /** | ||
| 824 | + * 获取模块路径 | ||
| 825 | + * @access public | ||
| 826 | + * @return string | ||
| 827 | + */ | ||
| 828 | + public function getModulePath() | ||
| 829 | + { | ||
| 830 | + return $this->modulePath; | ||
| 831 | + } | ||
| 832 | + | ||
| 833 | + /** | ||
| 834 | + * 设置模块路径 | ||
| 835 | + * @access public | ||
| 836 | + * @param string $path 路径 | ||
| 837 | + * @return void | ||
| 838 | + */ | ||
| 839 | + public function setModulePath($path) | ||
| 840 | + { | ||
| 841 | + $this->modulePath = $path; | ||
| 842 | + $this->env->set('module_path', $path); | ||
| 843 | + } | ||
| 844 | + | ||
| 845 | + /** | ||
| 846 | + * 获取应用根目录 | ||
| 847 | + * @access public | ||
| 848 | + * @return string | ||
| 849 | + */ | ||
| 850 | + public function getRootPath() | ||
| 851 | + { | ||
| 852 | + return $this->rootPath; | ||
| 853 | + } | ||
| 854 | + | ||
| 855 | + /** | ||
| 856 | + * 获取应用类库目录 | ||
| 857 | + * @access public | ||
| 858 | + * @return string | ||
| 859 | + */ | ||
| 860 | + public function getAppPath() | ||
| 861 | + { | ||
| 862 | + if (is_null($this->appPath)) { | ||
| 863 | + $this->appPath = Loader::getRootPath() . 'application' . DIRECTORY_SEPARATOR; | ||
| 864 | + } | ||
| 865 | + | ||
| 866 | + return $this->appPath; | ||
| 867 | + } | ||
| 868 | + | ||
| 869 | + /** | ||
| 870 | + * 获取应用运行时目录 | ||
| 871 | + * @access public | ||
| 872 | + * @return string | ||
| 873 | + */ | ||
| 874 | + public function getRuntimePath() | ||
| 875 | + { | ||
| 876 | + return $this->runtimePath; | ||
| 877 | + } | ||
| 878 | + | ||
| 879 | + /** | ||
| 880 | + * 获取核心框架目录 | ||
| 881 | + * @access public | ||
| 882 | + * @return string | ||
| 883 | + */ | ||
| 884 | + public function getThinkPath() | ||
| 885 | + { | ||
| 886 | + return $this->thinkPath; | ||
| 887 | + } | ||
| 888 | + | ||
| 889 | + /** | ||
| 890 | + * 获取路由目录 | ||
| 891 | + * @access public | ||
| 892 | + * @return string | ||
| 893 | + */ | ||
| 894 | + public function getRoutePath() | ||
| 895 | + { | ||
| 896 | + return $this->routePath; | ||
| 897 | + } | ||
| 898 | + | ||
| 899 | + /** | ||
| 900 | + * 获取应用配置目录 | ||
| 901 | + * @access public | ||
| 902 | + * @return string | ||
| 903 | + */ | ||
| 904 | + public function getConfigPath() | ||
| 905 | + { | ||
| 906 | + return $this->configPath; | ||
| 907 | + } | ||
| 908 | + | ||
| 909 | + /** | ||
| 910 | + * 获取配置后缀 | ||
| 911 | + * @access public | ||
| 912 | + * @return string | ||
| 913 | + */ | ||
| 914 | + public function getConfigExt() | ||
| 915 | + { | ||
| 916 | + return $this->configExt; | ||
| 917 | + } | ||
| 918 | + | ||
| 919 | + /** | ||
| 920 | + * 获取应用类库命名空间 | ||
| 921 | + * @access public | ||
| 922 | + * @return string | ||
| 923 | + */ | ||
| 924 | + public function getNamespace() | ||
| 925 | + { | ||
| 926 | + return $this->namespace; | ||
| 927 | + } | ||
| 928 | + | ||
| 929 | + /** | ||
| 930 | + * 设置应用类库命名空间 | ||
| 931 | + * @access public | ||
| 932 | + * @param string $namespace 命名空间名称 | ||
| 933 | + * @return $this | ||
| 934 | + */ | ||
| 935 | + public function setNamespace($namespace) | ||
| 936 | + { | ||
| 937 | + $this->namespace = $namespace; | ||
| 938 | + return $this; | ||
| 939 | + } | ||
| 940 | + | ||
| 941 | + /** | ||
| 942 | + * 是否启用类库后缀 | ||
| 943 | + * @access public | ||
| 944 | + * @return bool | ||
| 945 | + */ | ||
| 946 | + public function getSuffix() | ||
| 947 | + { | ||
| 948 | + return $this->suffix; | ||
| 949 | + } | ||
| 950 | + | ||
| 951 | + /** | ||
| 952 | + * 获取应用开启时间 | ||
| 953 | + * @access public | ||
| 954 | + * @return float | ||
| 955 | + */ | ||
| 956 | + public function getBeginTime() | ||
| 957 | + { | ||
| 958 | + return $this->beginTime; | ||
| 959 | + } | ||
| 960 | + | ||
| 961 | + /** | ||
| 962 | + * 获取应用初始内存占用 | ||
| 963 | + * @access public | ||
| 964 | + * @return integer | ||
| 965 | + */ | ||
| 966 | + public function getBeginMem() | ||
| 967 | + { | ||
| 968 | + return $this->beginMem; | ||
| 969 | + } | ||
| 970 | + | ||
| 971 | +} |
thinkphp/library/think/Build.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// +---------------------------------------------------------------------- | ||
| 3 | +// | ThinkPHP [ WE CAN DO IT JUST THINK ] | ||
| 4 | +// +---------------------------------------------------------------------- | ||
| 5 | +// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved. | ||
| 6 | +// +---------------------------------------------------------------------- | ||
| 7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
| 8 | +// +---------------------------------------------------------------------- | ||
| 9 | +// | Author: liu21st <liu21st@gmail.com> | ||
| 10 | +// +---------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +namespace think; | ||
| 13 | + | ||
| 14 | +class Build | ||
| 15 | +{ | ||
| 16 | + /** | ||
| 17 | + * 应用对象 | ||
| 18 | + * @var App | ||
| 19 | + */ | ||
| 20 | + protected $app; | ||
| 21 | + | ||
| 22 | + /** | ||
| 23 | + * 应用目录 | ||
| 24 | + * @var string | ||
| 25 | + */ | ||
| 26 | + protected $basePath; | ||
| 27 | + | ||
| 28 | + public function __construct(App $app) | ||
| 29 | + { | ||
| 30 | + $this->app = $app; | ||
| 31 | + $this->basePath = $this->app->getAppPath(); | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + /** | ||
| 35 | + * 根据传入的build资料创建目录和文件 | ||
| 36 | + * @access public | ||
| 37 | + * @param array $build build列表 | ||
| 38 | + * @param string $namespace 应用类库命名空间 | ||
| 39 | + * @param bool $suffix 类库后缀 | ||
| 40 | + * @return void | ||
| 41 | + */ | ||
| 42 | + public function run(array $build = [], $namespace = 'app', $suffix = false) | ||
| 43 | + { | ||
| 44 | + // 锁定 | ||
| 45 | + $lockfile = $this->basePath . 'build.lock'; | ||
| 46 | + | ||
| 47 | + if (is_writable($lockfile)) { | ||
| 48 | + return; | ||
| 49 | + } elseif (!touch($lockfile)) { | ||
| 50 | + throw new Exception('应用目录[' . $this->basePath . ']不可写,目录无法自动生成!<BR>请手动生成项目目录~', 10006); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + foreach ($build as $module => $list) { | ||
| 54 | + if ('__dir__' == $module) { | ||
| 55 | + // 创建目录列表 | ||
| 56 | + $this->buildDir($list); | ||
| 57 | + } elseif ('__file__' == $module) { | ||
| 58 | + // 创建文件列表 | ||
| 59 | + $this->buildFile($list); | ||
| 60 | + } else { | ||
| 61 | + // 创建模块 | ||
| 62 | + $this->module($module, $list, $namespace, $suffix); | ||
| 63 | + } | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + // 解除锁定 | ||
| 67 | + unlink($lockfile); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + /** | ||
| 71 | + * 创建目录 | ||
| 72 | + * @access protected | ||
| 73 | + * @param array $list 目录列表 | ||
| 74 | + * @return void | ||
| 75 | + */ | ||
| 76 | + protected function buildDir($list) | ||
| 77 | + { | ||
| 78 | + foreach ($list as $dir) { | ||
| 79 | + $this->checkDirBuild($this->basePath . $dir); | ||
| 80 | + } | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + /** | ||
| 84 | + * 创建文件 | ||
| 85 | + * @access protected | ||
| 86 | + * @param array $list 文件列表 | ||
| 87 | + * @return void | ||
| 88 | + */ | ||
| 89 | + protected function buildFile($list) | ||
| 90 | + { | ||
| 91 | + foreach ($list as $file) { | ||
| 92 | + if (!is_dir($this->basePath . dirname($file))) { | ||
| 93 | + // 创建目录 | ||
| 94 | + mkdir($this->basePath . dirname($file), 0755, true); | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + if (!is_file($this->basePath . $file)) { | ||
| 98 | + file_put_contents($this->basePath . $file, 'php' == pathinfo($file, PATHINFO_EXTENSION) ? "<?php\n" : ''); | ||
| 99 | + } | ||
| 100 | + } | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + /** | ||
| 104 | + * 创建模块 | ||
| 105 | + * @access public | ||
| 106 | + * @param string $module 模块名 | ||
| 107 | + * @param array $list build列表 | ||
| 108 | + * @param string $namespace 应用类库命名空间 | ||
| 109 | + * @param bool $suffix 类库后缀 | ||
| 110 | + * @return void | ||
| 111 | + */ | ||
| 112 | + public function module($module = '', $list = [], $namespace = 'app', $suffix = false) | ||
| 113 | + { | ||
| 114 | + $module = $module ? $module : ''; | ||
| 115 | + | ||
| 116 | + if (!is_dir($this->basePath . $module)) { | ||
| 117 | + // 创建模块目录 | ||
| 118 | + mkdir($this->basePath . $module); | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + if (basename($this->app->getRuntimePath()) != $module) { | ||
| 122 | + // 创建配置文件和公共文件 | ||
| 123 | + $this->buildCommon($module); | ||
| 124 | + // 创建模块的默认页面 | ||
| 125 | + $this->buildHello($module, $namespace, $suffix); | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + if (empty($list)) { | ||
| 129 | + // 创建默认的模块目录和文件 | ||
| 130 | + $list = [ | ||
| 131 | + '__file__' => ['common.php'], | ||
| 132 | + '__dir__' => ['controller', 'model', 'view', 'config'], | ||
| 133 | + ]; | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + // 创建子目录和文件 | ||
| 137 | + foreach ($list as $path => $file) { | ||
| 138 | + $modulePath = $this->basePath . $module . DIRECTORY_SEPARATOR; | ||
| 139 | + if ('__dir__' == $path) { | ||
| 140 | + // 生成子目录 | ||
| 141 | + foreach ($file as $dir) { | ||
| 142 | + $this->checkDirBuild($modulePath . $dir); | ||
| 143 | + } | ||
| 144 | + } elseif ('__file__' == $path) { | ||
| 145 | + // 生成(空白)文件 | ||
| 146 | + foreach ($file as $name) { | ||
| 147 | + if (!is_file($modulePath . $name)) { | ||
| 148 | + file_put_contents($modulePath . $name, 'php' == pathinfo($name, PATHINFO_EXTENSION) ? "<?php\n" : ''); | ||
| 149 | + } | ||
| 150 | + } | ||
| 151 | + } else { | ||
| 152 | + // 生成相关MVC文件 | ||
| 153 | + foreach ($file as $val) { | ||
| 154 | + $val = trim($val); | ||
| 155 | + $filename = $modulePath . $path . DIRECTORY_SEPARATOR . $val . ($suffix ? ucfirst($path) : '') . '.php'; | ||
| 156 | + $space = $namespace . '\\' . ($module ? $module . '\\' : '') . $path; | ||
| 157 | + $class = $val . ($suffix ? ucfirst($path) : ''); | ||
| 158 | + switch ($path) { | ||
| 159 | + case 'controller': // 控制器 | ||
| 160 | + $content = "<?php\nnamespace {$space};\n\nclass {$class}\n{\n\n}"; | ||
| 161 | + break; | ||
| 162 | + case 'model': // 模型 | ||
| 163 | + $content = "<?php\nnamespace {$space};\n\nuse think\Model;\n\nclass {$class} extends Model\n{\n\n}"; | ||
| 164 | + break; | ||
| 165 | + case 'view': // 视图 | ||
| 166 | + $filename = $modulePath . $path . DIRECTORY_SEPARATOR . $val . '.html'; | ||
| 167 | + $this->checkDirBuild(dirname($filename)); | ||
| 168 | + $content = ''; | ||
| 169 | + break; | ||
| 170 | + default: | ||
| 171 | + // 其他文件 | ||
| 172 | + $content = "<?php\nnamespace {$space};\n\nclass {$class}\n{\n\n}"; | ||
| 173 | + } | ||
| 174 | + | ||
| 175 | + if (!is_file($filename)) { | ||
| 176 | + file_put_contents($filename, $content); | ||
| 177 | + } | ||
| 178 | + } | ||
| 179 | + } | ||
| 180 | + } | ||
| 181 | + } | ||
| 182 | + | ||
| 183 | + /** | ||
| 184 | + * 根据注释自动生成路由规则 | ||
| 185 | + * @access public | ||
| 186 | + * @param bool $suffix 类库后缀 | ||
| 187 | + * @param string $layer 控制器层目录名 | ||
| 188 | + * @return string | ||
| 189 | + */ | ||
| 190 | + public function buildRoute($suffix = false, $layer = '') | ||
| 191 | + { | ||
| 192 | + $namespace = $this->app->getNameSpace(); | ||
| 193 | + $modules = glob($this->basePath . '*', GLOB_ONLYDIR); | ||
| 194 | + $content = '<?php ' . PHP_EOL . '//根据 Annotation 自动生成的路由规则'; | ||
| 195 | + | ||
| 196 | + if (!$layer) { | ||
| 197 | + $layer = $this->app->config('app.url_controller_layer'); | ||
| 198 | + } | ||
| 199 | + | ||
| 200 | + foreach ($modules as $module) { | ||
| 201 | + $module = basename($module); | ||
| 202 | + | ||
| 203 | + if (in_array($module, $this->app->config('app.deny_module_list'))) { | ||
| 204 | + continue; | ||
| 205 | + } | ||
| 206 | + | ||
| 207 | + $path = $this->basePath . $module . DIRECTORY_SEPARATOR . $layer . DIRECTORY_SEPARATOR; | ||
| 208 | + $content .= $this->buildDirRoute($path, $namespace, $module, $suffix, $layer); | ||
| 209 | + } | ||
| 210 | + | ||
| 211 | + $filename = $this->app->getRuntimePath() . 'build_route.php'; | ||
| 212 | + file_put_contents($filename, $content); | ||
| 213 | + | ||
| 214 | + return $filename; | ||
| 215 | + } | ||
| 216 | + | ||
| 217 | + /** | ||
| 218 | + * 生成子目录控制器类的路由规则 | ||
| 219 | + * @access protected | ||
| 220 | + * @param string $path 控制器目录 | ||
| 221 | + * @param string $namespace 应用命名空间 | ||
| 222 | + * @param string $module 模块 | ||
| 223 | + * @param bool $suffix 类库后缀 | ||
| 224 | + * @param string $layer 控制器层目录名 | ||
| 225 | + * @return string | ||
| 226 | + */ | ||
| 227 | + protected function buildDirRoute($path, $namespace, $module, $suffix, $layer) | ||
| 228 | + { | ||
| 229 | + $content = ''; | ||
| 230 | + $controllers = glob($path . '*.php'); | ||
| 231 | + | ||
| 232 | + foreach ($controllers as $controller) { | ||
| 233 | + $controller = basename($controller, '.php'); | ||
| 234 | + | ||
| 235 | + $class = new \ReflectionClass($namespace . '\\' . $module . '\\' . $layer . '\\' . $controller); | ||
| 236 | + | ||
| 237 | + if ($suffix) { | ||
| 238 | + // 控制器后缀 | ||
| 239 | + $controller = substr($controller, 0, -10); | ||
| 240 | + } | ||
| 241 | + | ||
| 242 | + if (strpos($layer, '\\')) { | ||
| 243 | + // 多级控制器 | ||
| 244 | + $level = str_replace(DIRECTORY_SEPARATOR, '.', substr($layer, 11)); | ||
| 245 | + $controller = $level . '.' . $controller; | ||
| 246 | + } | ||
| 247 | + | ||
| 248 | + $content .= $this->getControllerRoute($class, $module, $controller); | ||
| 249 | + } | ||
| 250 | + | ||
| 251 | + $subDir = glob($path . '*', GLOB_ONLYDIR); | ||
| 252 | + | ||
| 253 | + foreach ($subDir as $dir) { | ||
| 254 | + $content .= $this->buildDirRoute($dir . DIRECTORY_SEPARATOR, $namespace, $module, $suffix, $layer . '\\' . basename($dir)); | ||
| 255 | + } | ||
| 256 | + | ||
| 257 | + return $content; | ||
| 258 | + } | ||
| 259 | + | ||
| 260 | + /** | ||
| 261 | + * 生成控制器类的路由规则 | ||
| 262 | + * @access protected | ||
| 263 | + * @param string $class 控制器完整类名 | ||
| 264 | + * @param string $module 模块名 | ||
| 265 | + * @param string $controller 控制器名 | ||
| 266 | + * @return string | ||
| 267 | + */ | ||
| 268 | + protected function getControllerRoute($class, $module, $controller) | ||
| 269 | + { | ||
| 270 | + $content = ''; | ||
| 271 | + $comment = $class->getDocComment(); | ||
| 272 | + | ||
| 273 | + if (false !== strpos($comment, '@route(')) { | ||
| 274 | + $comment = $this->parseRouteComment($comment); | ||
| 275 | + $route = $module . '/' . $controller; | ||
| 276 | + $comment = preg_replace('/route\(\s?([\'\"][\-\_\/\:\<\>\?\$\[\]\w]+[\'\"])\s?\)/is', 'Route::resource(\1,\'' . $route . '\')', $comment); | ||
| 277 | + $content .= PHP_EOL . $comment; | ||
| 278 | + } elseif (false !== strpos($comment, '@alias(')) { | ||
| 279 | + $comment = $this->parseRouteComment($comment, '@alias('); | ||
| 280 | + $route = $module . '/' . $controller; | ||
| 281 | + $comment = preg_replace('/alias\(\s?([\'\"][\-\_\/\w]+[\'\"])\s?\)/is', 'Route::alias(\1,\'' . $route . '\')', $comment); | ||
| 282 | + $content .= PHP_EOL . $comment; | ||
| 283 | + } | ||
| 284 | + | ||
| 285 | + $methods = $class->getMethods(\ReflectionMethod::IS_PUBLIC); | ||
| 286 | + | ||
| 287 | + foreach ($methods as $method) { | ||
| 288 | + $comment = $this->getMethodRouteComment($module, $controller, $method); | ||
| 289 | + if ($comment) { | ||
| 290 | + $content .= PHP_EOL . $comment; | ||
| 291 | + } | ||
| 292 | + } | ||
| 293 | + | ||
| 294 | + return $content; | ||
| 295 | + } | ||
| 296 | + | ||
| 297 | + /** | ||
| 298 | + * 解析路由注释 | ||
| 299 | + * @access protected | ||
| 300 | + * @param string $comment | ||
| 301 | + * @param string $tag | ||
| 302 | + * @return string | ||
| 303 | + */ | ||
| 304 | + protected function parseRouteComment($comment, $tag = '@route(') | ||
| 305 | + { | ||
| 306 | + $comment = substr($comment, 3, -2); | ||
| 307 | + $comment = explode(PHP_EOL, substr(strstr(trim($comment), $tag), 1)); | ||
| 308 | + $comment = array_map(function ($item) {return trim(trim($item), ' \t*');}, $comment); | ||
| 309 | + | ||
| 310 | + if (count($comment) > 1) { | ||
| 311 | + $key = array_search('', $comment); | ||
| 312 | + $comment = array_slice($comment, 0, false === $key ? 1 : $key); | ||
| 313 | + } | ||
| 314 | + | ||
| 315 | + $comment = implode(PHP_EOL . "\t", $comment) . ';'; | ||
| 316 | + | ||
| 317 | + if (strpos($comment, '{')) { | ||
| 318 | + $comment = preg_replace_callback('/\{\s?.*?\s?\}/s', function ($matches) { | ||
| 319 | + return false !== strpos($matches[0], '"') ? '[' . substr(var_export(json_decode($matches[0], true), true), 7, -1) . ']' : $matches[0]; | ||
| 320 | + }, $comment); | ||
| 321 | + } | ||
| 322 | + return $comment; | ||
| 323 | + } | ||
| 324 | + | ||
| 325 | + /** | ||
| 326 | + * 获取方法的路由注释 | ||
| 327 | + * @access protected | ||
| 328 | + * @param string $module 模块 | ||
| 329 | + * @param string $controller 控制器名 | ||
| 330 | + * @param \ReflectMethod $reflectMethod | ||
| 331 | + * @return string|void | ||
| 332 | + */ | ||
| 333 | + protected function getMethodRouteComment($module, $controller, $reflectMethod) | ||
| 334 | + { | ||
| 335 | + $comment = $reflectMethod->getDocComment(); | ||
| 336 | + | ||
| 337 | + if (false !== strpos($comment, '@route(')) { | ||
| 338 | + $comment = $this->parseRouteComment($comment); | ||
| 339 | + $action = $reflectMethod->getName(); | ||
| 340 | + | ||
| 341 | + if ($suffix = $this->app->config('app.action_suffix')) { | ||
| 342 | + $action = substr($action, 0, -strlen($suffix)); | ||
| 343 | + } | ||
| 344 | + | ||
| 345 | + $route = $module . '/' . $controller . '/' . $action; | ||
| 346 | + $comment = preg_replace('/route\s?\(\s?([\'\"][\-\_\/\:\<\>\?\$\[\]\w]+[\'\"])\s?\,?\s?[\'\"]?(\w+?)[\'\"]?\s?\)/is', 'Route::\2(\1,\'' . $route . '\')', $comment); | ||
| 347 | + $comment = preg_replace('/route\s?\(\s?([\'\"][\-\_\/\:\<\>\?\$\[\]\w]+[\'\"])\s?\)/is', 'Route::rule(\1,\'' . $route . '\')', $comment); | ||
| 348 | + | ||
| 349 | + return $comment; | ||
| 350 | + } | ||
| 351 | + } | ||
| 352 | + | ||
| 353 | + /** | ||
| 354 | + * 创建模块的欢迎页面 | ||
| 355 | + * @access protected | ||
| 356 | + * @param string $module 模块名 | ||
| 357 | + * @param string $namespace 应用类库命名空间 | ||
| 358 | + * @param bool $suffix 类库后缀 | ||
| 359 | + * @return void | ||
| 360 | + */ | ||
| 361 | + protected function buildHello($module, $namespace, $suffix = false) | ||
| 362 | + { | ||
| 363 | + $filename = $this->basePath . ($module ? $module . DIRECTORY_SEPARATOR : '') . 'controller' . DIRECTORY_SEPARATOR . 'Index' . ($suffix ? 'Controller' : '') . '.php'; | ||
| 364 | + if (!is_file($filename)) { | ||
| 365 | + $content = file_get_contents($this->app->getThinkPath() . 'tpl' . DIRECTORY_SEPARATOR . 'default_index.tpl'); | ||
| 366 | + $content = str_replace(['{$app}', '{$module}', '{layer}', '{$suffix}'], [$namespace, $module ? $module . '\\' : '', 'controller', $suffix ? 'Controller' : ''], $content); | ||
| 367 | + $this->checkDirBuild(dirname($filename)); | ||
| 368 | + | ||
| 369 | + file_put_contents($filename, $content); | ||
| 370 | + } | ||
| 371 | + } | ||
| 372 | + | ||
| 373 | + /** | ||
| 374 | + * 创建模块的公共文件 | ||
| 375 | + * @access protected | ||
| 376 | + * @param string $module 模块名 | ||
| 377 | + * @return void | ||
| 378 | + */ | ||
| 379 | + protected function buildCommon($module) | ||
| 380 | + { | ||
| 381 | + $filename = $this->app->getConfigPath() . ($module ? $module . DIRECTORY_SEPARATOR : '') . 'app.php'; | ||
| 382 | + $this->checkDirBuild(dirname($filename)); | ||
| 383 | + | ||
| 384 | + if (!is_file($filename)) { | ||
| 385 | + file_put_contents($filename, "<?php\n//配置文件\nreturn [\n\n];"); | ||
| 386 | + } | ||
| 387 | + | ||
| 388 | + $filename = $this->basePath . ($module ? $module . DIRECTORY_SEPARATOR : '') . 'common.php'; | ||
| 389 | + | ||
| 390 | + if (!is_file($filename)) { | ||
| 391 | + file_put_contents($filename, "<?php\n"); | ||
| 392 | + } | ||
| 393 | + } | ||
| 394 | + | ||
| 395 | + /** | ||
| 396 | + * 创建目录 | ||
| 397 | + * @access protected | ||
| 398 | + * @param string $dirname 目录名称 | ||
| 399 | + * @return void | ||
| 400 | + */ | ||
| 401 | + protected function checkDirBuild($dirname) | ||
| 402 | + { | ||
| 403 | + if (!is_dir($dirname)) { | ||
| 404 | + mkdir($dirname, 0755, true); | ||
| 405 | + } | ||
| 406 | + } | ||
| 407 | +} |
thinkphp/library/think/Cache.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// +---------------------------------------------------------------------- | ||
| 3 | +// | ThinkPHP [ WE CAN DO IT JUST THINK ] | ||
| 4 | +// +---------------------------------------------------------------------- | ||
| 5 | +// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved. | ||
| 6 | +// +---------------------------------------------------------------------- | ||
| 7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
| 8 | +// +---------------------------------------------------------------------- | ||
| 9 | +// | Author: liu21st <liu21st@gmail.com> | ||
| 10 | +// +---------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +namespace think; | ||
| 13 | + | ||
| 14 | +use think\cache\Driver; | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * Class Cache | ||
| 18 | + * | ||
| 19 | + * @package think | ||
| 20 | + * | ||
| 21 | + * @mixin Driver | ||
| 22 | + * @mixin \think\cache\driver\File | ||
| 23 | + */ | ||
| 24 | +class Cache | ||
| 25 | +{ | ||
| 26 | + /** | ||
| 27 | + * 缓存实例 | ||
| 28 | + * @var array | ||
| 29 | + */ | ||
| 30 | + protected $instance = []; | ||
| 31 | + | ||
| 32 | + /** | ||
| 33 | + * 缓存配置 | ||
| 34 | + * @var array | ||
| 35 | + */ | ||
| 36 | + protected $config = []; | ||
| 37 | + | ||
| 38 | + /** | ||
| 39 | + * 操作句柄 | ||
| 40 | + * @var object | ||
| 41 | + */ | ||
| 42 | + protected $handler; | ||
| 43 | + | ||
| 44 | + public function __construct(array $config = []) | ||
| 45 | + { | ||
| 46 | + $this->config = $config; | ||
| 47 | + $this->init($config); | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * 连接缓存 | ||
| 52 | + * @access public | ||
| 53 | + * @param array $options 配置数组 | ||
| 54 | + * @param bool|string $name 缓存连接标识 true 强制重新连接 | ||
| 55 | + * @return Driver | ||
| 56 | + */ | ||
| 57 | + public function connect(array $options = [], $name = false) | ||
| 58 | + { | ||
| 59 | + if (false === $name) { | ||
| 60 | + $name = md5(serialize($options)); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + if (true === $name || !isset($this->instance[$name])) { | ||
| 64 | + $type = !empty($options['type']) ? $options['type'] : 'File'; | ||
| 65 | + | ||
| 66 | + if (true === $name) { | ||
| 67 | + $name = md5(serialize($options)); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + $this->instance[$name] = Loader::factory($type, '\\think\\cache\\driver\\', $options); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + return $this->instance[$name]; | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + /** | ||
| 77 | + * 自动初始化缓存 | ||
| 78 | + * @access public | ||
| 79 | + * @param array $options 配置数组 | ||
| 80 | + * @param bool $force 强制更新 | ||
| 81 | + * @return Driver | ||
| 82 | + */ | ||
| 83 | + public function init(array $options = [], $force = false) | ||
| 84 | + { | ||
| 85 | + if (is_null($this->handler) || $force) { | ||
| 86 | + | ||
| 87 | + if ('complex' == $options['type']) { | ||
| 88 | + $default = $options['default']; | ||
| 89 | + $options = isset($options[$default['type']]) ? $options[$default['type']] : $default; | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + $this->handler = $this->connect($options); | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + return $this->handler; | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + public static function __make(Config $config) | ||
| 99 | + { | ||
| 100 | + return new static($config->pull('cache')); | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + public function getConfig() | ||
| 104 | + { | ||
| 105 | + return $this->config; | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + public function setConfig(array $config) | ||
| 109 | + { | ||
| 110 | + $this->config = array_merge($this->config, $config); | ||
| 111 | + } | ||
| 112 | + | ||
| 113 | + /** | ||
| 114 | + * 切换缓存类型 需要配置 cache.type 为 complex | ||
| 115 | + * @access public | ||
| 116 | + * @param string $name 缓存标识 | ||
| 117 | + * @return Driver | ||
| 118 | + */ | ||
| 119 | + public function store($name = '') | ||
| 120 | + { | ||
| 121 | + if ('' !== $name && 'complex' == $this->config['type']) { | ||
| 122 | + return $this->connect($this->config[$name], strtolower($name)); | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + return $this->init(); | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + public function __call($method, $args) | ||
| 129 | + { | ||
| 130 | + return call_user_func_array([$this->init(), $method], $args); | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | +} |
thinkphp/library/think/Collection.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// +---------------------------------------------------------------------- | ||
| 3 | +// | ThinkPHP [ WE CAN DO IT JUST THINK ] | ||
| 4 | +// +---------------------------------------------------------------------- | ||
| 5 | +// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved. | ||
| 6 | +// +---------------------------------------------------------------------- | ||
| 7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
| 8 | +// +---------------------------------------------------------------------- | ||
| 9 | +// | Author: zhangyajun <448901948@qq.com> | ||
| 10 | +// +---------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +namespace think; | ||
| 13 | + | ||
| 14 | +use ArrayAccess; | ||
| 15 | +use ArrayIterator; | ||
| 16 | +use Countable; | ||
| 17 | +use IteratorAggregate; | ||
| 18 | +use JsonSerializable; | ||
| 19 | + | ||
| 20 | +class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable | ||
| 21 | +{ | ||
| 22 | + /** | ||
| 23 | + * 数据集数据 | ||
| 24 | + * @var array | ||
| 25 | + */ | ||
| 26 | + protected $items = []; | ||
| 27 | + | ||
| 28 | + public function __construct($items = []) | ||
| 29 | + { | ||
| 30 | + $this->items = $this->convertToArray($items); | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + public static function make($items = []) | ||
| 34 | + { | ||
| 35 | + return new static($items); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + /** | ||
| 39 | + * 是否为空 | ||
| 40 | + * @access public | ||
| 41 | + * @return bool | ||
| 42 | + */ | ||
| 43 | + public function isEmpty() | ||
| 44 | + { | ||
| 45 | + return empty($this->items); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + public function toArray() | ||
| 49 | + { | ||
| 50 | + return array_map(function ($value) { | ||
| 51 | + return ($value instanceof Model || $value instanceof self) ? $value->toArray() : $value; | ||
| 52 | + }, $this->items); | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + public function all() | ||
| 56 | + { | ||
| 57 | + return $this->items; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + /** | ||
| 61 | + * 合并数组 | ||
| 62 | + * | ||
| 63 | + * @access public | ||
| 64 | + * @param mixed $items | ||
| 65 | + * @return static | ||
| 66 | + */ | ||
| 67 | + public function merge($items) | ||
| 68 | + { | ||
| 69 | + return new static(array_merge($this->items, $this->convertToArray($items))); | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + /** | ||
| 73 | + * 比较数组,返回差集 | ||
| 74 | + * | ||
| 75 | + * @access public | ||
| 76 | + * @param mixed $items | ||
| 77 | + * @return static | ||
| 78 | + */ | ||
| 79 | + public function diff($items) | ||
| 80 | + { | ||
| 81 | + return new static(array_diff($this->items, $this->convertToArray($items))); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + /** | ||
| 85 | + * 交换数组中的键和值 | ||
| 86 | + * | ||
| 87 | + * @access public | ||
| 88 | + * @return static | ||
| 89 | + */ | ||
| 90 | + public function flip() | ||
| 91 | + { | ||
| 92 | + return new static(array_flip($this->items)); | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + /** | ||
| 96 | + * 比较数组,返回交集 | ||
| 97 | + * | ||
| 98 | + * @access public | ||
| 99 | + * @param mixed $items | ||
| 100 | + * @return static | ||
| 101 | + */ | ||
| 102 | + public function intersect($items) | ||
| 103 | + { | ||
| 104 | + return new static(array_intersect($this->items, $this->convertToArray($items))); | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + /** | ||
| 108 | + * 返回数组中所有的键名 | ||
| 109 | + * | ||
| 110 | + * @access public | ||
| 111 | + * @return static | ||
| 112 | + */ | ||
| 113 | + public function keys() | ||
| 114 | + { | ||
| 115 | + return new static(array_keys($this->items)); | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + /** | ||
| 119 | + * 删除数组的最后一个元素(出栈) | ||
| 120 | + * | ||
| 121 | + * @access public | ||
| 122 | + * @return mixed | ||
| 123 | + */ | ||
| 124 | + public function pop() | ||
| 125 | + { | ||
| 126 | + return array_pop($this->items); | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | + /** | ||
| 130 | + * 通过使用用户自定义函数,以字符串返回数组 | ||
| 131 | + * | ||
| 132 | + * @access public | ||
| 133 | + * @param callable $callback | ||
| 134 | + * @param mixed $initial | ||
| 135 | + * @return mixed | ||
| 136 | + */ | ||
| 137 | + public function reduce(callable $callback, $initial = null) | ||
| 138 | + { | ||
| 139 | + return array_reduce($this->items, $callback, $initial); | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + /** | ||
| 143 | + * 以相反的顺序返回数组。 | ||
| 144 | + * | ||
| 145 | + * @access public | ||
| 146 | + * @return static | ||
| 147 | + */ | ||
| 148 | + public function reverse() | ||
| 149 | + { | ||
| 150 | + return new static(array_reverse($this->items)); | ||
| 151 | + } | ||
| 152 | + | ||
| 153 | + /** | ||
| 154 | + * 删除数组中首个元素,并返回被删除元素的值 | ||
| 155 | + * | ||
| 156 | + * @access public | ||
| 157 | + * @return mixed | ||
| 158 | + */ | ||
| 159 | + public function shift() | ||
| 160 | + { | ||
| 161 | + return array_shift($this->items); | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | + /** | ||
| 165 | + * 在数组结尾插入一个元素 | ||
| 166 | + * @access public | ||
| 167 | + * @param mixed $value | ||
| 168 | + * @param mixed $key | ||
| 169 | + * @return void | ||
| 170 | + */ | ||
| 171 | + public function push($value, $key = null) | ||
| 172 | + { | ||
| 173 | + if (is_null($key)) { | ||
| 174 | + $this->items[] = $value; | ||
| 175 | + } else { | ||
| 176 | + $this->items[$key] = $value; | ||
| 177 | + } | ||
| 178 | + } | ||
| 179 | + | ||
| 180 | + /** | ||
| 181 | + * 把一个数组分割为新的数组块. | ||
| 182 | + * | ||
| 183 | + * @access public | ||
| 184 | + * @param int $size | ||
| 185 | + * @param bool $preserveKeys | ||
| 186 | + * @return static | ||
| 187 | + */ | ||
| 188 | + public function chunk($size, $preserveKeys = false) | ||
| 189 | + { | ||
| 190 | + $chunks = []; | ||
| 191 | + | ||
| 192 | + foreach (array_chunk($this->items, $size, $preserveKeys) as $chunk) { | ||
| 193 | + $chunks[] = new static($chunk); | ||
| 194 | + } | ||
| 195 | + | ||
| 196 | + return new static($chunks); | ||
| 197 | + } | ||
| 198 | + | ||
| 199 | + /** | ||
| 200 | + * 在数组开头插入一个元素 | ||
| 201 | + * @access public | ||
| 202 | + * @param mixed $value | ||
| 203 | + * @param mixed $key | ||
| 204 | + * @return void | ||
| 205 | + */ | ||
| 206 | + public function unshift($value, $key = null) | ||
| 207 | + { | ||
| 208 | + if (is_null($key)) { | ||
| 209 | + array_unshift($this->items, $value); | ||
| 210 | + } else { | ||
| 211 | + $this->items = [$key => $value] + $this->items; | ||
| 212 | + } | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + /** | ||
| 216 | + * 给每个元素执行个回调 | ||
| 217 | + * | ||
| 218 | + * @access public | ||
| 219 | + * @param callable $callback | ||
| 220 | + * @return $this | ||
| 221 | + */ | ||
| 222 | + public function each(callable $callback) | ||
| 223 | + { | ||
| 224 | + foreach ($this->items as $key => $item) { | ||
| 225 | + $result = $callback($item, $key); | ||
| 226 | + | ||
| 227 | + if (false === $result) { | ||
| 228 | + break; | ||
| 229 | + } elseif (!is_object($item)) { | ||
| 230 | + $this->items[$key] = $result; | ||
| 231 | + } | ||
| 232 | + } | ||
| 233 | + | ||
| 234 | + return $this; | ||
| 235 | + } | ||
| 236 | + | ||
| 237 | + /** | ||
| 238 | + * 用回调函数过滤数组中的元素 | ||
| 239 | + * @access public | ||
| 240 | + * @param callable|null $callback | ||
| 241 | + * @return static | ||
| 242 | + */ | ||
| 243 | + public function filter(callable $callback = null) | ||
| 244 | + { | ||
| 245 | + if ($callback) { | ||
| 246 | + return new static(array_filter($this->items, $callback)); | ||
| 247 | + } | ||
| 248 | + | ||
| 249 | + return new static(array_filter($this->items)); | ||
| 250 | + } | ||
| 251 | + | ||
| 252 | + /** | ||
| 253 | + * 根据字段条件过滤数组中的元素 | ||
| 254 | + * @access public | ||
| 255 | + * @param string $field 字段名 | ||
| 256 | + * @param mixed $operator 操作符 | ||
| 257 | + * @param mixed $value 数据 | ||
| 258 | + * @return static | ||
| 259 | + */ | ||
| 260 | + public function where($field, $operator, $value = null) | ||
| 261 | + { | ||
| 262 | + if (is_null($value)) { | ||
| 263 | + $value = $operator; | ||
| 264 | + $operator = '='; | ||
| 265 | + } | ||
| 266 | + | ||
| 267 | + return $this->filter(function ($data) use ($field, $operator, $value) { | ||
| 268 | + if (strpos($field, '.')) { | ||
| 269 | + list($field, $relation) = explode('.', $field); | ||
| 270 | + | ||
| 271 | + $result = isset($data[$field][$relation]) ? $data[$field][$relation] : null; | ||
| 272 | + } else { | ||
| 273 | + $result = isset($data[$field]) ? $data[$field] : null; | ||
| 274 | + } | ||
| 275 | + | ||
| 276 | + switch ($operator) { | ||
| 277 | + case '===': | ||
| 278 | + return $result === $value; | ||
| 279 | + case '!==': | ||
| 280 | + return $result !== $value; | ||
| 281 | + case '!=': | ||
| 282 | + case '<>': | ||
| 283 | + return $result != $value; | ||
| 284 | + case '>': | ||
| 285 | + return $result > $value; | ||
| 286 | + case '>=': | ||
| 287 | + return $result >= $value; | ||
| 288 | + case '<': | ||
| 289 | + return $result < $value; | ||
| 290 | + case '<=': | ||
| 291 | + return $result <= $value; | ||
| 292 | + case 'like': | ||
| 293 | + return is_string($result) && false !== strpos($result, $value); | ||
| 294 | + case 'not like': | ||
| 295 | + return is_string($result) && false === strpos($result, $value); | ||
| 296 | + case 'in': | ||
| 297 | + return is_scalar($result) && in_array($result, $value, true); | ||
| 298 | + case 'not in': | ||
| 299 | + return is_scalar($result) && !in_array($result, $value, true); | ||
| 300 | + case 'between': | ||
| 301 | + list($min, $max) = is_string($value) ? explode(',', $value) : $value; | ||
| 302 | + return is_scalar($result) && $result >= $min && $result <= $max; | ||
| 303 | + case 'not between': | ||
| 304 | + list($min, $max) = is_string($value) ? explode(',', $value) : $value; | ||
| 305 | + return is_scalar($result) && $result > $max || $result < $min; | ||
| 306 | + case '==': | ||
| 307 | + case '=': | ||
| 308 | + default: | ||
| 309 | + return $result == $value; | ||
| 310 | + } | ||
| 311 | + }); | ||
| 312 | + } | ||
| 313 | + | ||
| 314 | + /** | ||
| 315 | + * 返回数据中指定的一列 | ||
| 316 | + * @access public | ||
| 317 | + * @param mixed $columnKey 键名 | ||
| 318 | + * @param mixed $indexKey 作为索引值的列 | ||
| 319 | + * @return array | ||
| 320 | + */ | ||
| 321 | + public function column($columnKey, $indexKey = null) | ||
| 322 | + { | ||
| 323 | + return array_column($this->items, $columnKey, $indexKey); | ||
| 324 | + } | ||
| 325 | + | ||
| 326 | + /** | ||
| 327 | + * 对数组排序 | ||
| 328 | + * | ||
| 329 | + * @access public | ||
| 330 | + * @param callable|null $callback | ||
| 331 | + * @return static | ||
| 332 | + */ | ||
| 333 | + public function sort(callable $callback = null) | ||
| 334 | + { | ||
| 335 | + $items = $this->items; | ||
| 336 | + | ||
| 337 | + $callback = $callback ?: function ($a, $b) { | ||
| 338 | + return $a == $b ? 0 : (($a < $b) ? -1 : 1); | ||
| 339 | + | ||
| 340 | + }; | ||
| 341 | + | ||
| 342 | + uasort($items, $callback); | ||
| 343 | + | ||
| 344 | + return new static($items); | ||
| 345 | + } | ||
| 346 | + | ||
| 347 | + /** | ||
| 348 | + * 将数组打乱 | ||
| 349 | + * | ||
| 350 | + * @access public | ||
| 351 | + * @return static | ||
| 352 | + */ | ||
| 353 | + public function shuffle() | ||
| 354 | + { | ||
| 355 | + $items = $this->items; | ||
| 356 | + | ||
| 357 | + shuffle($items); | ||
| 358 | + | ||
| 359 | + return new static($items); | ||
| 360 | + } | ||
| 361 | + | ||
| 362 | + /** | ||
| 363 | + * 截取数组 | ||
| 364 | + * | ||
| 365 | + * @access public | ||
| 366 | + * @param int $offset | ||
| 367 | + * @param int $length | ||
| 368 | + * @param bool $preserveKeys | ||
| 369 | + * @return static | ||
| 370 | + */ | ||
| 371 | + public function slice($offset, $length = null, $preserveKeys = false) | ||
| 372 | + { | ||
| 373 | + return new static(array_slice($this->items, $offset, $length, $preserveKeys)); | ||
| 374 | + } | ||
| 375 | + | ||
| 376 | + // ArrayAccess | ||
| 377 | + public function offsetExists($offset) | ||
| 378 | + { | ||
| 379 | + return array_key_exists($offset, $this->items); | ||
| 380 | + } | ||
| 381 | + | ||
| 382 | + public function offsetGet($offset) | ||
| 383 | + { | ||
| 384 | + return $this->items[$offset]; | ||
| 385 | + } | ||
| 386 | + | ||
| 387 | + public function offsetSet($offset, $value) | ||
| 388 | + { | ||
| 389 | + if (is_null($offset)) { | ||
| 390 | + $this->items[] = $value; | ||
| 391 | + } else { | ||
| 392 | + $this->items[$offset] = $value; | ||
| 393 | + } | ||
| 394 | + } | ||
| 395 | + | ||
| 396 | + public function offsetUnset($offset) | ||
| 397 | + { | ||
| 398 | + unset($this->items[$offset]); | ||
| 399 | + } | ||
| 400 | + | ||
| 401 | + //Countable | ||
| 402 | + public function count() | ||
| 403 | + { | ||
| 404 | + return count($this->items); | ||
| 405 | + } | ||
| 406 | + | ||
| 407 | + //IteratorAggregate | ||
| 408 | + public function getIterator() | ||
| 409 | + { | ||
| 410 | + return new ArrayIterator($this->items); | ||
| 411 | + } | ||
| 412 | + | ||
| 413 | + //JsonSerializable | ||
| 414 | + public function jsonSerialize() | ||
| 415 | + { | ||
| 416 | + return $this->toArray(); | ||
| 417 | + } | ||
| 418 | + | ||
| 419 | + /** | ||
| 420 | + * 转换当前数据集为JSON字符串 | ||
| 421 | + * @access public | ||
| 422 | + * @param integer $options json参数 | ||
| 423 | + * @return string | ||
| 424 | + */ | ||
| 425 | + public function toJson($options = JSON_UNESCAPED_UNICODE) | ||
| 426 | + { | ||
| 427 | + return json_encode($this->toArray(), $options); | ||
| 428 | + } | ||
| 429 | + | ||
| 430 | + public function __toString() | ||
| 431 | + { | ||
| 432 | + return $this->toJson(); | ||
| 433 | + } | ||
| 434 | + | ||
| 435 | + /** | ||
| 436 | + * 转换成数组 | ||
| 437 | + * | ||
| 438 | + * @access public | ||
| 439 | + * @param mixed $items | ||
| 440 | + * @return array | ||
| 441 | + */ | ||
| 442 | + protected function convertToArray($items) | ||
| 443 | + { | ||
| 444 | + if ($items instanceof self) { | ||
| 445 | + return $items->all(); | ||
| 446 | + } | ||
| 447 | + | ||
| 448 | + return (array) $items; | ||
| 449 | + } | ||
| 450 | +} |
thinkphp/library/think/Compression.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// +---------------------------------------------------------------------- | ||
| 3 | +// | ThinkPHP [ WE CAN DO IT JUST THINK ] | ||
| 4 | +// +---------------------------------------------------------------------- | ||
| 5 | +// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved. | ||
| 6 | +// +---------------------------------------------------------------------- | ||
| 7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
| 8 | +// +---------------------------------------------------------------------- | ||
| 9 | +// | Author: liu21st <liu21st@gmail.com> | ||
| 10 | +// +---------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +namespace think; | ||
| 13 | +/** | ||
| 14 | + 图片压缩操作类 | ||
| 15 | + v1.0 | ||
| 16 | +*/ | ||
| 17 | +class Compression | ||
| 18 | +{ | ||
| 19 | + private $src; | ||
| 20 | + public $percent = 0.1; | ||
| 21 | + public function __construct($src){ | ||
| 22 | + | ||
| 23 | + $this->src = $src; | ||
| 24 | + | ||
| 25 | + } | ||
| 26 | + /** | ||
| 27 | + * 图片压缩处理 | ||
| 28 | + * @param string $sFile 图片路径 | ||
| 29 | + * @param int $iWidth 自定义图片宽度 | ||
| 30 | + * @param int $iHeight 自定义图片高度 | ||
| 31 | + */ | ||
| 32 | + function getThumb(){ | ||
| 33 | + $iWidth = 375; | ||
| 34 | + $iHeight = 240; | ||
| 35 | + $sFile = $this->src; | ||
| 36 | + //判断该图片是否存在 | ||
| 37 | + if(!file_exists($sFile)) return $sFile; | ||
| 38 | + //判断图片格式 | ||
| 39 | + $attach_fileext = $this->get_filetype($sFile); | ||
| 40 | + if (!in_array($attach_fileext, array('jpg','png','jpeg'))){ | ||
| 41 | + return $sFile; | ||
| 42 | + } | ||
| 43 | + //压缩图片 | ||
| 44 | + $sFileNameS = str_replace(".".$attach_fileext, "_".$iWidth.'_'.$iHeight.'.'.$attach_fileext, $sFile); | ||
| 45 | + //判断是否已压缩图片,若是则返回压缩图片路径 | ||
| 46 | + if(file_exists($sFileNameS)){ | ||
| 47 | + return $sFileNameS; | ||
| 48 | + } | ||
| 49 | + //解决手机端上传图片被旋转问题 | ||
| 50 | + /*if (in_array($attach_fileext, array('jpeg')) ){ | ||
| 51 | + $this->adjustPicOrientation($sFile); | ||
| 52 | + }*/ | ||
| 53 | + //生成压缩图片,并存储到原图同路径下 | ||
| 54 | + $this->resizeImage($sFile, $sFileNameS, $iWidth, $iHeight); | ||
| 55 | + if(!file_exists($sFileNameS)){ | ||
| 56 | + return $sFile; | ||
| 57 | + } | ||
| 58 | + return $sFileNameS; | ||
| 59 | + } | ||
| 60 | + /** | ||
| 61 | + *获取文件后缀名 | ||
| 62 | + */ | ||
| 63 | + function get_filetype($filename) { | ||
| 64 | + $extend = explode("." , $filename); | ||
| 65 | + return strtolower($extend[count($extend) - 1]); | ||
| 66 | + } | ||
| 67 | + /** | ||
| 68 | + * 生成图片 | ||
| 69 | + * @param string $im 源图片路径 | ||
| 70 | + * @param string $dest 目标图片路径 | ||
| 71 | + * @param int $maxwidth 生成图片宽 | ||
| 72 | + * @param int $maxheight 生成图片高 | ||
| 73 | + */ | ||
| 74 | + function resizeImage($im, $dest, $maxwidth, $maxheight) { | ||
| 75 | + $img = getimagesize($im); | ||
| 76 | + switch ($img[2]) { | ||
| 77 | + case 1: | ||
| 78 | + $im = @imagecreatefromgif($im); | ||
| 79 | + break; | ||
| 80 | + case 2: | ||
| 81 | + $im = @imagecreatefromjpeg($im); | ||
| 82 | + break; | ||
| 83 | + case 3: | ||
| 84 | + $im = @imagecreatefrompng($im); | ||
| 85 | + break; | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + $pic_width = imagesx($im); | ||
| 89 | + $pic_height = imagesy($im); | ||
| 90 | + $resizewidth_tag = false; | ||
| 91 | + $resizeheight_tag = false; | ||
| 92 | + if (($maxwidth && $pic_width > $maxwidth) || ($maxheight && $pic_height > $maxheight)) { | ||
| 93 | + if ($maxwidth && $pic_width > $maxwidth) { | ||
| 94 | + $widthratio = $maxwidth / $pic_width; | ||
| 95 | + $resizewidth_tag = true; | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + if ($maxheight && $pic_height > $maxheight) { | ||
| 99 | + $heightratio = $maxheight / $pic_height; | ||
| 100 | + $resizeheight_tag = true; | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + if ($resizewidth_tag && $resizeheight_tag) { | ||
| 104 | + if ($widthratio < $heightratio) | ||
| 105 | + $ratio = $widthratio; | ||
| 106 | + else | ||
| 107 | + $ratio = $heightratio; | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + | ||
| 111 | + if ($resizewidth_tag && !$resizeheight_tag) | ||
| 112 | + $ratio = $widthratio; | ||
| 113 | + if ($resizeheight_tag && !$resizewidth_tag) | ||
| 114 | + $ratio = $heightratio; | ||
| 115 | + $newwidth = $pic_width * $ratio; | ||
| 116 | + $newheight = $pic_height * $ratio; | ||
| 117 | + | ||
| 118 | + if (function_exists("imagecopyresampled")) { | ||
| 119 | + $newim = imagecreatetruecolor($newwidth, $newheight); | ||
| 120 | + imagecopyresampled($newim, $im, 0, 0, 0, 0, $newwidth, $newheight, $pic_width, $pic_height); | ||
| 121 | + } else { | ||
| 122 | + $newim = imagecreate($newwidth, $newheight); | ||
| 123 | + imagecopyresized($newim, $im, 0, 0, 0, 0, $newwidth, $newheight, $pic_width, $pic_height); | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + imagejpeg($newim, $dest); | ||
| 127 | + imagedestroy($newim); | ||
| 128 | + } else { | ||
| 129 | + imagejpeg($im, $dest); | ||
| 130 | + } | ||
| 131 | + } | ||
| 132 | + /** | ||
| 133 | + * 解决手机上传图片被旋转问题 | ||
| 134 | + * @param string $full_filename 文件路径 | ||
| 135 | + */ | ||
| 136 | + function adjustPicOrientation($full_filename){ | ||
| 137 | + $exif = exif_read_data($full_filename); | ||
| 138 | + if($exif && isset($exif['Orientation'])) { | ||
| 139 | + $orientation = $exif['Orientation']; | ||
| 140 | + if($orientation != 1){ | ||
| 141 | + $img = imagecreatefromjpeg($full_filename); | ||
| 142 | + | ||
| 143 | + $mirror = false; | ||
| 144 | + $deg = 0; | ||
| 145 | + | ||
| 146 | + switch ($orientation) { | ||
| 147 | + case 2: | ||
| 148 | + $mirror = true; | ||
| 149 | + break; | ||
| 150 | + case 3: | ||
| 151 | + $deg = 180; | ||
| 152 | + break; | ||
| 153 | + case 4: | ||
| 154 | + $deg = 180; | ||
| 155 | + $mirror = true; | ||
| 156 | + break; | ||
| 157 | + case 5: | ||
| 158 | + $deg = 270; | ||
| 159 | + $mirror = true; | ||
| 160 | + break; | ||
| 161 | + case 6: | ||
| 162 | + $deg = 270; | ||
| 163 | + break; | ||
| 164 | + case 7: | ||
| 165 | + $deg = 90; | ||
| 166 | + $mirror = true; | ||
| 167 | + break; | ||
| 168 | + case 8: | ||
| 169 | + $deg = 90; | ||
| 170 | + break; | ||
| 171 | + } | ||
| 172 | + if ($deg) $img = imagerotate($img, $deg, 0); | ||
| 173 | + if ($mirror) $img = _mirrorImage($img); | ||
| 174 | + //$full_filename = str_replace('.jpg', "-O$orientation.jpg", $full_filename);新文件名 | ||
| 175 | + imagejpeg($img, $full_filename, 95); | ||
| 176 | + } | ||
| 177 | + } | ||
| 178 | + return $full_filename; | ||
| 179 | + } | ||
| 180 | +} |
thinkphp/library/think/Config.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// +---------------------------------------------------------------------- | ||
| 3 | +// | ThinkPHP [ WE CAN DO IT JUST THINK ] | ||
| 4 | +// +---------------------------------------------------------------------- | ||
| 5 | +// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved. | ||
| 6 | +// +---------------------------------------------------------------------- | ||
| 7 | +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) | ||
| 8 | +// +---------------------------------------------------------------------- | ||
| 9 | +// | Author: liu21st <liu21st@gmail.com> | ||
| 10 | +// +---------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +namespace think; | ||
| 13 | + | ||
| 14 | +use Yaconf; | ||
| 15 | + | ||
| 16 | +class Config implements \ArrayAccess | ||
| 17 | +{ | ||
| 18 | + /** | ||
| 19 | + * 配置参数 | ||
| 20 | + * @var array | ||
| 21 | + */ | ||
| 22 | + protected $config = []; | ||
| 23 | + | ||
| 24 | + /** | ||
| 25 | + * 配置前缀 | ||
| 26 | + * @var string | ||
| 27 | + */ | ||
| 28 | + protected $prefix = 'app'; | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 配置文件目录 | ||
| 32 | + * @var string | ||
| 33 | + */ | ||
| 34 | + protected $path; | ||
| 35 | + | ||
| 36 | + /** | ||
| 37 | + * 配置文件后缀 | ||
| 38 | + * @var string | ||
| 39 | + */ | ||
| 40 | + protected $ext; | ||
| 41 | + | ||
| 42 | + /** | ||
| 43 | + * 是否支持Yaconf | ||
| 44 | + * @var bool | ||
| 45 | + */ | ||
| 46 | + protected $yaconf; | ||
| 47 | + | ||
| 48 | + /** | ||
| 49 | + * 构造方法 | ||
| 50 | + * @access public | ||
| 51 | + */ | ||
| 52 | + public function __construct($path = '', $ext = '.php') | ||
| 53 | + { | ||
| 54 | + $this->path = $path; | ||
| 55 | + $this->ext = $ext; | ||
| 56 | + $this->yaconf = class_exists('Yaconf'); | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + public static function __make(App $app) | ||
| 60 | + { | ||
| 61 | + $path = $app->getConfigPath(); | ||
| 62 | + $ext = $app->getConfigExt(); | ||
| 63 | + return new static($path, $ext); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + /** | ||
| 67 | + * 设置开启Yaconf | ||
| 68 | + * @access public | ||
| 69 | + * @param bool $yaconf 是否使用Yaconf | ||
| 70 | + * @return void | ||
| 71 | + */ | ||
| 72 | + public function useYaconf($yaconf) | ||
| 73 | + { | ||
| 74 | + $this->yaconf = $yaconf; | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + /** | ||
| 78 | + * 设置配置参数默认前缀 | ||
| 79 | + * @access public | ||
| 80 | + * @param string $prefix 前缀 | ||
| 81 | + * @return void | ||
| 82 | + */ | ||
| 83 | + public function setDefaultPrefix($prefix) | ||
| 84 | + { | ||
| 85 | + $this->prefix = $prefix; | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + /** | ||
| 89 | + * 解析配置文件或内容 | ||
| 90 | + * @access public | ||
| 91 | + * @param string $config 配置文件路径或内容 | ||
| 92 | + * @param string $type 配置解析类型 | ||
| 93 | + * @param string $name 配置名(如设置即表示二级配置) | ||
| 94 | + * @return mixed | ||
| 95 | + */ | ||
| 96 | + public function parse($config, $type = '', $name = '') | ||
| 97 | + { | ||
| 98 | + if (empty($type)) { | ||
| 99 | + $type = pathinfo($config, PATHINFO_EXTENSION); | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + $object = Loader::factory($type, '\\think\\config\\driver\\', $config); | ||
| 103 | + | ||
| 104 | + return $this->set($object->parse(), $name); | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + /** | ||
| 108 | + * 加载配置文件(多种格式) | ||
| 109 | + * @access public | ||
| 110 | + * @param string $file 配置文件名 | ||
| 111 | + * @param string $name 一级配置名 | ||
| 112 | + * @return mixed | ||
| 113 | + */ | ||
| 114 | + public function load($file, $name = '') | ||
| 115 | + { | ||
| 116 | + if (is_file($file)) { | ||
| 117 | + $filename = $file; | ||
| 118 | + } elseif (is_file($this->path . $file . $this->ext)) { | ||
| 119 | + $filename = $this->path . $file . $this->ext; | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + if (isset($filename)) { | ||
| 123 | + return $this->loadFile($filename, $name); | ||
| 124 | + } elseif ($this->yaconf && Yaconf::has($file)) { | ||
| 125 | + return $this->set(Yaconf::get($file), $name); | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + return $this->config; | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + protected function loadFile($file, $name) | ||
| 132 | + { | ||
| 133 | + $name = strtolower($name); | ||
| 134 | + $type = pathinfo($file, PATHINFO_EXTENSION); | ||
| 135 | + | ||
| 136 | + if ('php' == $type) { | ||
| 137 | + return $this->set(include $file, $name); | ||
| 138 | + } elseif ('yaml' == $type && function_exists('yaml_parse_file')) { | ||
| 139 | + return $this->set(yaml_parse_file($file), $name); | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + return $this->parse($file, $type, $name); | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + /** | ||
| 146 | + * 检测配置是否存在 | ||
| 147 | + * @access public | ||
| 148 | + * @param string $name 配置参数名(支持多级配置 .号分割) | ||
| 149 | + * @return bool | ||
| 150 | + */ | ||
| 151 | + public function has($name) | ||
| 152 | + { | ||
| 153 | + if (!strpos($name, '.')) { | ||
| 154 | + $name = $this->prefix . '.' . $name; | ||
| 155 | + } | ||
| 156 | + | ||
| 157 | + return !is_null($this->get($name)); | ||
| 158 | + } | ||
| 159 | + | ||
| 160 | + /** | ||
| 161 | + * 获取一级配置 | ||
| 162 | + * @access public | ||
| 163 | + * @param string $name 一级配置名 | ||
| 164 | + * @return array | ||
| 165 | + */ | ||
| 166 | + public function pull($name) | ||
| 167 | + { | ||
| 168 | + $name = strtolower($name); | ||
| 169 | + | ||
| 170 | + if ($this->yaconf && Yaconf::has($name)) { | ||
| 171 | + $config = Yaconf::get($name); | ||
| 172 | + return isset($this->config[$name]) ? array_merge($this->config[$name], $config) : $config; | ||
| 173 | + } | ||
| 174 | + | ||
| 175 | + return isset($this->config[$name]) ? $this->config[$name] : []; | ||
| 176 | + } | ||
| 177 | + | ||
| 178 | + /** | ||
| 179 | + * 获取配置参数 为空则获取所有配置 | ||
| 180 | + * @access public | ||
| 181 | + * @param string $name 配置参数名(支持多级配置 .号分割) | ||
| 182 | + * @param mixed $default 默认值 | ||
| 183 | + * @return mixed | ||
| 184 | + */ | ||
| 185 | + public function get($name = null, $default = null) | ||
| 186 | + { | ||
| 187 | + if ($name && !strpos($name, '.')) { | ||
| 188 | + $name = $this->prefix . '.' . $name; | ||
| 189 | + } | ||
| 190 | + | ||
| 191 | + // 无参数时获取所有 | ||
| 192 | + if (empty($name)) { | ||
| 193 | + return $this->config; | ||
| 194 | + } | ||
| 195 | + | ||
| 196 | + if ('.' == substr($name, -1)) { | ||
| 197 | + return $this->pull(substr($name, 0, -1)); | ||
| 198 | + } | ||
| 199 | + | ||
| 200 | + if ($this->yaconf && Yaconf::has($name)) { | ||
| 201 | + return Yaconf::get($name); | ||
| 202 | + } | ||
| 203 | + | ||
| 204 | + $name = explode('.', $name); | ||
| 205 | + $name[0] = strtolower($name[0]); | ||
| 206 | + $config = $this->config; | ||
| 207 | + | ||
| 208 | + // 按.拆分成多维数组进行判断 | ||
| 209 | + foreach ($name as $val) { | ||
| 210 | + if (isset($config[$val])) { | ||
| 211 | + $config = $config[$val]; | ||
| 212 | + } else { | ||
| 213 | + return $default; | ||
| 214 | + } | ||
| 215 | + } | ||
| 216 | + | ||
| 217 | + return $config; | ||
| 218 | + } | ||
| 219 | + | ||
| 220 | + /** | ||
| 221 | + * 设置配置参数 name为数组则为批量设置 | ||
| 222 | + * @access public | ||
| 223 | + * @param string|array $name 配置参数名(支持三级配置 .号分割) | ||
| 224 | + * @param mixed $value 配置值 | ||
| 225 | + * @return mixed | ||
| 226 | + */ | ||
| 227 | + public function set($name, $value = null) | ||
| 228 | + { | ||
| 229 | + if (is_string($name)) { | ||
| 230 | + if (!strpos($name, '.')) { | ||
| 231 | + $name = $this->prefix . '.' . $name; | ||
| 232 | + } | ||
| 233 | + | ||
| 234 | + $name = explode('.', $name, 3); | ||
| 235 | + | ||
| 236 | + if (count($name) == 2) { | ||
| 237 | + $this->config[strtolower($name[0])][$name[1]] = $value; | ||
| 238 | + } else { | ||
| 239 | + $this->config[strtolower($name[0])][$name[1]][$name[2]] = $value; | ||
| 240 | + } | ||
| 241 | + | ||
| 242 | + return $value; | ||
| 243 | + } elseif (is_array($name)) { | ||
| 244 | + // 批量设置 | ||
| 245 | + if (!empty($value)) { | ||
| 246 | + if (isset($this->config[$value])) { | ||
| 247 | + $result = array_merge($this->config[$value], $name); | ||
| 248 | + } else { | ||
| 249 | + $result = $name; | ||
| 250 | + } | ||
| 251 | + | ||
| 252 | + $this->config[$value] = $result; | ||
| 253 | + } else { | ||
| 254 | + $result = $this->config = array_merge($this->config, $name); | ||
| 255 | + } | ||
| 256 | + } else { | ||
| 257 | + // 为空直接返回 已有配置 | ||
| 258 | + $result = $this->config; | ||
| 259 | + } | ||
| 260 | + | ||
| 261 | + return $result; | ||
| 262 | + } | ||
| 263 | + | ||
| 264 | + /** | ||
| 265 | + * 移除配置 | ||
| 266 | + * @access public | ||
| 267 | + * @param string $name 配置参数名(支持三级配置 .号分割) | ||
| 268 | + * @return void | ||
| 269 | + */ | ||
| 270 | + public function remove($name) | ||
| 271 | + { | ||
| 272 | + if (!strpos($name, '.')) { | ||
| 273 | + $name = $this->prefix . '.' . $name; | ||
| 274 | + } | ||
| 275 | + | ||
| 276 | + $name = explode('.', $name, 3); | ||
| 277 | + | ||
| 278 | + if (count($name) == 2) { | ||
| 279 | + unset($this->config[strtolower($name[0])][$name[1]]); | ||
| 280 | + } else { | ||
| 281 | + unset($this->config[strtolower($name[0])][$name[1]][$name[2]]); | ||
| 282 | + } | ||
| 283 | + } | ||
| 284 | + | ||
| 285 | + /** | ||
| 286 | + * 重置配置参数 | ||
| 287 | + * @access public | ||
| 288 | + * @param string $prefix 配置前缀名 | ||
| 289 | + * @return void | ||
| 290 | + */ | ||
| 291 | + public function reset($prefix = '') | ||
| 292 | + { | ||
| 293 | + if ('' === $prefix) { | ||
| 294 | + $this->config = []; | ||
| 295 | + } else { | ||
| 296 | + $this->config[$prefix] = []; | ||
| 297 | + } | ||
| 298 | + } | ||
| 299 | + | ||
| 300 | + /** | ||
| 301 | + * 设置配置 | ||
| 302 | + * @access public | ||
| 303 | + * @param string $name 参数名 | ||
| 304 | + * @param mixed $value 值 | ||
| 305 | + */ | ||
| 306 | + public function __set($name, $value) | ||
| 307 | + { | ||
| 308 | + return $this->set($name, $value); | ||
| 309 | + } | ||
| 310 | + | ||
| 311 | + /** | ||
| 312 | + * 获取配置参数 | ||
| 313 | + * @access public | ||
| 314 | + * @param string $name 参数名 | ||
| 315 | + * @return mixed | ||
| 316 | + */ | ||
| 317 | + public function __get($name) | ||
| 318 | + { | ||
| 319 | + return $this->get($name); | ||
| 320 | + } | ||
| 321 | + | ||
| 322 | + /** | ||
| 323 | + * 检测是否存在参数 | ||
| 324 | + * @access public | ||
| 325 | + * @param string $name 参数名 | ||
| 326 | + * @return bool | ||
| 327 | + */ | ||
| 328 | + public function __isset($name) | ||
| 329 | + { | ||
| 330 | + return $this->has($name); | ||
| 331 | + } | ||
| 332 | + | ||
| 333 | + // ArrayAccess | ||
| 334 | + public function offsetSet($name, $value) | ||
| 335 | + { | ||
| 336 | + $this->set($name, $value); | ||
| 337 | + } | ||
| 338 | + | ||
| 339 | + public function offsetExists($name) | ||
| 340 | + { | ||
| 341 | + return $this->has($name); | ||
| 342 | + } | ||
| 343 | + | ||
| 344 | + public function offsetUnset($name) | ||
| 345 | + { | ||
| 346 | + $this->remove($name); | ||
| 347 | + } | ||
| 348 | + | ||
| 349 | + public function offsetGet($name) | ||
| 350 | + { | ||
| 351 | + return $this->get($name); | ||
| 352 | + } | ||
| 353 | +} |
thinkphp/library/think/Console.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// +---------------------------------------------------------------------- | ||
| 3 | +// | TopThink [ WE CAN DO IT JUST THINK IT ] | ||
| 4 | +// +---------------------------------------------------------------------- | ||
| 5 | +// | Copyright (c) 2015 http://www.topthink.com All rights reserved. | ||
| 6 | +// +---------------------------------------------------------------------- | ||
| 7 | +// | Author: zhangyajun <448901948@qq.com> | ||
| 8 | +// +---------------------------------------------------------------------- | ||
| 9 | + | ||
| 10 | +namespace think; | ||
| 11 | + | ||
| 12 | +use think\console\Command; | ||
| 13 | +use think\console\command\Help as HelpCommand; | ||
| 14 | +use think\console\Input; | ||
| 15 | +use think\console\input\Argument as InputArgument; | ||
| 16 | +use think\console\input\Definition as InputDefinition; | ||
| 17 | +use think\console\input\Option as InputOption; | ||
| 18 | +use think\console\Output; | ||
| 19 | +use think\console\output\driver\Buffer; | ||
| 20 | + | ||
| 21 | +class Console | ||
| 22 | +{ | ||
| 23 | + | ||
| 24 | + private $name; | ||
| 25 | + private $version; | ||
| 26 | + | ||
| 27 | + /** @var Command[] */ | ||
| 28 | + private $commands = []; | ||
| 29 | + | ||
| 30 | + private $wantHelps = false; | ||
| 31 | + | ||
| 32 | + private $catchExceptions = true; | ||
| 33 | + private $autoExit = true; | ||
| 34 | + private $definition; | ||
| 35 | + private $defaultCommand; | ||
| 36 | + | ||
| 37 | + private static $defaultCommands = [ | ||
| 38 | + "think\\console\\command\\Help", | ||
| 39 | + "think\\console\\command\\Lists", | ||
| 40 | + "think\\console\\command\\Build", | ||
| 41 | + "think\\console\\command\\Clear", | ||
| 42 | + "think\\console\\command\\make\\Controller", | ||
| 43 | + "think\\console\\command\\make\\Model", | ||
| 44 | + "think\\console\\command\\make\\Middleware", | ||
| 45 | + "think\\console\\command\\make\\Validate", | ||
| 46 | + "think\\console\\command\\optimize\\Autoload", | ||
| 47 | + "think\\console\\command\\optimize\\Config", | ||
| 48 | + "think\\console\\command\\optimize\\Schema", | ||
| 49 | + "think\\console\\command\\optimize\\Route", | ||
| 50 | + "think\\console\\command\\RunServer", | ||
| 51 | + "think\\console\\command\\Version", | ||
| 52 | + ]; | ||
| 53 | + | ||
| 54 | + /** | ||
| 55 | + * Console constructor. | ||
| 56 | + * @access public | ||
| 57 | + * @param string $name 名称 | ||
| 58 | + * @param string $version 版本 | ||
| 59 | + * @param null|string $user 执行用户 | ||
| 60 | + */ | ||
| 61 | + public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN', $user = null) | ||
| 62 | + { | ||
| 63 | + $this->name = $name; | ||
| 64 | + $this->version = $version; | ||
| 65 | + | ||
| 66 | + if ($user) { | ||
| 67 | + $this->setUser($user); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + $this->defaultCommand = 'list'; | ||
| 71 | + $this->definition = $this->getDefaultInputDefinition(); | ||
| 72 | + | ||
| 73 | + foreach ($this->getDefaultCommands() as $command) { | ||
| 74 | + $this->add($command); | ||
| 75 | + } | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + /** | ||
| 79 | + * 设置执行用户 | ||
| 80 | + * @param $user | ||
| 81 | + */ | ||
| 82 | + public function setUser($user) | ||
| 83 | + { | ||
| 84 | + $user = posix_getpwnam($user); | ||
| 85 | + if ($user) { | ||
| 86 | + posix_setuid($user['uid']); | ||
| 87 | + posix_setgid($user['gid']); | ||
| 88 | + } | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + /** | ||
| 92 | + * 初始化 Console | ||
| 93 | + * @access public | ||
| 94 | + * @param bool $run 是否运行 Console | ||
| 95 | + * @return int|Console | ||
| 96 | + */ | ||
| 97 | + public static function init($run = true) | ||
| 98 | + { | ||
| 99 | + static $console; | ||
| 100 | + | ||
| 101 | + if (!$console) { | ||
| 102 | + $config = Container::get('config')->pull('console'); | ||
| 103 | + // 实例化 console | ||
| 104 | + $console = new self($config['name'], $config['version'], $config['user']); | ||
| 105 | + | ||
| 106 | + // 读取指令集 | ||
| 107 | + $file = Container::get('env')->get('app_path') . 'command.php'; | ||
| 108 | + | ||
| 109 | + if (is_file($file)) { | ||
| 110 | + $commands = include $file; | ||
| 111 | + | ||
| 112 | + if (is_array($commands)) { | ||
| 113 | + foreach ($commands as $command) { | ||
| 114 | + if (class_exists($command) && is_subclass_of($command, "\\think\\console\\Command")) { | ||
| 115 | + // 注册指令 | ||
| 116 | + $console->add(new $command()); | ||
| 117 | + } | ||
| 118 | + } | ||
| 119 | + } | ||
| 120 | + } | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + if ($run) { | ||
| 124 | + // 运行 | ||
| 125 | + return $console->run(); | ||
| 126 | + } else { | ||
| 127 | + return $console; | ||
| 128 | + } | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + /** | ||
| 132 | + * @access public | ||
| 133 | + * @param string $command | ||
| 134 | + * @param array $parameters | ||
| 135 | + * @param string $driver | ||
| 136 | + * @return Output|Buffer | ||
| 137 | + */ | ||
| 138 | + public static function call($command, array $parameters = [], $driver = 'buffer') | ||
| 139 | + { | ||
| 140 | + $console = self::init(false); | ||
| 141 | + | ||
| 142 | + array_unshift($parameters, $command); | ||
| 143 | + | ||
| 144 | + $input = new Input($parameters); | ||
| 145 | + $output = new Output($driver); | ||
| 146 | + | ||
| 147 | + $console->setCatchExceptions(false); | ||
| 148 | + $console->find($command)->run($input, $output); | ||
| 149 | + | ||
| 150 | + return $output; | ||
| 151 | + } | ||
| 152 | + | ||
| 153 | + /** | ||
| 154 | + * 执行当前的指令 | ||
| 155 | + * @access public | ||
| 156 | + * @return int | ||
| 157 | + * @throws \Exception | ||
| 158 | + * @api | ||
| 159 | + */ | ||
| 160 | + public function run() | ||
| 161 | + { | ||
| 162 | + $input = new Input(); | ||
| 163 | + $output = new Output(); | ||
| 164 | + | ||
| 165 | + $this->configureIO($input, $output); | ||
| 166 | + | ||
| 167 | + try { | ||
| 168 | + $exitCode = $this->doRun($input, $output); | ||
| 169 | + } catch (\Exception $e) { | ||
| 170 | + if (!$this->catchExceptions) { | ||
| 171 | + throw $e; | ||
| 172 | + } | ||
| 173 | + | ||
| 174 | + $output->renderException($e); | ||
| 175 | + | ||
| 176 | + $exitCode = $e->getCode(); | ||
| 177 | + if (is_numeric($exitCode)) { | ||
| 178 | + $exitCode = (int) $exitCode; | ||
| 179 | + if (0 === $exitCode) { | ||
| 180 | + $exitCode = 1; | ||
| 181 | + } | ||
| 182 | + } else { | ||
| 183 | + $exitCode = 1; | ||
| 184 | + } | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + if ($this->autoExit) { | ||
| 188 | + if ($exitCode > 255) { | ||
| 189 | + $exitCode = 255; | ||
| 190 | + } | ||
| 191 | + | ||
| 192 | + exit($exitCode); | ||
| 193 | + } | ||
| 194 | + | ||
| 195 | + return $exitCode; | ||
| 196 | + } | ||
| 197 | + | ||
| 198 | + /** | ||
| 199 | + * 执行指令 | ||
| 200 | + * @access public | ||
| 201 | + * @param Input $input | ||
| 202 | + * @param Output $output | ||
| 203 | + * @return int | ||
| 204 | + */ | ||
| 205 | + public function doRun(Input $input, Output $output) | ||
| 206 | + { | ||
| 207 | + if (true === $input->hasParameterOption(['--version', '-V'])) { | ||
| 208 | + $output->writeln($this->getLongVersion()); | ||
| 209 | + | ||
| 210 | + return 0; | ||
| 211 | + } | ||
| 212 | + | ||
| 213 | + $name = $this->getCommandName($input); | ||
| 214 | + | ||
| 215 | + if (true === $input->hasParameterOption(['--help', '-h'])) { | ||
| 216 | + if (!$name) { | ||
| 217 | + $name = 'help'; | ||
| 218 | + $input = new Input(['help']); | ||
| 219 | + } else { | ||
| 220 | + $this->wantHelps = true; | ||
| 221 | + } | ||
| 222 | + } | ||
| 223 | + | ||
| 224 | + if (!$name) { | ||
| 225 | + $name = $this->defaultCommand; | ||
| 226 | + $input = new Input([$this->defaultCommand]); | ||
| 227 | + } | ||
| 228 | + | ||
| 229 | + $command = $this->find($name); | ||
| 230 | + | ||
| 231 | + $exitCode = $this->doRunCommand($command, $input, $output); | ||
| 232 | + | ||
| 233 | + return $exitCode; | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + /** | ||
| 237 | + * 设置输入参数定义 | ||
| 238 | + * @access public | ||
| 239 | + * @param InputDefinition $definition | ||
| 240 | + */ | ||
| 241 | + public function setDefinition(InputDefinition $definition) | ||
| 242 | + { | ||
| 243 | + $this->definition = $definition; | ||
| 244 | + } | ||
| 245 | + | ||
| 246 | + /** | ||
| 247 | + * 获取输入参数定义 | ||
| 248 | + * @access public | ||
| 249 | + * @return InputDefinition The InputDefinition instance | ||
| 250 | + */ | ||
| 251 | + public function getDefinition() | ||
| 252 | + { | ||
| 253 | + return $this->definition; | ||
| 254 | + } | ||
| 255 | + | ||
| 256 | + /** | ||
| 257 | + * Gets the help message. | ||
| 258 | + * @access public | ||
| 259 | + * @return string A help message. | ||
| 260 | + */ | ||
| 261 | + public function getHelp() | ||
| 262 | + { | ||
| 263 | + return $this->getLongVersion(); | ||
| 264 | + } | ||
| 265 | + | ||
| 266 | + /** | ||
| 267 | + * 是否捕获异常 | ||
| 268 | + * @access public | ||
| 269 | + * @param bool $boolean | ||
| 270 | + * @api | ||
| 271 | + */ | ||
| 272 | + public function setCatchExceptions($boolean) | ||
| 273 | + { | ||
| 274 | + $this->catchExceptions = (bool) $boolean; | ||
| 275 | + } | ||
| 276 | + | ||
| 277 | + /** | ||
| 278 | + * 是否自动退出 | ||
| 279 | + * @access public | ||
| 280 | + * @param bool $boolean | ||
| 281 | + * @api | ||
| 282 | + */ | ||
| 283 | + public function setAutoExit($boolean) | ||
| 284 | + { | ||
| 285 | + $this->autoExit = (bool) $boolean; | ||
| 286 | + } | ||
| 287 | + | ||
| 288 | + /** | ||
| 289 | + * 获取名称 | ||
| 290 | + * @access public | ||
| 291 | + * @return string | ||
| 292 | + */ | ||
| 293 | + public function getName() | ||
| 294 | + { | ||
| 295 | + return $this->name; | ||
| 296 | + } | ||
| 297 | + | ||
| 298 | + /** | ||
| 299 | + * 设置名称 | ||
| 300 | + * @access public | ||
| 301 | + * @param string $name | ||
| 302 | + */ | ||
| 303 | + public function setName($name) | ||
| 304 | + { | ||
| 305 | + $this->name = $name; | ||
| 306 | + } | ||
| 307 | + | ||
| 308 | + /** | ||
| 309 | + * 获取版本 | ||
| 310 | + * @access public | ||
| 311 | + * @return string | ||
| 312 | + * @api | ||
| 313 | + */ | ||
| 314 | + public function getVersion() | ||
| 315 | + { | ||
| 316 | + return $this->version; | ||
| 317 | + } | ||
| 318 | + | ||
| 319 | + /** | ||
| 320 | + * 设置版本 | ||
| 321 | + * @access public | ||
| 322 | + * @param string $version | ||
| 323 | + */ | ||
| 324 | + public function setVersion($version) | ||
| 325 | + { | ||
| 326 | + $this->version = $version; | ||
| 327 | + } | ||
| 328 | + | ||
| 329 | + /** | ||
| 330 | + * 获取完整的版本号 | ||
| 331 | + * @access public | ||
| 332 | + * @return string | ||
| 333 | + */ | ||
| 334 | + public function getLongVersion() | ||
| 335 | + { | ||
| 336 | + if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) { | ||
| 337 | + return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion()); | ||
| 338 | + } | ||
| 339 | + | ||
| 340 | + return '<info>Console Tool</info>'; | ||
| 341 | + } | ||
| 342 | + | ||
| 343 | + /** | ||
| 344 | + * 注册一个指令 | ||
| 345 | + * @access public | ||
| 346 | + * @param string $name | ||
| 347 | + * @return Command | ||
| 348 | + */ | ||
| 349 | + public function register($name) | ||
| 350 | + { | ||
| 351 | + return $this->add(new Command($name)); | ||
| 352 | + } | ||
| 353 | + | ||
| 354 | + /** | ||
| 355 | + * 添加指令 | ||
| 356 | + * @access public | ||
| 357 | + * @param Command[] $commands | ||
| 358 | + */ | ||
| 359 | + public function addCommands(array $commands) | ||
| 360 | + { | ||
| 361 | + foreach ($commands as $command) { | ||
| 362 | + $this->add($command); | ||
| 363 | + } | ||
| 364 | + } | ||
| 365 | + | ||
| 366 | + /** | ||
| 367 | + * 添加一个指令 | ||
| 368 | + * @access public | ||
| 369 | + * @param Command $command | ||
| 370 | + * @return Command | ||
| 371 | + */ | ||
| 372 | + public function add(Command $command) | ||
| 373 | + { | ||
| 374 | + $command->setConsole($this); | ||
| 375 | + | ||
| 376 | + if (!$command->isEnabled()) { | ||
| 377 | + $command->setConsole(null); | ||
| 378 | + return; | ||
| 379 | + } | ||
| 380 | + | ||
| 381 | + if (null === $command->getDefinition()) { | ||
| 382 | + throw new \LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command))); | ||
| 383 | + } | ||
| 384 | + | ||
| 385 | + $this->commands[$command->getName()] = $command; | ||
| 386 | + | ||
| 387 | + foreach ($command->getAliases() as $alias) { | ||
| 388 | + $this->commands[$alias] = $command; | ||
| 389 | + } | ||
| 390 | + | ||
| 391 | + return $command; | ||
| 392 | + } | ||
| 393 | + | ||
| 394 | + /** | ||
| 395 | + * 获取指令 | ||
| 396 | + * @access public | ||
| 397 | + * @param string $name 指令名称 | ||
| 398 | + * @return Command | ||
| 399 | + * @throws \InvalidArgumentException | ||
| 400 | + */ | ||
| 401 | + public function get($name) | ||
| 402 | + { | ||
| 403 | + if (!isset($this->commands[$name])) { | ||
| 404 | + throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name)); | ||
| 405 | + } | ||
| 406 | + | ||
| 407 | + $command = $this->commands[$name]; | ||
| 408 | + | ||
| 409 | + if ($this->wantHelps) { | ||
| 410 | + $this->wantHelps = false; | ||
| 411 | + | ||
| 412 | + /** @var HelpCommand $helpCommand */ | ||
| 413 | + $helpCommand = $this->get('help'); | ||
| 414 | + $helpCommand->setCommand($command); | ||
| 415 | + | ||
| 416 | + return $helpCommand; | ||
| 417 | + } | ||
| 418 | + | ||
| 419 | + return $command; | ||
| 420 | + } | ||
| 421 | + | ||
| 422 | + /** | ||
| 423 | + * 某个指令是否存在 | ||
| 424 | + * @access public | ||
| 425 | + * @param string $name 指令名称 | ||
| 426 | + * @return bool | ||
| 427 | + */ | ||
| 428 | + public function has($name) | ||
| 429 | + { | ||
| 430 | + return isset($this->commands[$name]); | ||
| 431 | + } | ||
| 432 | + | ||
| 433 | + /** | ||
| 434 | + * 获取所有的命名空间 | ||
| 435 | + * @access public | ||
| 436 | + * @return array | ||
| 437 | + */ | ||
| 438 | + public function getNamespaces() | ||
| 439 | + { | ||
| 440 | + $namespaces = []; | ||
| 441 | + foreach ($this->commands as $command) { | ||
| 442 | + $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName())); | ||
| 443 | + | ||
| 444 | + foreach ($command->getAliases() as $alias) { | ||
| 445 | + $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias)); | ||
| 446 | + } | ||
| 447 | + } | ||
| 448 | + | ||
| 449 | + return array_values(array_unique(array_filter($namespaces))); | ||
| 450 | + } | ||
| 451 | + | ||
| 452 | + /** | ||
| 453 | + * 查找注册命名空间中的名称或缩写。 | ||
| 454 | + * @access public | ||
| 455 | + * @param string $namespace | ||
| 456 | + * @return string | ||
| 457 | + * @throws \InvalidArgumentException | ||
| 458 | + */ | ||
| 459 | + public function findNamespace($namespace) | ||
| 460 | + { | ||
| 461 | + $allNamespaces = $this->getNamespaces(); | ||
| 462 | + $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { | ||
| 463 | + return preg_quote($matches[1]) . '[^:]*'; | ||
| 464 | + }, $namespace); | ||
| 465 | + $namespaces = preg_grep('{^' . $expr . '}', $allNamespaces); | ||
| 466 | + | ||
| 467 | + if (empty($namespaces)) { | ||
| 468 | + $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace); | ||
| 469 | + | ||
| 470 | + if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) { | ||
| 471 | + if (1 == count($alternatives)) { | ||
| 472 | + $message .= "\n\nDid you mean this?\n "; | ||
| 473 | + } else { | ||
| 474 | + $message .= "\n\nDid you mean one of these?\n "; | ||
| 475 | + } | ||
| 476 | + | ||
| 477 | + $message .= implode("\n ", $alternatives); | ||
| 478 | + } | ||
| 479 | + | ||
| 480 | + throw new \InvalidArgumentException($message); | ||
| 481 | + } | ||
| 482 | + | ||
| 483 | + $exact = in_array($namespace, $namespaces, true); | ||
| 484 | + if (count($namespaces) > 1 && !$exact) { | ||
| 485 | + throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces)))); | ||
| 486 | + } | ||
| 487 | + | ||
| 488 | + return $exact ? $namespace : reset($namespaces); | ||
| 489 | + } | ||
| 490 | + | ||
| 491 | + /** | ||
| 492 | + * 查找指令 | ||
| 493 | + * @access public | ||
| 494 | + * @param string $name 名称或者别名 | ||
| 495 | + * @return Command | ||
| 496 | + * @throws \InvalidArgumentException | ||
| 497 | + */ | ||
| 498 | + public function find($name) | ||
| 499 | + { | ||
| 500 | + $allCommands = array_keys($this->commands); | ||
| 501 | + | ||
| 502 | + $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { | ||
| 503 | + return preg_quote($matches[1]) . '[^:]*'; | ||
| 504 | + }, $name); | ||
| 505 | + | ||
| 506 | + $commands = preg_grep('{^' . $expr . '}', $allCommands); | ||
| 507 | + | ||
| 508 | + if (empty($commands) || count(preg_grep('{^' . $expr . '$}', $commands)) < 1) { | ||
| 509 | + if (false !== $pos = strrpos($name, ':')) { | ||
| 510 | + $this->findNamespace(substr($name, 0, $pos)); | ||
| 511 | + } | ||
| 512 | + | ||
| 513 | + $message = sprintf('Command "%s" is not defined.', $name); | ||
| 514 | + | ||
| 515 | + if ($alternatives = $this->findAlternatives($name, $allCommands)) { | ||
| 516 | + if (1 == count($alternatives)) { | ||
| 517 | + $message .= "\n\nDid you mean this?\n "; | ||
| 518 | + } else { | ||
| 519 | + $message .= "\n\nDid you mean one of these?\n "; | ||
| 520 | + } | ||
| 521 | + $message .= implode("\n ", $alternatives); | ||
| 522 | + } | ||
| 523 | + | ||
| 524 | + throw new \InvalidArgumentException($message); | ||
| 525 | + } | ||
| 526 | + | ||
| 527 | + if (count($commands) > 1) { | ||
| 528 | + $commandList = $this->commands; | ||
| 529 | + | ||
| 530 | + $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) { | ||
| 531 | + $commandName = $commandList[$nameOrAlias]->getName(); | ||
| 532 | + | ||
| 533 | + return $commandName === $nameOrAlias || !in_array($commandName, $commands); | ||
| 534 | + }); | ||
| 535 | + } | ||
| 536 | + | ||
| 537 | + $exact = in_array($name, $commands, true); | ||
| 538 | + if (count($commands) > 1 && !$exact) { | ||
| 539 | + $suggestions = $this->getAbbreviationSuggestions(array_values($commands)); | ||
| 540 | + | ||
| 541 | + throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions)); | ||
| 542 | + } | ||
| 543 | + | ||
| 544 | + return $this->get($exact ? $name : reset($commands)); | ||
| 545 | + } | ||
| 546 | + | ||
| 547 | + /** | ||
| 548 | + * 获取所有的指令 | ||
| 549 | + * @access public | ||
| 550 | + * @param string $namespace 命名空间 | ||
| 551 | + * @return Command[] | ||
| 552 | + * @api | ||
| 553 | + */ | ||
| 554 | + public function all($namespace = null) | ||
| 555 | + { | ||
| 556 | + if (null === $namespace) { | ||
| 557 | + return $this->commands; | ||
| 558 | + } | ||
| 559 | + | ||
| 560 | + $commands = []; | ||
| 561 | + foreach ($this->commands as $name => $command) { | ||
| 562 | + if ($this->extractNamespace($name, substr_count($namespace, ':') + 1) === $namespace) { | ||
| 563 | + $commands[$name] = $command; | ||
| 564 | + } | ||
| 565 | + } | ||
| 566 | + | ||
| 567 | + return $commands; | ||
| 568 | + } | ||
| 569 | + | ||
| 570 | + /** | ||
| 571 | + * 获取可能的指令名 | ||
| 572 | + * @access public | ||
| 573 | + * @param array $names | ||
| 574 | + * @return array | ||
| 575 | + */ | ||
| 576 | + public static function getAbbreviations($names) | ||
| 577 | + { | ||
| 578 | + $abbrevs = []; | ||
| 579 | + foreach ($names as $name) { | ||
| 580 | + for ($len = strlen($name); $len > 0; --$len) { | ||
| 581 | + $abbrev = substr($name, 0, $len); | ||
| 582 | + $abbrevs[$abbrev][] = $name; | ||
| 583 | + } | ||
| 584 | + } | ||
| 585 | + | ||
| 586 | + return $abbrevs; | ||
| 587 | + } | ||
| 588 | + | ||
| 589 | + /** | ||
| 590 | + * 配置基于用户的参数和选项的输入和输出实例。 | ||
| 591 | + * @access protected | ||
| 592 | + * @param Input $input 输入实例 | ||
| 593 | + * @param Output $output 输出实例 | ||
| 594 | + */ | ||
| 595 | + protected function configureIO(Input $input, Output $output) | ||
| 596 | + { | ||
| 597 | + if (true === $input->hasParameterOption(['--ansi'])) { | ||
| 598 | + $output->setDecorated(true); | ||
| 599 | + } elseif (true === $input->hasParameterOption(['--no-ansi'])) { | ||
| 600 | + $output->setDecorated(false); | ||
| 601 | + } | ||
| 602 | + | ||
| 603 | + if (true === $input->hasParameterOption(['--no-interaction', '-n'])) { | ||
| 604 | + $input->setInteractive(false); | ||
| 605 | + } | ||
| 606 | + | ||
| 607 | + if (true === $input->hasParameterOption(['--quiet', '-q'])) { | ||
| 608 | + $output->setVerbosity(Output::VERBOSITY_QUIET); | ||
| 609 | + } else { | ||
| 610 | + if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) { | ||
| 611 | + $output->setVerbosity(Output::VERBOSITY_DEBUG); | ||
| 612 | + } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) { | ||
| 613 | + $output->setVerbosity(Output::VERBOSITY_VERY_VERBOSE); | ||
| 614 | + } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) { | ||
| 615 | + $output->setVerbosity(Output::VERBOSITY_VERBOSE); | ||
| 616 | + } | ||
| 617 | + } | ||
| 618 | + } | ||
| 619 | + | ||
| 620 | + /** | ||
| 621 | + * 执行指令 | ||
| 622 | + * @access protected | ||
| 623 | + * @param Command $command 指令实例 | ||
| 624 | + * @param Input $input 输入实例 | ||
| 625 | + * @param Output $output 输出实例 | ||
| 626 | + * @return int | ||
| 627 | + * @throws \Exception | ||
| 628 | + */ | ||
| 629 | + protected function doRunCommand(Command $command, Input $input, Output $output) | ||
| 630 | + { | ||
| 631 | + return $command->run($input, $output); | ||
| 632 | + } | ||
| 633 | + | ||
| 634 | + /** | ||
| 635 | + * 获取指令的基础名称 | ||
| 636 | + * @access protected | ||
| 637 | + * @param Input $input | ||
| 638 | + * @return string | ||
| 639 | + */ | ||
| 640 | + protected function getCommandName(Input $input) | ||
| 641 | + { | ||
| 642 | + return $input->getFirstArgument(); | ||
| 643 | + } | ||
| 644 | + | ||
| 645 | + /** | ||
| 646 | + * 获取默认输入定义 | ||
| 647 | + * @access protected | ||
| 648 | + * @return InputDefinition | ||
| 649 | + */ | ||
| 650 | + protected function getDefaultInputDefinition() | ||
| 651 | + { | ||
| 652 | + return new InputDefinition([ | ||
| 653 | + new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), | ||
| 654 | + new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'), | ||
| 655 | + new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this console version'), | ||
| 656 | + new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'), | ||
| 657 | + new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'), | ||
| 658 | + new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'), | ||
| 659 | + new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'), | ||
| 660 | + new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'), | ||
| 661 | + ]); | ||
| 662 | + } | ||
| 663 | + | ||
| 664 | + /** | ||
| 665 | + * 设置默认命令 | ||
| 666 | + * @access protected | ||
| 667 | + * @return Command[] An array of default Command instances | ||
| 668 | + */ | ||
| 669 | + protected function getDefaultCommands() | ||
| 670 | + { | ||
| 671 | + $defaultCommands = []; | ||
| 672 | + | ||
| 673 | + foreach (self::$defaultCommands as $classname) { | ||
| 674 | + if (class_exists($classname) && is_subclass_of($classname, "think\\console\\Command")) { | ||
| 675 | + $defaultCommands[] = new $classname(); | ||
| 676 | + } | ||
| 677 | + } | ||
| 678 | + | ||
| 679 | + return $defaultCommands; | ||
| 680 | + } | ||
| 681 | + | ||
| 682 | + public static function addDefaultCommands(array $classnames) | ||
| 683 | + { | ||
| 684 | + self::$defaultCommands = array_merge(self::$defaultCommands, $classnames); | ||
| 685 | + } | ||
| 686 | + | ||
| 687 | + /** | ||
| 688 | + * 获取可能的建议 | ||
| 689 | + * @access private | ||
| 690 | + * @param array $abbrevs | ||
| 691 | + * @return string | ||
| 692 | + */ | ||
| 693 | + private function getAbbreviationSuggestions($abbrevs) | ||
| 694 | + { | ||
| 695 | + return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : ''); | ||
| 696 | + } | ||
| 697 | + | ||
| 698 | + /** | ||
| 699 | + * 返回命名空间部分 | ||
| 700 | + * @access public | ||
| 701 | + * @param string $name 指令 | ||
| 702 | + * @param string $limit 部分的命名空间的最大数量 | ||
| 703 | + * @return string | ||
| 704 | + */ | ||
| 705 | + public function extractNamespace($name, $limit = null) | ||
| 706 | + { | ||
| 707 | + $parts = explode(':', $name); | ||
| 708 | + array_pop($parts); | ||
| 709 | + | ||
| 710 | + return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit)); | ||
| 711 | + } | ||
| 712 | + | ||
| 713 | + /** | ||
| 714 | + * 查找可替代的建议 | ||
| 715 | + * @access private | ||
| 716 | + * @param string $name | ||
| 717 | + * @param array|\Traversable $collection | ||
| 718 | + * @return array | ||
| 719 | + */ | ||
| 720 | + private function findAlternatives($name, $collection) | ||
| 721 | + { | ||
| 722 | + $threshold = 1e3; | ||
| 723 | + $alternatives = []; | ||
| 724 | + | ||
| 725 | + $collectionParts = []; | ||
| 726 | + foreach ($collection as $item) { | ||
| 727 | + $collectionParts[$item] = explode(':', $item); | ||
| 728 | + } | ||
| 729 | + | ||
| 730 | + foreach (explode(':', $name) as $i => $subname) { | ||
| 731 | + foreach ($collectionParts as $collectionName => $parts) { | ||
| 732 | + $exists = isset($alternatives[$collectionName]); | ||
| 733 | + if (!isset($parts[$i]) && $exists) { | ||
| 734 | + $alternatives[$collectionName] += $threshold; | ||
| 735 | + continue; | ||
| 736 | + } elseif (!isset($parts[$i])) { | ||
| 737 | + continue; | ||
| 738 | + } | ||
| 739 | + | ||
| 740 | + $lev = levenshtein($subname, $parts[$i]); | ||
| 741 | + if ($lev <= strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) { | ||
| 742 | + $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev; | ||
| 743 | + } elseif ($exists) { | ||
| 744 | + $alternatives[$collectionName] += $threshold; | ||
| 745 | + } | ||
| 746 | + } | ||
| 747 | + } | ||
| 748 | + | ||
| 749 | + foreach ($collection as $item) { | ||
| 750 | + $lev = levenshtein($name, $item); | ||
| 751 | + if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) { | ||
| 752 | + $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev; | ||
| 753 | + } | ||
| 754 | + } | ||
| 755 | + | ||
| 756 | + $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { | ||
| 757 | + return $lev < 2 * $threshold; | ||
| 758 | + }); | ||
| 759 | + asort($alternatives); | ||
| 760 | + | ||
| 761 | + return array_keys($alternatives); | ||
| 762 | + } | ||
| 763 | + | ||
| 764 | + /** | ||
| 765 | + * 设置默认的指令 | ||
| 766 | + * @access public | ||
| 767 | + * @param string $commandName The Command name | ||
| 768 | + */ | ||
| 769 | + public function setDefaultCommand($commandName) | ||
| 770 | + { | ||
| 771 | + $this->defaultCommand = $commandName; | ||
| 772 | + } | ||
| 773 | + | ||
| 774 | + /** | ||
| 775 | + * 返回所有的命名空间 | ||
| 776 | + * @access private | ||
| 777 | + * @param string $name | ||
| 778 | + * @return array | ||
| 779 | + */ | ||
| 780 | + private function extractAllNamespaces($name) | ||
| 781 | + { | ||
| 782 | + $parts = explode(':', $name, -1); | ||
| 783 | + $namespaces = []; | ||
| 784 | + | ||
| 785 | + foreach ($parts as $part) { | ||
| 786 | + if (count($namespaces)) { | ||
| 787 | + $namespaces[] = end($namespaces) . ':' . $part; | ||
| 788 | + } else { | ||
| 789 | + $namespaces[] = $part; | ||
| 790 | + } | ||
| 791 | + } | ||
| 792 | + | ||
| 793 | + return $namespaces; | ||
| 794 | + } | ||
| 795 | + | ||
| 796 | + public function __debugInfo() | ||
| 797 | + { | ||
| 798 | + $data = get_object_vars($this); | ||
| 799 | + unset($data['commands'], $data['definition']); | ||
| 800 | + | ||
| 801 | + return $data; | ||
| 802 | + } | ||
| 803 | +} |
-
Please register or login to post a comment