diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..36f7b6f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,42 @@ +sudo: false + +language: php + +branches: + only: + - stable + +cache: + directories: + - $HOME/.composer/cache + +before_install: + - composer self-update + +install: + - composer install --no-dev --no-interaction --ignore-platform-reqs + - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip . + - composer require --update-no-dev --no-interaction "topthink/think-image:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0" + - composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0" + - composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0" + - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip . + +script: + - php think unit + +deploy: + provider: releases + api_key: + secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw= + file: + - ThinkPHP_Core.zip + - ThinkPHP_Full.zip + skip_cleanup: true + on: + tags: true diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..574a39c --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,32 @@ + +ThinkPHP遵循Apache2开源协议发布,并提供免费使用。 +版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn) +All rights reserved。 +ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。 + +Apache Licence是著名的非盈利开源组织Apache采用的协议。 +该协议和BSD类似,鼓励代码共享和尊重原作者的著作权, +允许代码修改,再作为开源或商业软件发布。需要满足 +的条件: +1. 需要给代码的用户一份Apache Licence ; +2. 如果你修改了代码,需要在被修改的文件中说明; +3. 在延伸的代码中(修改和有源代码衍生的代码中)需要 +带有原来代码中的协议,商标,专利声明和其他原来作者规 +定需要包含的说明; +4. 如果再发布的产品中包含一个Notice文件,则在Notice文 +件中需要带有本协议内容。你可以在Notice中增加自己的 +许可,但不可以表现为对Apache Licence构成更改。 +具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0 + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..acf2d0c --- /dev/null +++ b/README.md @@ -0,0 +1,155 @@ +ThinkPHP 5.1 +=============== + +ThinkPHP5.1对底层架构做了进一步的改进,减少依赖,其主要特性包括: + + + 采用容器统一管理对象 + + 支持Facade + + 注解路由支持 + + 路由跨域请求支持 + + 配置和路由目录独立 + + 取消系统常量 + + 助手函数增强 + + 类库别名机制 + + 增加条件查询 + + 改进查询机制 + + 配置采用二级 + + 依赖注入完善 + + +> ThinkPHP5的运行环境要求PHP5.6以上。 + + +## 目录结构 + +初始的目录结构如下: + +~~~ +www WEB部署目录(或者子目录) +├─application 应用目录 +│ ├─common 公共模块目录(可以更改) +│ ├─module_name 模块目录 +│ │ ├─common.php 模块函数文件 +│ │ ├─controller 控制器目录 +│ │ ├─model 模型目录 +│ │ ├─view 视图目录 +│ │ └─ ... 更多类库目录 +│ │ +│ ├─command.php 命令行定义文件 +│ ├─common.php 公共函数文件 +│ └─tags.php 应用行为扩展定义文件 +│ +├─config 应用配置目录 +│ ├─module_name 模块配置目录 +│ │ ├─database.php 数据库配置 +│ │ ├─cache 缓存配置 +│ │ └─ ... +│ │ +│ ├─app.php 应用配置 +│ ├─cache.php 缓存配置 +│ ├─cookie.php Cookie配置 +│ ├─database.php 数据库配置 +│ ├─log.php 日志配置 +│ ├─session.php Session配置 +│ ├─template.php 模板引擎配置 +│ └─trace.php Trace配置 +│ +├─route 路由定义目录 +│ ├─route.php 路由定义 +│ └─... 更多 +│ +├─public WEB目录(对外访问目录) +│ ├─index.php 入口文件 +│ ├─router.php 快速测试文件 +│ └─.htaccess 用于apache的重写 +│ +├─thinkphp 框架系统目录 +│ ├─lang 语言文件目录 +│ ├─library 框架类库目录 +│ │ ├─think Think类库包目录 +│ │ └─traits 系统Trait目录 +│ │ +│ ├─tpl 系统模板目录 +│ ├─base.php 基础定义文件 +│ ├─console.php 控制台入口文件 +│ ├─convention.php 框架惯例配置文件 +│ ├─helper.php 助手函数文件 +│ ├─phpunit.xml phpunit配置文件 +│ └─start.php 框架入口文件 +│ +├─extend 扩展类库目录 +├─runtime 应用的运行时目录(可写,可定制) +├─vendor 第三方类库目录(Composer依赖库) +├─build.php 自动生成定义文件(参考) +├─composer.json composer 定义文件 +├─LICENSE.txt 授权说明文件 +├─README.md README 文件 +├─think 命令行入口文件 +~~~ + +> router.php用于php自带webserver支持,可用于快速测试 +> 切换到public目录后,启动命令:php -S localhost:8888 router.php +> 上面的目录结构和名称是可以改变的,这取决于你的入口文件和配置参数。 + +## 升级指导 + +原有下面系统类库的命名空间需要调整: + +* think\App => think\facade\App (或者 App ) +* think\Cache => think\facade\Cache (或者 Cache ) +* think\Config => think\facade\Config (或者 Config ) +* think\Cookie => think\facade\Cookie (或者 Cookie ) +* think\Debug => think\facade\Debug (或者 Debug ) +* think\Hook => think\facade\Hook (或者 Hook ) +* think\Lang => think\facade\Lang (或者 Lang ) +* think\Log => think\facade\Log (或者 Log ) +* think\Request => think\facade\Request (或者 Request ) +* think\Response => think\facade\Reponse (或者 Reponse ) +* think\Route => think\facade\Route (或者 Route ) +* think\Session => think\facade\Session (或者 Session ) +* think\Url => think\facade\Url (或者 Url ) + +原有的配置文件config.php 拆分为app.php cache.php 等独立配置文件 放入config目录。 +原有的路由定义文件route.php 移动到route目录 + +## 命名规范 + +`ThinkPHP5`遵循PSR-2命名规范和PSR-4自动加载规范,并且注意如下规范: + +### 目录和文件 + +* 目录不强制规范,驼峰和小写+下划线模式均支持; +* 类库、函数文件统一以`.php`为后缀; +* 类的文件名均以命名空间定义,并且命名空间的路径和类库文件所在路径一致; +* 类名和类文件名保持一致,统一采用驼峰法命名(首字母大写); + +### 函数和类、属性命名 +* 类的命名采用驼峰法,并且首字母大写,例如 `User`、`UserType`,默认不需要添加后缀,例如`UserController`应该直接命名为`User`; +* 函数的命名使用小写字母和下划线(小写字母开头)的方式,例如 `get_client_ip`; +* 方法的命名使用驼峰法,并且首字母小写,例如 `getUserName`; +* 属性的命名使用驼峰法,并且首字母小写,例如 `tableName`、`instance`; +* 以双下划线“__”打头的函数或方法作为魔法方法,例如 `__call` 和 `__autoload`; + +### 常量和配置 +* 常量以大写字母和下划线命名,例如 `APP_PATH`和 `THINK_PATH`; +* 配置参数以小写字母和下划线命名,例如 `url_route_on` 和`url_convert`; + +### 数据表和字段 +* 数据表和字段采用小写加下划线方式命名,并注意字段名不要以下划线开头,例如 `think_user` 表和 `user_name`字段,不建议使用驼峰和中文作为数据表字段命名。 + +## 参与开发 +请参阅 [ThinkPHP5 核心框架包](https://github.com/top-think/framework)。 + +## 版权信息 + +ThinkPHP遵循Apache2开源协议发布,并提供免费使用。 + +本项目包含的第三方源码和二进制文件之版权信息另行标注。 + +版权所有Copyright © 2006-2018 by ThinkPHP (http://thinkphp.cn) + +All rights reserved。 + +ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。 + +更多细节参阅 [LICENSE.txt](LICENSE.txt) diff --git a/application/.htaccess b/application/.htaccess new file mode 100644 index 0000000..3418e55 --- /dev/null +++ b/application/.htaccess @@ -0,0 +1 @@ +deny from all \ No newline at end of file diff --git a/application/command.php b/application/command.php new file mode 100644 index 0000000..826bb2b --- /dev/null +++ b/application/command.php @@ -0,0 +1,12 @@ + +// +---------------------------------------------------------------------- + +return []; diff --git a/application/common.php b/application/common.php new file mode 100644 index 0000000..55d22f2 --- /dev/null +++ b/application/common.php @@ -0,0 +1,12 @@ + +// +---------------------------------------------------------------------- + +// 应用公共文件 diff --git a/application/index/behavior/test.php b/application/index/behavior/test.php new file mode 100644 index 0000000..9ec4839 --- /dev/null +++ b/application/index/behavior/test.php @@ -0,0 +1,23 @@ +'; + } + + //若位置名称对应的方法不存在,则执行这个 + public function run($params) + { + echo 'run参数'.$params; + } + + //根据执行的位置名称,方法名 对应位置名称,若存在下划线将去掉下划线 + public function appInit($params) + { + echo 'appInit参数'; + } +} diff --git a/application/index/controller/Index.php b/application/index/controller/Index.php new file mode 100644 index 0000000..2c4ed42 --- /dev/null +++ b/application/index/controller/Index.php @@ -0,0 +1,15 @@ +*{ padding: 0; margin: 0; } div{ padding: 4px 48px;} a{color:#2E5CD5;cursor: pointer;text-decoration: none} a:hover{text-decoration:underline; } body{ background: #fff; font-family: "Century Gothic","Microsoft yahei"; color: #333;font-size:18px;} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.6em; font-size: 42px }
ThinkPHP V5.1
12载初心不改(2006-2018) - 你值得信赖的PHP框架
\n";
+ if ($label != '') {
+ $content .= "{$label} :\n";
+ }
+ $content .= htmlspecialchars(print_r($vars, true), ENT_COMPAT, 'ISO-8859-1');
+ $content .= "\n\n";
+ } else {
+ $content = $label . " :\n" . print_r($vars, true);
+ }
+ echo $content;
+ if ($return) exit;
+ return null;
+
+ for ($i=0;$i<100;$i++){
+
+ }
+
+}
+
+
+
+// 加载基础文件
+require __DIR__ . '/../thinkphp/base.php';
+
+// 支持事先使用静态方法设置Request对象和Config对象
+
+// Container::get('app') 返回thinkphp/libray/think/app的实例
+// run() thinkphp/libray/think/app 对应用进行各种配置和初始化
+// send() think\Response 内
+// 执行应用并响应
+
+Container::get('app')->run()->send();
+
+//Loader::dinfo();
diff --git a/public/robots.txt b/public/robots.txt
new file mode 100644
index 0000000..eb05362
--- /dev/null
+++ b/public/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+Disallow:
diff --git a/public/router.php b/public/router.php
new file mode 100644
index 0000000..4f916b4
--- /dev/null
+++ b/public/router.php
@@ -0,0 +1,17 @@
+
+// +----------------------------------------------------------------------
+// $Id$
+
+if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"])) {
+ return false;
+} else {
+ require __DIR__ . "/index.php";
+}
diff --git a/public/static/.gitignore b/public/static/.gitignore
new file mode 100644
index 0000000..c96a04f
--- /dev/null
+++ b/public/static/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
\ No newline at end of file
diff --git a/route/route.php b/route/route.php
new file mode 100644
index 0000000..1a44c5e
--- /dev/null
+++ b/route/route.php
@@ -0,0 +1,22 @@
+
+// +----------------------------------------------------------------------
+
+//Route::get('think', function () {
+// return 'hello,ThinkPHP5!';
+//});
+
+Route::get('hello/:name', 'index/hello');
+
+Route::get('news', 'news/test/hello');
+
+return [
+
+];
diff --git a/route/routes.php b/route/routes.php
new file mode 100644
index 0000000..d2342f3
--- /dev/null
+++ b/route/routes.php
@@ -0,0 +1,22 @@
+
+// +----------------------------------------------------------------------
+
+Route::get('think', function () {
+ return 'hello,ThinkPHP5!';
+});
+
+//Route::get('hello/:name', 'index/hello');
+//
+//Route::get('news', 'news/test/hello');
+
+return [
+
+];
diff --git a/route/routet.php b/route/routet.php
new file mode 100644
index 0000000..eb326a7
--- /dev/null
+++ b/route/routet.php
@@ -0,0 +1,16 @@
+
+// +----------------------------------------------------------------------
+
+return [
+ 'test' => [
+ 'news/test/index',[]
+ ]
+];
diff --git a/runtime/.gitignore b/runtime/.gitignore
new file mode 100644
index 0000000..c96a04f
--- /dev/null
+++ b/runtime/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
\ No newline at end of file
diff --git a/think b/think
new file mode 100644
index 0000000..6a923b3
--- /dev/null
+++ b/think
@@ -0,0 +1,22 @@
+#!/usr/bin/env php
+
+// +----------------------------------------------------------------------
+
+namespace think;
+
+// 加载基础文件
+require __DIR__ . '/thinkphp/base.php';
+
+// 应用初始化
+Container::get('app')->path(__DIR__ . '/application/')->initialize();
+
+// 控制台初始化
+Console::init();
\ No newline at end of file
diff --git a/thinkphp/.gitignore b/thinkphp/.gitignore
new file mode 100644
index 0000000..832c352
--- /dev/null
+++ b/thinkphp/.gitignore
@@ -0,0 +1,3 @@
+/composer.lock
+.idea
+.DS_Store
diff --git a/thinkphp/.htaccess b/thinkphp/.htaccess
new file mode 100644
index 0000000..3418e55
--- /dev/null
+++ b/thinkphp/.htaccess
@@ -0,0 +1 @@
+deny from all
\ No newline at end of file
diff --git a/thinkphp/CONTRIBUTING.md b/thinkphp/CONTRIBUTING.md
new file mode 100644
index 0000000..6cefcb3
--- /dev/null
+++ b/thinkphp/CONTRIBUTING.md
@@ -0,0 +1,119 @@
+如何贡献我的源代码
+===
+
+此文档介绍了 ThinkPHP 团队的组成以及运转机制,您提交的代码将给 ThinkPHP 项目带来什么好处,以及如何才能加入我们的行列。
+
+## 通过 Github 贡献代码
+
+ThinkPHP 目前使用 Git 来控制程序版本,如果你想为 ThinkPHP 贡献源代码,请先大致了解 Git 的使用方法。我们目前把项目托管在 GitHub 上,任何 GitHub 用户都可以向我们贡献代码。
+
+参与的方式很简单,`fork`一份 ThinkPHP 的代码到你的仓库中,修改后提交,并向我们发起`pull request`申请,我们会及时对代码进行审查并处理你的申请并。审查通过后,你的代码将被`merge`进我们的仓库中,这样你就会自动出现在贡献者名单里了,非常方便。
+
+我们希望你贡献的代码符合:
+
+* ThinkPHP 的编码规范
+* 适当的注释,能让其他人读懂
+* 遵循 Apache2 开源协议
+
+**如果想要了解更多细节或有任何疑问,请继续阅读下面的内容**
+
+### 注意事项
+
+* 本项目代码格式化标准选用 [**PSR-2**](http://www.kancloud.cn/thinkphp/php-fig-psr/3141);
+* 类名和类文件名遵循 [**PSR-4**](http://www.kancloud.cn/thinkphp/php-fig-psr/3144);
+* 对于 Issues 的处理,请使用诸如 `fix #xxx(Issue ID)` 的 commit title 直接关闭 issue。
+* 系统会自动在 PHP 5.4 5.5 5.6 7.0 和 HHVM 上测试修改,其中 HHVM 下的测试容许报错,请确保你的修改符合 PHP 5.4 ~ 5.6 和 PHP 7.0 的语法规范;
+* 管理员不会合并造成 CI faild 的修改,若出现 CI faild 请检查自己的源代码或修改相应的[单元测试文件](tests);
+
+## GitHub Issue
+
+GitHub 提供了 Issue 功能,该功能可以用于:
+
+* 提出 bug
+* 提出功能改进
+* 反馈使用体验
+
+该功能不应该用于:
+
+ * 提出修改意见(涉及代码署名和修订追溯问题)
+ * 不友善的言论
+
+## 快速修改
+
+**GitHub 提供了快速编辑文件的功能**
+
+1. 登录 GitHub 帐号;
+2. 浏览项目文件,找到要进行修改的文件;
+3. 点击右上角铅笔图标进行修改;
+4. 填写 `Commit changes` 相关内容(Title 必填);
+5. 提交修改,等待 CI 验证和管理员合并。
+
+**若您需要一次提交大量修改,请继续阅读下面的内容**
+
+## 完整流程
+
+1. `fork`本项目;
+2. 克隆(`clone`)你 `fork` 的项目到本地;
+3. 新建分支(`branch`)并检出(`checkout`)新分支;
+4. 添加本项目到你的本地 git 仓库作为上游(`upstream`);
+5. 进行修改,若你的修改包含方法或函数的增减,请记得修改[单元测试文件](tests);
+6. 变基(衍合 `rebase`)你的分支到上游 master 分支;
+7. `push` 你的本地仓库到 GitHub;
+8. 提交 `pull request`;
+9. 等待 CI 验证(若不通过则重复 5~7,GitHub 会自动更新你的 `pull request`);
+10. 等待管理员处理,并及时 `rebase` 你的分支到上游 master 分支(若上游 master 分支有修改)。
+
+*若有必要,可以 `git push -f` 强行推送 rebase 后的分支到自己的 `fork`*
+
+*绝对不可以使用 `git push -f` 强行推送修改到上游*
+
+### 注意事项
+
+* 若对上述流程有任何不清楚的地方,请查阅 GIT 教程,如 [这个](http://backlogtool.com/git-guide/cn/);
+* 对于代码**不同方面**的修改,请在自己 `fork` 的项目中**创建不同的分支**(原因参见`完整流程`第9条备注部分);
+* 变基及交互式变基操作参见 [Git 交互式变基](http://pakchoi.me/2015/03/17/git-interactive-rebase/)
+
+## 推荐资源
+
+### 开发环境
+
+* XAMPP for Windows 5.5.x
+* WampServer (for Windows)
+* upupw Apache PHP5.4 ( for Windows)
+
+或自行安装
+
+- Apache / Nginx
+- PHP 5.4 ~ 5.6
+- MySQL / MariaDB
+
+*Windows 用户推荐添加 PHP bin 目录到 PATH,方便使用 composer*
+
+*Linux 用户自行配置环境, Mac 用户推荐使用内置 Apache 配合 Homebrew 安装 PHP 和 MariaDB*
+
+### 编辑器
+
+Sublime Text 3 + phpfmt 插件
+
+phpfmt 插件参数
+
+```json
+{
+ "autocomplete": true,
+ "enable_auto_align": true,
+ "format_on_save": true,
+ "indent_with_space": true,
+ "psr1_naming": false,
+ "psr2": true,
+ "version": 4
+}
+```
+
+或其他 编辑器 / IDE 配合 PSR2 自动格式化工具
+
+### Git GUI
+
+* SourceTree
+* GitHub Desktop
+
+或其他 Git 图形界面客户端
diff --git a/thinkphp/LICENSE.txt b/thinkphp/LICENSE.txt
new file mode 100644
index 0000000..574a39c
--- /dev/null
+++ b/thinkphp/LICENSE.txt
@@ -0,0 +1,32 @@
+
+ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
+版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
+All rights reserved。
+ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
+
+Apache Licence是著名的非盈利开源组织Apache采用的协议。
+该协议和BSD类似,鼓励代码共享和尊重原作者的著作权,
+允许代码修改,再作为开源或商业软件发布。需要满足
+的条件:
+1. 需要给代码的用户一份Apache Licence ;
+2. 如果你修改了代码,需要在被修改的文件中说明;
+3. 在延伸的代码中(修改和有源代码衍生的代码中)需要
+带有原来代码中的协议,商标,专利声明和其他原来作者规
+定需要包含的说明;
+4. 如果再发布的产品中包含一个Notice文件,则在Notice文
+件中需要带有本协议内容。你可以在Notice中增加自己的
+许可,但不可以表现为对Apache Licence构成更改。
+具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/thinkphp/README.md b/thinkphp/README.md
new file mode 100644
index 0000000..5da1eef
--- /dev/null
+++ b/thinkphp/README.md
@@ -0,0 +1,61 @@
+ThinkPHP 5.1
+===============
+
+[](https://styleci.io/repos/48530411)
+[](https://travis-ci.org/top-think/framework)
+[](http://codecov.io/github/github/top-think/framework?branch=master)
+[](https://packagist.org/packages/topthink/framework)
+[](https://packagist.org/packages/topthink/framework)
+[](https://packagist.org/packages/topthink/framework)
+[](https://packagist.org/packages/topthink/framework)
+
+ThinkPHP5.1对底层架构做了进一步的改进,减少依赖,其主要特性包括:
+
+ + 采用容器统一管理对象
+ + 支持Facade
+ + 更易用的路由
+ + 注解路由支持
+ + 路由跨域请求支持
+ + 验证类增强
+ + 配置和路由目录独立
+ + 取消系统常量
+ + 类库别名机制
+ + 模型和数据库增强
+ + 依赖注入完善
+ + 支持PSR-3日志规范
+
+### 废除的功能:
+
+ + 聚合模型
+ + 内置控制器扩展类
+ + 模型自动验证
+
+> ThinkPHP5的运行环境要求PHP5.6以上。
+
+
+## 在线手册
+
++ [完全开发手册](https://www.kancloud.cn/manual/thinkphp5_1)
++ [升级指导](https://www.kancloud.cn/manual/thinkphp5_1/354155)
+
+## 命名规范
+
+`ThinkPHP5`遵循PSR-2命名规范和PSR-4自动加载规范。
+
+## 参与开发
+
+请参阅 [ThinkPHP5 核心框架包](https://github.com/top-think/framework)。
+
+## 版权信息
+
+ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
+
+本项目包含的第三方源码和二进制文件之版权信息另行标注。
+
+版权所有Copyright © 2006-2018 by ThinkPHP (http://thinkphp.cn)
+
+All rights reserved。
+
+ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
+
+更多细节参阅 [LICENSE.txt](LICENSE.txt)
diff --git a/thinkphp/base.php b/thinkphp/base.php
new file mode 100644
index 0000000..0b78920
--- /dev/null
+++ b/thinkphp/base.php
@@ -0,0 +1,103 @@
+
+// +----------------------------------------------------------------------
+namespace think;
+
+// 载入Loader类
+require __DIR__ . '/library/think/Loader.php';
+
+// 注册自动加载
+Loader::register();
+
+//// 注册错误和异常处理机制
+//Error::register();
+//
+//// 实现日志接口
+//if (interface_exists('Psr\Log\LoggerInterface')) {
+// interface LoggerInterface extends \Psr\Log\LoggerInterface
+// {}
+//} else {
+// interface LoggerInterface
+// {}
+//}
+
+// 注册核心类到容器
+Container::getInstance()->bind([
+ 'app' => App::class,
+ 'build' => Build::class,
+ 'cache' => Cache::class,
+ 'config' => Config::class,
+ 'cookie' => Cookie::class,
+ 'debug' => Debug::class,
+ 'env' => Env::class,
+ 'hook' => Hook::class,
+ 'lang' => Lang::class,
+ 'log' => Log::class,
+ 'request' => Request::class,
+ 'response' => Response::class,
+ 'route' => Route::class,
+ 'session' => Session::class,
+ 'url' => Url::class,
+ 'validate' => Validate::class,
+ 'view' => View::class,
+ 'middlewareDispatcher' => http\middleware\Dispatcher::class,
+ // 接口依赖注入
+ 'think\LoggerInterface' => Log::class,
+]);
+
+// 注册核心类的静态代理
+Facade::bind([
+ facade\App::class => App::class,
+ facade\Build::class => Build::class,
+ facade\Cache::class => Cache::class,
+ facade\Config::class => Config::class,
+ facade\Cookie::class => Cookie::class,
+ facade\Debug::class => Debug::class,
+ facade\Env::class => Env::class,
+ facade\Hook::class => Hook::class,
+ facade\Lang::class => Lang::class,
+ facade\Log::class => Log::class,
+ facade\Request::class => Request::class,
+ facade\Response::class => Response::class,
+ facade\Route::class => Route::class,
+ facade\Session::class => Session::class,
+ facade\Url::class => Url::class,
+ facade\Validate::class => Validate::class,
+ facade\View::class => View::class,
+]);
+
+// 注册类库别名
+Loader::addClassAlias([
+ 'App' => facade\App::class,
+ 'Build' => facade\Build::class,
+ 'Cache' => facade\Cache::class,
+ 'Config' => facade\Config::class,
+ 'Cookie' => facade\Cookie::class,
+ 'Db' => Db::class,
+ 'Debug' => facade\Debug::class,
+ 'Env' => facade\Env::class,
+ 'Facade' => Facade::class,
+ 'Hook' => facade\Hook::class,
+ 'Lang' => facade\Lang::class,
+ 'Log' => facade\Log::class,
+ 'Request' => facade\Request::class,
+ 'Response' => facade\Response::class,
+ 'Route' => facade\Route::class,
+ 'Session' => facade\Session::class,
+ 'Url' => facade\Url::class,
+ 'Validate' => facade\Validate::class,
+ 'View' => facade\View::class,
+]);
+
+// 加载惯例配置文件
+facade\Config::set(__include_file(__DIR__ . '/convention.php'));
+
+// 加载composer autofile文件
+Loader::loadComposerAutoloadFiles();
diff --git a/thinkphp/composer.json b/thinkphp/composer.json
new file mode 100644
index 0000000..3e50496
--- /dev/null
+++ b/thinkphp/composer.json
@@ -0,0 +1,35 @@
+{
+ "name": "topthink/framework",
+ "description": "the new thinkphp framework",
+ "type": "think-framework",
+ "keywords": [
+ "framework",
+ "thinkphp",
+ "ORM"
+ ],
+ "homepage": "http://thinkphp.cn/",
+ "license": "Apache-2.0",
+ "authors": [
+ {
+ "name": "liu21st",
+ "email": "liu21st@gmail.com"
+ },
+ {
+ "name": "yunwuxin",
+ "email": "448901948@qq.com"
+ }
+ ],
+ "require": {
+ "php": ">=5.6.0",
+ "topthink/think-installer": "~1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^5.0|^6.0",
+ "johnkary/phpunit-speedtrap": "^1.0",
+ "mikey179/vfsStream": "~1.6",
+ "phploc/phploc": "2.*",
+ "sebastian/phpcpd": "2.*",
+ "squizlabs/php_codesniffer": "2.*",
+ "phpdocumentor/reflection-docblock": "^2.0"
+ }
+}
diff --git a/thinkphp/convention.php b/thinkphp/convention.php
new file mode 100644
index 0000000..01046c4
--- /dev/null
+++ b/thinkphp/convention.php
@@ -0,0 +1,292 @@
+ [
+ // 应用名称
+ 'app_name' => '',
+ // 应用地址
+ 'app_host' => '',
+ // 应用调试模式
+ 'app_debug' => false,
+ // 应用Trace
+ 'app_trace' => false,
+ // 应用模式状态
+ 'app_status' => '',
+ // 是否支持多模块
+ 'app_multi_module' => true,
+ // 入口自动绑定模块
+ 'auto_bind_module' => false,
+ // 注册的根命名空间
+ 'root_namespace' => [],
+ // 默认输出类型
+ 'default_return_type' => 'html',
+ // 默认AJAX 数据返回格式,可选json xml ...
+ 'default_ajax_return' => 'json',
+ // 默认JSONP格式返回的处理方法
+ 'default_jsonp_handler' => 'jsonpReturn',
+ // 默认JSONP处理方法
+ 'var_jsonp_handler' => 'callback',
+ // 默认时区
+ 'default_timezone' => 'PRC',
+ // 是否开启多语言
+ 'lang_switch_on' => false,
+ // 默认全局过滤方法 用逗号分隔多个
+ 'default_filter' => '',
+ // 默认语言
+ 'default_lang' => 'zh-cn',
+ // 应用类库后缀
+ 'class_suffix' => false,
+ // 控制器类后缀
+ 'controller_suffix' => false,
+
+ // +----------------------------------------------------------------------
+ // | 模块设置
+ // +----------------------------------------------------------------------
+
+ // 默认模块名
+ 'default_module' => 'index',
+ // 禁止访问模块
+ 'deny_module_list' => ['common'],
+ // 默认控制器名
+ 'default_controller' => 'Index',
+ // 默认操作名
+ 'default_action' => 'index',
+ // 默认验证器
+ 'default_validate' => '',
+ // 默认的空模块名
+ 'empty_module' => '',
+ // 默认的空控制器名
+ 'empty_controller' => 'Error',
+ // 操作方法前缀
+ 'use_action_prefix' => false,
+ // 操作方法后缀
+ 'action_suffix' => '',
+ // 自动搜索控制器
+ 'controller_auto_search' => false,
+
+ // +----------------------------------------------------------------------
+ // | URL设置
+ // +----------------------------------------------------------------------
+
+ // PATHINFO变量名 用于兼容模式
+ 'var_pathinfo' => 's',
+ // 兼容PATH_INFO获取
+ 'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
+ // pathinfo分隔符
+ 'pathinfo_depr' => '/',
+ // HTTPS代理标识
+ 'https_agent_name' => '',
+ // URL伪静态后缀
+ 'url_html_suffix' => 'html',
+ // URL普通方式参数 用于自动生成
+ 'url_common_param' => false,
+ // URL参数方式 0 按名称成对解析 1 按顺序解析
+ 'url_param_type' => 0,
+ // 是否开启路由延迟解析
+ 'url_lazy_route' => false,
+ // 是否强制使用路由
+ 'url_route_must' => false,
+ // 路由是否完全匹配
+ 'route_complete_match' => false,
+ // 使用注解路由
+ 'route_annotation' => false,
+ // 域名根,如thinkphp.cn
+ 'url_domain_root' => '',
+ // 是否自动转换URL中的控制器和操作名
+ 'url_convert' => true,
+ // 默认的访问控制器层
+ 'url_controller_layer' => 'controller',
+ // 表单请求类型伪装变量
+ 'var_method' => '_method',
+ // 表单ajax伪装变量
+ 'var_ajax' => '_ajax',
+ // 表单pjax伪装变量
+ 'var_pjax' => '_pjax',
+ // 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
+ 'request_cache' => false,
+ // 请求缓存有效期
+ 'request_cache_expire' => null,
+ // 全局请求缓存排除规则
+ 'request_cache_except' => [],
+
+ // 默认跳转页面对应的模板文件
+ 'dispatch_success_tmpl' => __DIR__ . '/tpl/dispatch_jump.tpl',
+ 'dispatch_error_tmpl' => __DIR__ . '/tpl/dispatch_jump.tpl',
+
+ // +----------------------------------------------------------------------
+ // | 异常及错误设置
+ // +----------------------------------------------------------------------
+
+ // 异常页面的模板文件
+ 'exception_tmpl' => __DIR__ . '/tpl/think_exception.tpl',
+
+ // 错误显示信息,非调试模式有效
+ 'error_message' => '页面错误!请稍后再试~',
+ // 显示错误信息
+ 'show_error_msg' => false,
+ // 异常处理handle类 留空使用 \think\exception\Handle
+ 'exception_handle' => '',
+ ],
+
+ // +----------------------------------------------------------------------
+ // | 模板设置
+ // +----------------------------------------------------------------------
+
+ 'template' => [
+ // 模板引擎类型 支持 php think 支持扩展
+ 'type' => 'Think',
+ // 视图基础目录,配置目录为所有模块的视图起始目录
+ 'view_base' => '',
+ // 当前模板的视图目录 留空为自动获取
+ 'view_path' => '',
+ // 模板后缀
+ 'view_suffix' => 'html',
+ // 模板文件名分隔符
+ 'view_depr' => DIRECTORY_SEPARATOR,
+ // 模板引擎普通标签开始标记
+ 'tpl_begin' => '{',
+ // 模板引擎普通标签结束标记
+ 'tpl_end' => '}',
+ // 标签库标签开始标记
+ 'taglib_begin' => '{',
+ // 标签库标签结束标记
+ 'taglib_end' => '}',
+ ],
+
+ // +----------------------------------------------------------------------
+ // | 日志设置
+ // +----------------------------------------------------------------------
+
+ 'log' => [
+ // 日志记录方式,内置 file socket 支持扩展
+ 'type' => 'File',
+ // 日志保存目录
+ //'path' => LOG_PATH,
+ // 日志记录级别
+ 'level' => [],
+ // 是否记录trace信息到日志
+ 'record_trace' => false,
+ ],
+
+ // +----------------------------------------------------------------------
+ // | Trace设置 开启 app_trace 后 有效
+ // +----------------------------------------------------------------------
+ 'trace' => [
+ // 内置Html Console 支持扩展
+ 'type' => 'Html',
+ 'file' => __DIR__ . '/tpl/page_trace.tpl',
+ ],
+
+ // +----------------------------------------------------------------------
+ // | 缓存设置
+ // +----------------------------------------------------------------------
+
+ 'cache' => [
+ // 驱动方式
+ 'type' => 'File',
+ // 缓存保存目录
+ //'path' => CACHE_PATH,
+ // 缓存前缀
+ 'prefix' => '',
+ // 缓存有效期 0表示永久缓存
+ 'expire' => 0,
+ ],
+
+ // +----------------------------------------------------------------------
+ // | 会话设置
+ // +----------------------------------------------------------------------
+
+ 'session' => [
+ 'id' => '',
+ // SESSION_ID的提交变量,解决flash上传跨域
+ 'var_session_id' => '',
+ // SESSION 前缀
+ 'prefix' => 'think',
+ // 驱动方式 支持redis memcache memcached
+ 'type' => '',
+ // 是否自动开启 SESSION
+ 'auto_start' => true,
+ 'httponly' => true,
+ 'secure' => false,
+ ],
+
+ // +----------------------------------------------------------------------
+ // | Cookie设置
+ // +----------------------------------------------------------------------
+ 'cookie' => [
+ // cookie 名称前缀
+ 'prefix' => '',
+ // cookie 保存时间
+ 'expire' => 0,
+ // cookie 保存路径
+ 'path' => '/',
+ // cookie 有效域名
+ 'domain' => '',
+ // cookie 启用安全传输
+ 'secure' => false,
+ // httponly设置
+ 'httponly' => '',
+ // 是否使用 setcookie
+ 'setcookie' => true,
+ ],
+
+ // +----------------------------------------------------------------------
+ // | 数据库设置
+ // +----------------------------------------------------------------------
+
+ 'database' => [
+ // 数据库类型
+ 'type' => 'mysql',
+ // 数据库连接DSN配置
+ 'dsn' => '',
+ // 服务器地址
+ 'hostname' => '127.0.0.1',
+ // 数据库名
+ 'database' => '',
+ // 数据库用户名
+ 'username' => 'root',
+ // 数据库密码
+ 'password' => '',
+ // 数据库连接端口
+ 'hostport' => '',
+ // 数据库连接参数
+ 'params' => [],
+ // 数据库编码默认采用utf8
+ 'charset' => 'utf8',
+ // 数据库表前缀
+ 'prefix' => '',
+ // 数据库调试模式
+ 'debug' => false,
+ // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
+ 'deploy' => 0,
+ // 数据库读写是否分离 主从式有效
+ 'rw_separate' => false,
+ // 读写分离后 主服务器数量
+ 'master_num' => 1,
+ // 指定从服务器序号
+ 'slave_no' => '',
+ // 是否严格检查字段是否存在
+ 'fields_strict' => true,
+ // 数据集返回类型
+ 'resultset_type' => 'array',
+ // 自动写入时间戳字段
+ 'auto_timestamp' => false,
+ // 时间字段取出后的默认时间格式
+ 'datetime_format' => 'Y-m-d H:i:s',
+ // 是否需要进行SQL性能分析
+ 'sql_explain' => false,
+ // 查询对象
+ 'query' => '\\think\\db\\Query',
+ ],
+
+ //分页配置
+ 'paginate' => [
+ 'type' => 'bootstrap',
+ 'var_page' => 'page',
+ 'list_rows' => 15,
+ ],
+
+];
diff --git a/thinkphp/helper.php b/thinkphp/helper.php
new file mode 100644
index 0000000..461460e
--- /dev/null
+++ b/thinkphp/helper.php
@@ -0,0 +1,691 @@
+
+// +----------------------------------------------------------------------
+
+//------------------------
+// ThinkPHP 助手函数
+//-------------------------
+
+use think\Container;
+use think\Db;
+use think\exception\HttpException;
+use think\exception\HttpResponseException;
+use think\facade\Cache;
+use think\facade\Config;
+use think\facade\Cookie;
+use think\facade\Debug;
+use think\facade\Env;
+use think\facade\Hook;
+use think\facade\Lang;
+use think\facade\Log;
+use think\facade\Request;
+use think\facade\Route;
+use think\facade\Session;
+use think\facade\Url;
+use think\Response;
+use think\route\RuleItem;
+
+if (!function_exists('abort')) {
+ /**
+ * 抛出HTTP异常
+ * @param integer|Response $code 状态码 或者 Response对象实例
+ * @param string $message 错误信息
+ * @param array $header 参数
+ */
+ function abort($code, $message = null, $header = [])
+ {
+ if ($code instanceof Response) {
+ throw new HttpResponseException($code);
+ } else {
+ throw new HttpException($code, $message, null, $header);
+ }
+ }
+}
+
+if (!function_exists('action')) {
+ /**
+ * 调用模块的操作方法 参数格式 [模块/控制器/]操作
+ * @param string $url 调用地址
+ * @param string|array $vars 调用参数 支持字符串和数组
+ * @param string $layer 要调用的控制层名称
+ * @param bool $appendSuffix 是否添加类名后缀
+ * @return mixed
+ */
+ function action($url, $vars = [], $layer = 'controller', $appendSuffix = false)
+ {
+ return app()->action($url, $vars, $layer, $appendSuffix);
+ }
+}
+
+if (!function_exists('app')) {
+ /**
+ * 快速获取容器中的实例 支持依赖注入
+ * @param string $name 类名或标识 默认获取当前应用实例
+ * @param array $args 参数
+ * @param bool $newInstance 是否每次创建新的实例
+ * @return object
+ */
+ function app($name = 'think\App', $args = [], $newInstance = false)
+ {
+ return Container::get($name, $args, $newInstance);
+ }
+}
+
+if (!function_exists('behavior')) {
+ /**
+ * 执行某个行为(run方法) 支持依赖注入
+ * @param mixed $behavior 行为类名或者别名
+ * @param mixed $args 参数
+ * @return mixed
+ */
+ function behavior($behavior, $args = null)
+ {
+ return Hook::exec($behavior, $args);
+ }
+}
+
+if (!function_exists('bind')) {
+ /**
+ * 绑定一个类到容器
+ * @access public
+ * @param string $abstract 类标识、接口
+ * @param mixed $concrete 要绑定的类、闭包或者实例
+ * @return Container
+ */
+ function bind($abstract, $concrete = null)
+ {
+ return Container::getInstance()->bind($abstract, $concrete);
+ }
+}
+
+if (!function_exists('cache')) {
+ /**
+ * 缓存管理
+ * @param mixed $name 缓存名称,如果为数组表示进行缓存设置
+ * @param mixed $value 缓存值
+ * @param mixed $options 缓存参数
+ * @param string $tag 缓存标签
+ * @return mixed
+ */
+ function cache($name, $value = '', $options = null, $tag = null)
+ {
+ if (is_array($options)) {
+ // 缓存操作的同时初始化
+ Cache::connect($options);
+ } elseif (is_array($name)) {
+ // 缓存初始化
+ return Cache::connect($name);
+ }
+
+ if ('' === $value) {
+ // 获取缓存
+ return 0 === strpos($name, '?') ? Cache::has(substr($name, 1)) : Cache::get($name);
+ } elseif (is_null($value)) {
+ // 删除缓存
+ return Cache::rm($name);
+ } else {
+ // 缓存数据
+ if (is_array($options)) {
+ $expire = isset($options['expire']) ? $options['expire'] : null; //修复查询缓存无法设置过期时间
+ } else {
+ $expire = is_numeric($options) ? $options : null; //默认快捷缓存设置过期时间
+ }
+
+ if (is_null($tag)) {
+ return Cache::set($name, $value, $expire);
+ } else {
+ return Cache::tag($tag)->set($name, $value, $expire);
+ }
+ }
+ }
+}
+
+if (!function_exists('call')) {
+ /**
+ * 调用反射执行callable 支持依赖注入
+ * @param mixed $callable 支持闭包等callable写法
+ * @param array $args 参数
+ * @return mixed
+ */
+ function call($callable, $args = [])
+ {
+ return Container::getInstance()->invoke($callable, $args);
+ }
+}
+
+if (!function_exists('class_basename')) {
+ /**
+ * 获取类名(不包含命名空间)
+ *
+ * @param string|object $class
+ * @return string
+ */
+ function class_basename($class)
+ {
+ $class = is_object($class) ? get_class($class) : $class;
+ return basename(str_replace('\\', '/', $class));
+ }
+}
+
+if (!function_exists('class_uses_recursive')) {
+ /**
+ *获取一个类里所有用到的trait,包括父类的
+ *
+ * @param $class
+ * @return array
+ */
+ function class_uses_recursive($class)
+ {
+ if (is_object($class)) {
+ $class = get_class($class);
+ }
+
+ $results = [];
+ $classes = array_merge([$class => $class], class_parents($class));
+ foreach ($classes as $class) {
+ $results += trait_uses_recursive($class);
+ }
+
+ return array_unique($results);
+ }
+}
+
+if (!function_exists('config')) {
+ /**
+ * 获取和设置配置参数
+ * @param string|array $name 参数名
+ * @param mixed $value 参数值
+ * @return mixed
+ */
+ function config($name = '', $value = null)
+ {
+ if (is_null($value) && is_string($name)) {
+ if ('.' == substr($name, -1)) {
+ return Config::pull(substr($name, 0, -1));
+ }
+
+ return 0 === strpos($name, '?') ? Config::has(substr($name, 1)) : Config::get($name);
+ } else {
+ return Config::set($name, $value);
+ }
+ }
+}
+
+if (!function_exists('container')) {
+ /**
+ * 获取容器对象实例
+ * @return Container
+ */
+ function container()
+ {
+ return Container::getInstance();
+ }
+}
+
+if (!function_exists('controller')) {
+ /**
+ * 实例化控制器 格式:[模块/]控制器
+ * @param string $name 资源地址
+ * @param string $layer 控制层名称
+ * @param bool $appendSuffix 是否添加类名后缀
+ * @return \think\Controller
+ */
+ function controller($name, $layer = 'controller', $appendSuffix = false)
+ {
+ return app()->controller($name, $layer, $appendSuffix);
+ }
+}
+
+if (!function_exists('cookie')) {
+ /**
+ * Cookie管理
+ * @param string|array $name cookie名称,如果为数组表示进行cookie设置
+ * @param mixed $value cookie值
+ * @param mixed $option 参数
+ * @return mixed
+ */
+ function cookie($name, $value = '', $option = null)
+ {
+ if (is_array($name)) {
+ // 初始化
+ Cookie::init($name);
+ } elseif (is_null($name)) {
+ // 清除
+ Cookie::clear($value);
+ } elseif ('' === $value) {
+ // 获取
+ return 0 === strpos($name, '?') ? Cookie::has(substr($name, 1), $option) : Cookie::get($name);
+ } elseif (is_null($value)) {
+ // 删除
+ return Cookie::delete($name);
+ } else {
+ // 设置
+ return Cookie::set($name, $value, $option);
+ }
+ }
+}
+
+if (!function_exists('db')) {
+ /**
+ * 实例化数据库类
+ * @param string $name 操作的数据表名称(不含前缀)
+ * @param array|string $config 数据库配置参数
+ * @param bool $force 是否强制重新连接
+ * @return \think\db\Query
+ */
+ function db($name = '', $config = [], $force = true)
+ {
+ return Db::connect($config, $force)->name($name);
+ }
+}
+
+if (!function_exists('debug')) {
+ /**
+ * 记录时间(微秒)和内存使用情况
+ * @param string $start 开始标签
+ * @param string $end 结束标签
+ * @param integer|string $dec 小数位 如果是m 表示统计内存占用
+ * @return mixed
+ */
+ function debug($start, $end = '', $dec = 6)
+ {
+ if ('' == $end) {
+ Debug::remark($start);
+ } else {
+ return 'm' == $dec ? Debug::getRangeMem($start, $end) : Debug::getRangeTime($start, $end, $dec);
+ }
+ }
+}
+
+if (!function_exists('dump')) {
+ /**
+ * 浏览器友好的变量输出
+ * @param mixed $var 变量
+ * @param boolean $echo 是否输出 默认为true 如果为false 则返回输出字符串
+ * @param string $label 标签 默认为空
+ * @return void|string
+ */
+ function dump($var, $echo = true, $label = null)
+ {
+ return Debug::dump($var, $echo, $label);
+ }
+}
+
+if (!function_exists('env')) {
+ /**
+ * 获取环境变量值
+ * @access public
+ * @param string $name 环境变量名(支持二级 .号分割)
+ * @param string $default 默认值
+ * @return mixed
+ */
+ function env($name = null, $default = null)
+ {
+ return Env::get($name, $default);
+ }
+}
+
+if (!function_exists('exception')) {
+ /**
+ * 抛出异常处理
+ *
+ * @param string $msg 异常消息
+ * @param integer $code 异常代码 默认为0
+ * @param string $exception 异常类
+ *
+ * @throws Exception
+ */
+ function exception($msg, $code = 0, $exception = '')
+ {
+ $e = $exception ?: '\think\Exception';
+ throw new $e($msg, $code);
+ }
+}
+
+if (!function_exists('halt')) {
+ /**
+ * 调试变量并且中断输出
+ * @param mixed $var 调试变量或者信息
+ */
+ function halt($var)
+ {
+ dump($var);
+
+ throw new HttpResponseException(new Response);
+ }
+}
+
+if (!function_exists('input')) {
+ /**
+ * 获取输入数据 支持默认值和过滤
+ * @param string $key 获取的变量名
+ * @param mixed $default 默认值
+ * @param string $filter 过滤方法
+ * @return mixed
+ */
+ function input($key = '', $default = null, $filter = null)
+ {
+ if (0 === strpos($key, '?')) {
+ $key = substr($key, 1);
+ $has = true;
+ }
+
+ if ($pos = strpos($key, '.')) {
+ // 指定参数来源
+ $method = substr($key, 0, $pos);
+ if (in_array($method, ['get', 'post', 'put', 'patch', 'delete', 'route', 'param', 'request', 'session', 'cookie', 'server', 'env', 'path', 'file'])) {
+ $key = substr($key, $pos + 1);
+ } else {
+ $method = 'param';
+ }
+ } else {
+ // 默认为自动判断
+ $method = 'param';
+ }
+
+ if (isset($has)) {
+ return request()->has($key, $method, $default);
+ } else {
+ return request()->$method($key, $default, $filter);
+ }
+ }
+}
+
+if (!function_exists('json')) {
+ /**
+ * 获取\think\response\Json对象实例
+ * @param mixed $data 返回的数据
+ * @param integer $code 状态码
+ * @param array $header 头部
+ * @param array $options 参数
+ * @return \think\response\Json
+ */
+ function json($data = [], $code = 200, $header = [], $options = [])
+ {
+ return Response::create($data, 'json', $code, $header, $options);
+ }
+}
+
+if (!function_exists('jsonp')) {
+ /**
+ * 获取\think\response\Jsonp对象实例
+ * @param mixed $data 返回的数据
+ * @param integer $code 状态码
+ * @param array $header 头部
+ * @param array $options 参数
+ * @return \think\response\Jsonp
+ */
+ function jsonp($data = [], $code = 200, $header = [], $options = [])
+ {
+ return Response::create($data, 'jsonp', $code, $header, $options);
+ }
+}
+
+if (!function_exists('lang')) {
+ /**
+ * 获取语言变量值
+ * @param string $name 语言变量名
+ * @param array $vars 动态变量值
+ * @param string $lang 语言
+ * @return mixed
+ */
+ function lang($name, $vars = [], $lang = '')
+ {
+ return Lang::get($name, $vars, $lang);
+ }
+}
+
+if (!function_exists('model')) {
+ /**
+ * 实例化Model
+ * @param string $name Model名称
+ * @param string $layer 业务层名称
+ * @param bool $appendSuffix 是否添加类名后缀
+ * @return \think\Model
+ */
+ function model($name = '', $layer = 'model', $appendSuffix = false)
+ {
+ return app()->model($name, $layer, $appendSuffix);
+ }
+}
+
+if (!function_exists('parse_name')) {
+ /**
+ * 字符串命名风格转换
+ * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
+ * @param string $name 字符串
+ * @param integer $type 转换类型
+ * @param bool $ucfirst 首字母是否大写(驼峰规则)
+ * @return string
+ */
+ function parse_name($name, $type = 0, $ucfirst = true)
+ {
+ if ($type) {
+ $name = preg_replace_callback('/_([a-zA-Z])/', function ($match) {
+ return strtoupper($match[1]);
+ }, $name);
+
+ return $ucfirst ? ucfirst($name) : lcfirst($name);
+ } else {
+ return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
+ }
+ }
+}
+
+if (!function_exists('redirect')) {
+ /**
+ * 获取\think\response\Redirect对象实例
+ * @param mixed $url 重定向地址 支持Url::build方法的地址
+ * @param array|integer $params 额外参数
+ * @param integer $code 状态码
+ * @return \think\response\Redirect
+ */
+ function redirect($url = [], $params = [], $code = 302)
+ {
+ if (is_integer($params)) {
+ $code = $params;
+ $params = [];
+ }
+
+ return Response::create($url, 'redirect', $code)->params($params);
+ }
+}
+
+if (!function_exists('request')) {
+ /**
+ * 获取当前Request对象实例
+ * @return Request
+ */
+ function request()
+ {
+ return app('request');
+ }
+}
+
+if (!function_exists('response')) {
+ /**
+ * 创建普通 Response 对象实例
+ * @param mixed $data 输出数据
+ * @param int|string $code 状态码
+ * @param array $header 头信息
+ * @param string $type
+ * @return Response
+ */
+ function response($data = [], $code = 200, $header = [], $type = 'html')
+ {
+ return Response::create($data, $type, $code, $header);
+ }
+}
+
+if (!function_exists('route')) {
+ /**
+ * 路由注册
+ * @param string $rule 路由规则
+ * @param mixed $route 路由地址
+ * @param array $option 路由参数
+ * @param array $pattern 变量规则
+ * @return RuleItem
+ */
+ function route($rule, $route, $option = [], $pattern = [])
+ {
+ return Route::rule($rule, $route, '*', $option, $pattern);
+ }
+}
+
+if (!function_exists('session')) {
+ /**
+ * Session管理
+ * @param string|array $name session名称,如果为数组表示进行session设置
+ * @param mixed $value session值
+ * @param string $prefix 前缀
+ * @return mixed
+ */
+ function session($name, $value = '', $prefix = null)
+ {
+ if (is_array($name)) {
+ // 初始化
+ Session::init($name);
+ } elseif (is_null($name)) {
+ // 清除
+ Session::clear($value);
+ } elseif ('' === $value) {
+ // 判断或获取
+ return 0 === strpos($name, '?') ? Session::has(substr($name, 1), $prefix) : Session::get($name, $prefix);
+ } elseif (is_null($value)) {
+ // 删除
+ return Session::delete($name, $prefix);
+ } else {
+ // 设置
+ return Session::set($name, $value, $prefix);
+ }
+ }
+}
+
+if (!function_exists('token')) {
+ /**
+ * 生成表单令牌
+ * @param string $name 令牌名称
+ * @param mixed $type 令牌生成方法
+ * @return string
+ */
+ function token($name = '__token__', $type = 'md5')
+ {
+ $token = Request::token($name, $type);
+
+ return '';
+ }
+}
+
+if (!function_exists('trace')) {
+ /**
+ * 记录日志信息
+ * @param mixed $log log信息 支持字符串和数组
+ * @param string $level 日志级别
+ * @return array|void
+ */
+ function trace($log = '[think]', $level = 'log')
+ {
+ if ('[think]' === $log) {
+ return Log::getLog();
+ } else {
+ Log::record($log, $level);
+ }
+ }
+}
+
+if (!function_exists('trait_uses_recursive')) {
+ /**
+ * 获取一个trait里所有引用到的trait
+ *
+ * @param string $trait
+ * @return array
+ */
+ function trait_uses_recursive($trait)
+ {
+ $traits = class_uses($trait);
+ foreach ($traits as $trait) {
+ $traits += trait_uses_recursive($trait);
+ }
+
+ return $traits;
+ }
+}
+
+if (!function_exists('url')) {
+ /**
+ * Url生成
+ * @param string $url 路由地址
+ * @param string|array $vars 变量
+ * @param bool|string $suffix 生成的URL后缀
+ * @param bool|string $domain 域名
+ * @return string
+ */
+ function url($url = '', $vars = '', $suffix = true, $domain = false)
+ {
+ return Url::build($url, $vars, $suffix, $domain);
+ }
+}
+
+if (!function_exists('validate')) {
+ /**
+ * 实例化验证器
+ * @param string $name 验证器名称
+ * @param string $layer 业务层名称
+ * @param bool $appendSuffix 是否添加类名后缀
+ * @return \think\Validate
+ */
+ function validate($name = '', $layer = 'validate', $appendSuffix = false)
+ {
+ return app()->validate($name, $layer, $appendSuffix);
+ }
+}
+
+if (!function_exists('view')) {
+ /**
+ * 渲染模板输出
+ * @param string $template 模板文件
+ * @param array $vars 模板变量
+ * @param integer $code 状态码
+ * @param callable $filer 内容过滤
+ * @return \think\response\View
+ */
+ function view($template = '', $vars = [], $code = 200, $filter = null)
+ {
+ return Response::create($template, 'view', $code)->assign($vars)->filter($filter);
+ }
+}
+
+if (!function_exists('widget')) {
+ /**
+ * 渲染输出Widget
+ * @param string $name Widget名称
+ * @param array $data 传入的参数
+ * @return mixed
+ */
+ function widget($name, $data = [])
+ {
+ return app()->action($name, $data, 'widget');
+ }
+}
+
+if (!function_exists('xml')) {
+ /**
+ * 获取\think\response\Xml对象实例
+ * @param mixed $data 返回的数据
+ * @param integer $code 状态码
+ * @param array $header 头部
+ * @param array $options 参数
+ * @return \think\response\Xml
+ */
+ function xml($data = [], $code = 200, $header = [], $options = [])
+ {
+ return Response::create($data, 'xml', $code, $header, $options);
+ }
+}
diff --git a/thinkphp/lang/zh-cn.php b/thinkphp/lang/zh-cn.php
new file mode 100644
index 0000000..dd8084d
--- /dev/null
+++ b/thinkphp/lang/zh-cn.php
@@ -0,0 +1,135 @@
+
+// +----------------------------------------------------------------------
+
+// 核心中文语言包
+return [
+ // 系统错误提示
+ 'Undefined variable' => '未定义变量',
+ 'Undefined index' => '未定义数组索引',
+ 'Undefined offset' => '未定义数组下标',
+ 'Parse error' => '语法解析错误',
+ 'Type error' => '类型错误',
+ 'Fatal error' => '致命错误',
+ 'syntax error' => '语法错误',
+
+ // 框架核心错误提示
+ 'dispatch type not support' => '不支持的调度类型',
+ 'method param miss' => '方法参数错误',
+ 'method not exists' => '方法不存在',
+ 'module not exists' => '模块不存在',
+ 'controller not exists' => '控制器不存在',
+ 'class not exists' => '类不存在',
+ 'property not exists' => '类的属性不存在',
+ 'template not exists' => '模板文件不存在',
+ 'illegal controller name' => '非法的控制器名称',
+ 'illegal action name' => '非法的操作名称',
+ 'url suffix deny' => '禁止的URL后缀访问',
+ 'Route Not Found' => '当前访问路由未定义',
+ 'Undefined db type' => '未定义数据库类型',
+ 'variable type error' => '变量类型错误',
+ 'PSR-4 error' => 'PSR-4 规范错误',
+ 'not support total' => '简洁模式下不能获取数据总数',
+ 'not support last' => '简洁模式下不能获取最后一页',
+ 'error session handler' => '错误的SESSION处理器类',
+ 'not allow php tag' => '模板不允许使用PHP语法',
+ 'not support' => '不支持',
+ 'redisd master' => 'Redisd 主服务器错误',
+ 'redisd slave' => 'Redisd 从服务器错误',
+ 'must run at sae' => '必须在SAE运行',
+ 'memcache init error' => '未开通Memcache服务,请在SAE管理平台初始化Memcache服务',
+ 'KVDB init error' => '没有初始化KVDB,请在SAE管理平台初始化KVDB服务',
+ 'fields not exists' => '数据表字段不存在',
+ 'where express error' => '查询表达式错误',
+ 'no data to update' => '没有任何数据需要更新',
+ 'miss data to insert' => '缺少需要写入的数据',
+ 'miss complex primary data' => '缺少复合主键数据',
+ 'miss update condition' => '缺少更新条件',
+ 'model data Not Found' => '模型数据不存在',
+ 'table data not Found' => '表数据不存在',
+ 'delete without condition' => '没有条件不会执行删除操作',
+ 'miss relation data' => '缺少关联表数据',
+ 'tag attr must' => '模板标签属性必须',
+ 'tag error' => '模板标签错误',
+ 'cache write error' => '缓存写入失败',
+ 'sae mc write error' => 'SAE mc 写入错误',
+ 'route name not exists' => '路由标识不存在(或参数不够)',
+ 'invalid request' => '非法请求',
+ 'bind attr has exists' => '模型的属性已经存在',
+ 'relation data not exists' => '关联数据不存在',
+ 'relation not support' => '关联不支持',
+ 'chunk not support order' => 'Chunk不支持调用order方法',
+
+ // 上传错误信息
+ 'unknown upload error' => '未知上传错误!',
+ 'file write error' => '文件写入失败!',
+ 'upload temp dir not found' => '找不到临时文件夹!',
+ 'no file to uploaded' => '没有文件被上传!',
+ 'only the portion of file is uploaded' => '文件只有部分被上传!',
+ 'upload File size exceeds the maximum value' => '上传文件大小超过了最大值!',
+ 'upload write error' => '文件上传保存错误!',
+ 'has the same filename: {:filename}' => '存在同名文件:{:filename}',
+ 'upload illegal files' => '非法上传文件',
+ 'illegal image files' => '非法图片文件',
+ 'extensions to upload is not allowed' => '上传文件后缀不允许',
+ 'mimetype to upload is not allowed' => '上传文件MIME类型不允许!',
+ 'filesize not match' => '上传文件大小不符!',
+ 'directory {:path} creation failed' => '目录 {:path} 创建失败!',
+
+ // Validate Error Message
+ ':attribute require' => ':attribute不能为空',
+ ':attribute must' => ':attribute必须',
+ ':attribute must be numeric' => ':attribute必须是数字',
+ ':attribute must be integer' => ':attribute必须是整数',
+ ':attribute must be float' => ':attribute必须是浮点数',
+ ':attribute must be bool' => ':attribute必须是布尔值',
+ ':attribute not a valid email address' => ':attribute格式不符',
+ ':attribute not a valid mobile' => ':attribute格式不符',
+ ':attribute must be a array' => ':attribute必须是数组',
+ ':attribute must be yes,on or 1' => ':attribute必须是yes、on或者1',
+ ':attribute not a valid datetime' => ':attribute不是一个有效的日期或时间格式',
+ ':attribute not a valid file' => ':attribute不是有效的上传文件',
+ ':attribute not a valid image' => ':attribute不是有效的图像文件',
+ ':attribute must be alpha' => ':attribute只能是字母',
+ ':attribute must be alpha-numeric' => ':attribute只能是字母和数字',
+ ':attribute must be alpha-numeric, dash, underscore' => ':attribute只能是字母、数字和下划线_及破折号-',
+ ':attribute not a valid domain or ip' => ':attribute不是有效的域名或者IP',
+ ':attribute must be chinese' => ':attribute只能是汉字',
+ ':attribute must be chinese or alpha' => ':attribute只能是汉字、字母',
+ ':attribute must be chinese,alpha-numeric' => ':attribute只能是汉字、字母和数字',
+ ':attribute must be chinese,alpha-numeric,underscore, dash' => ':attribute只能是汉字、字母、数字和下划线_及破折号-',
+ ':attribute not a valid url' => ':attribute不是有效的URL地址',
+ ':attribute not a valid ip' => ':attribute不是有效的IP地址',
+ ':attribute must be dateFormat of :rule' => ':attribute必须使用日期格式 :rule',
+ ':attribute must be in :rule' => ':attribute必须在 :rule 范围内',
+ ':attribute be notin :rule' => ':attribute不能在 :rule 范围内',
+ ':attribute must between :1 - :2' => ':attribute只能在 :1 - :2 之间',
+ ':attribute not between :1 - :2' => ':attribute不能在 :1 - :2 之间',
+ 'size of :attribute must be :rule' => ':attribute长度不符合要求 :rule',
+ 'max size of :attribute must be :rule' => ':attribute长度不能超过 :rule',
+ 'min size of :attribute must be :rule' => ':attribute长度不能小于 :rule',
+ ':attribute cannot be less than :rule' => ':attribute日期不能小于 :rule',
+ ':attribute cannot exceed :rule' => ':attribute日期不能超过 :rule',
+ ':attribute not within :rule' => '不在有效期内 :rule',
+ 'access IP is not allowed' => '不允许的IP访问',
+ 'access IP denied' => '禁止的IP访问',
+ ':attribute out of accord with :2' => ':attribute和确认字段:2不一致',
+ ':attribute cannot be same with :2' => ':attribute和比较字段:2不能相同',
+ ':attribute must greater than or equal :rule' => ':attribute必须大于等于 :rule',
+ ':attribute must greater than :rule' => ':attribute必须大于 :rule',
+ ':attribute must less than or equal :rule' => ':attribute必须小于等于 :rule',
+ ':attribute must less than :rule' => ':attribute必须小于 :rule',
+ ':attribute must equal :rule' => ':attribute必须等于 :rule',
+ ':attribute has exists' => ':attribute已存在',
+ ':attribute not conform to the rules' => ':attribute不符合指定规则',
+ 'invalid Request method' => '无效的请求类型',
+ 'invalid token' => '令牌数据无效',
+ 'not conform to the rules' => '规则错误',
+];
diff --git a/thinkphp/library/think/App.php b/thinkphp/library/think/App.php
new file mode 100644
index 0000000..ad1fefd
--- /dev/null
+++ b/thinkphp/library/think/App.php
@@ -0,0 +1,946 @@
+
+// +----------------------------------------------------------------------
+
+namespace think;
+
+use think\exception\ClassNotFoundException;
+use think\exception\HttpResponseException;
+use think\route\Dispatch;
+
+/**
+ * App 应用管理
+ */
+class App implements \ArrayAccess
+{
+ const VERSION = '5.1.5';
+
+ /**
+ * 当前模块路径
+ * @var string
+ */
+ protected $modulePath;
+
+ /**
+ * 应用调试模式
+ * @var bool
+ */
+ protected $debug = true;
+
+ /**
+ * 应用开始时间
+ * @var float
+ */
+ protected $beginTime;
+
+ /**
+ * 应用内存初始占用
+ * @var integer
+ */
+ protected $beginMem;
+
+ /**
+ * 应用类库命名空间
+ * @var string
+ */
+ protected $namespace = 'app';
+
+ /**
+ * 应用类库后缀
+ * @var bool
+ */
+ protected $suffix = false;
+
+ /**
+ * 严格路由检测
+ * @var bool
+ */
+ protected $routeMust;
+
+ /**
+ * 应用类库目录
+ * @var string
+ */
+ protected $appPath;
+
+ /**
+ * 框架目录
+ * @var string
+ */
+ protected $thinkPath;
+
+ /**
+ * 应用根目录
+ * @var string
+ */
+ protected $rootPath;
+
+ /**
+ * 运行时目录
+ * @var string
+ */
+ protected $runtimePath;
+
+ /**
+ * 配置目录
+ * @var string
+ */
+ protected $configPath;
+
+ /**
+ * 路由目录
+ * @var string
+ */
+ protected $routePath;
+
+ /**
+ * 配置后缀
+ * @var string
+ */
+ protected $configExt;
+
+ /**
+ * 应用调度实例
+ * @var Dispatch
+ */
+ protected $dispatch;
+
+ /**
+ * 容器对象实例
+ * @var Container
+ */
+ protected $container;
+
+ /**
+ * 绑定模块(控制器)
+ * @var string
+ */
+ protected $bind;
+
+ public function __construct($appPath = '')
+ {
+ $this->appPath = $appPath ?: realpath(dirname($_SERVER['SCRIPT_FILENAME']) . '/../application') . '/';
+ $this->container = Container::getInstance();
+ }
+
+ /**
+ * 绑定模块或者控制器
+ * @access public
+ * @param string $bind
+ * @return $this
+ */
+ public function bind($bind)
+ {
+ $this->bind = $bind;
+ return $this;
+ }
+
+ /**
+ * 设置应用类库目录
+ * @access public
+ * @param string $path 路径
+ * @return $this
+ */
+ public function path($path)
+ {
+ $this->appPath = $path;
+ return $this;
+ }
+
+ /**
+ * 初始化应用
+ * @access public
+ * @return void
+ */
+ public function initialize()
+ {
+ //返回当前 Unix 时间戳的微秒数
+ $this->beginTime = microtime(true);
+
+ //返回分配给 PHP 的内存量
+ $this->beginMem = memory_get_usage();
+
+ //函数返回路径中的目录部分
+ // dirname(__DIR__) D:\wamp\www\tp5\thinkphp\library
+ // dirname(dirname(__DIR__)) D:\wamp\www\tp5\thinkphp
+ $this->thinkPath = dirname(dirname(__DIR__)) . '/'; // D:\wamp\www\tp5\thinkphp/
+
+ //realpath() 函数返回绝对路径。
+ // $this->appPath D:\wamp\www\tp5\application/
+ $this->rootPath = dirname(realpath($this->appPath)) . '/'; // D:\wamp\www\tp5/
+ $this->runtimePath = $this->rootPath . 'runtime/'; // D:\wamp\www\tp5/runtime/
+ $this->routePath = $this->rootPath . 'route/'; // D:\wamp\www\tp5/route/
+ $this->configPath = $this->rootPath . 'config/'; // D:\wamp\www\tp5/config/
+
+ // 设置路径环境变量
+ //$this->env think\Env
+ $this->env->set([
+ 'think_path' => $this->thinkPath, // D:\wamp\www\tp5\thinkphp/
+ 'root_path' => $this->rootPath, // D:\wamp\www\tp5/
+ 'app_path' => $this->appPath, // D:\wamp\www\tp5\application/ 应用所在的文件夹
+ 'config_path' => $this->configPath, // D:\wamp\www\tp5/config/
+ 'route_path' => $this->routePath, // D:\wamp\www\tp5/route/
+ 'runtime_path' => $this->runtimePath, // D:\wamp\www\tp5/runtime/
+ 'extend_path' => $this->rootPath . 'extend/', // D:\wamp\www\tp5/extend/
+ 'vendor_path' => $this->rootPath . 'vendor/', // D:\wamp\www\tp5/vendor/
+ ]);
+
+ // 加载环境变量配置文件
+ // is_file() 函数检查指定的文件名是否存在 文件存在则返回 true。
+ if (is_file($this->rootPath . '.env')) {
+ // 获取.env的配置信息 内容格式为.ini语法
+ $this->env->load($this->rootPath . '.env');
+ }
+
+ $this->namespace = $this->env->get('app_namespace', $this->namespace); //返回app // $this->namespace
+
+ $this->env->set('app_namespace', $this->namespace);
+
+ // 注册应用命名空间 $this->appPath [指定应用所在的文件夹 D:\wamp\www\tp5\application/]
+ Loader::addNamespace($this->namespace, $this->appPath);
+
+ // 配置后缀
+ $this->configExt = $this->env->get('config_ext', '.php');
+
+ // 初始化应用
+ $this->init();
+
+ // 开启类名后缀 实际是查看config 内 app内的 class_suffix 值,默认为false
+ $this->suffix = $this->config('app.class_suffix');
+
+ // 应用调试模式
+ // 如果app_debug 没有设置 则启用 $this->config('app.app_debug')的值 默认为false
+ $this->debug = $this->env->get('app_debug', $this->config('app.app_debug'));
+ //获取的值设置为 app_debug 的值给予下次调用
+ $this->env->set('app_debug', $this->debug);
+
+ if (!$this->debug) {
+ // 非调试模式 关闭(Off)错误
+ ini_set('display_errors', 'Off');
+ } elseif (PHP_SAPI != 'cli') {
+ //开启调试后切非cli格式 执行
+ //重新申请一块比较大的buffer
+ if (ob_get_level() > 0) {
+ $output = ob_get_clean();
+ }
+ ob_start();
+ if (!empty($output)) {
+ echo $output;
+ }
+ }
+
+ // 注册根命名空间
+ // root_namespace 默认为 空数组
+ if (!empty($this->config('app.root_namespace'))) {
+ //等于非空数组时执行
+ Loader::addNamespace($this->config('app.root_namespace'));
+ }
+
+ // 注册类库别名
+ // alias 主页为空
+ Loader::addClassAlias($this->config->pull('alias'));
+
+ // 设置系统时区
+ date_default_timezone_set($this->config('app.default_timezone'));
+
+ // 监听app_init
+ $this->hook->listen('app_init',['ceshi','TESTT']);
+ }
+
+ /**
+ * 初始化应用或模块
+ * @access public
+ * @param string $module 模块名
+ * @return void
+ */
+ public function init($module = '')
+ {
+ // 定位模块目录文件名,指定当前模块的文件夹名称
+ $module = $module ? $module . DIRECTORY_SEPARATOR : '';
+
+ //指定当前模块的文件夹目录
+ $path = $this->appPath . $module;
+
+ // 加载初始化文件
+ // 检测init.php 是否存在
+ if (is_file($path . 'init.php')) {
+ include $path . 'init.php';
+ //检测根目录下的是否存在 D:\wamp\www\tp5/runtime/
+ } elseif (is_file($this->runtimePath . $module . 'init.php')) {
+ include $this->runtimePath . $module . 'init.php';
+ } else {
+ // 加载行为扩展文件
+ if (is_file($path . 'tags.php')) {
+ // $this->hook think\Hook
+ // 注册钩子
+ $this->hook->import(include $path . 'tags.php');
+ }
+
+ // 加载application下的 common.php 公共文件
+ if (is_file($path . 'common.php')) {
+ include $path . 'common.php';
+ }
+
+ //$module 等于空 加载系统助手函数
+ if ('' == $module) {
+ // 加载系统助手函数 D:\wamp\www\tp5\thinkphp/
+ include $this->thinkPath . 'helper.php';
+ }
+
+ // 注册服务的容器对象实例
+ if (is_file($path . 'provider.php')) {
+ $this->container->bind(include $path . 'provider.php');
+ }
+
+ // 自动读取配置文件
+ //模块下的配置文件夹不存在就加载 D:\wamp\www\tp5/config/ 内的
+ if (is_dir($path . 'config')) {
+ $dir = $path . 'config';
+ } elseif (is_dir($this->configPath . $module)) {
+ $dir = $this->configPath . $module;
+ }
+
+ // scandir($dir) 列出 $dir 目录中的文件和目录
+ $files = isset($dir) ? scandir($dir) : [];
+
+ //循环去掉一切不需要的值
+ foreach ($files as $file) {
+ if ('.' . pathinfo($file, PATHINFO_EXTENSION) === $this->configExt) {
+ $filename = $dir . DIRECTORY_SEPARATOR . $file;
+ //加载所有的配置文件
+ // $this->config think\Config
+ $this->config->load($filename, pathinfo($file, PATHINFO_FILENAME));
+ }
+ }
+ }
+
+ // $this->request think\Request
+ // 全局过滤方法 default_filter 实际是 app 键值内的 default_filter 值
+ $this->request->filter($this->config('app.default_filter'));
+ }
+
+ /**
+ * 执行应用程序
+ * @access public
+ * @return Response
+ * @throws Exception
+ */
+ public function run()
+ {
+ // 初始化应用,初步完成注释
+ $this->initialize();
+
+ try {
+ if ($this->bind) {
+ // 模块/控制器绑定
+ // $this->route think\Route
+ $this->route->bind($this->bind);
+ } elseif ($this->config('app.auto_bind_module')) {
+ // 入口自动绑定模块 app.auto_bind_module 默认是false
+ // 入口自动绑定
+ $name = pathinfo($this->request->baseFile(), PATHINFO_FILENAME);
+ if ($name && 'index' != $name && is_dir($this->appPath . $name)) {
+ $this->route->bind($name);
+ }
+ }
+
+ // 读取默认语言
+ // app.default_lang 默认为 zh-cn
+ // $this->lang think\Lang
+ // 设置当前的语言
+ $this->lang->range($this->config('app.default_lang'));
+ //判断是否开启了多语言,默认是false
+ if ($this->config('app.lang_switch_on')) {
+ // 开启多语言机制 检测当前语言
+ $this->lang->detect();
+ }
+
+ // $this->request think\Request
+ // $this->lang->range() 获取当前的语言
+ // 设置当前的语言
+ $this->request->langset($this->lang->range());
+
+ // 加载系统语言包
+ $this->lang->load([
+ $this->thinkPath . 'lang/' . $this->request->langset() . '.php',
+ $this->appPath . 'lang/' . $this->request->langset() . '.php',
+ ]);
+
+ // 监听app_dispatch
+ $this->hook->listen('app_dispatch');
+
+ // 获取应用调度信息
+ $dispatch = $this->dispatch;
+ if (empty($dispatch)) {
+ //$dispatch 为空时执行
+ // 进行URL路由检测
+ // 主页返回的 think\route\dispatch\Url 实例
+ // 在这里也或许会返回404
+ $dispatch = $this->routeCheck();
+ }
+
+ // 记录当前调度信息 设置或者获取当前请求的调度信息
+ $this->request->dispatch($dispatch);
+
+ // 记录路由和请求信息
+ if ($this->debug) {
+ $this->log('[ ROUTE ] ' . var_export($this->request->routeInfo(), true));
+ $this->log('[ HEADER ] ' . var_export($this->request->header(), true));
+ $this->log('[ PARAM ] ' . var_export($this->request->param(), true));
+ }
+
+ // 监听app_begin
+ $this->hook->listen('app_begin');
+
+ // 请求缓存检查
+ $this->request->cache(
+ $this->config('app.request_cache'),
+ $this->config('app.request_cache_expire'),
+ $this->config('app.request_cache_except')
+ );
+
+ // 执行调度
+ // think\route\dispatch\Url 内的 run()
+ $data = $dispatch->run();
+ var_dump($data);
+
+// EXIT;
+
+ } catch (HttpResponseException $exception) {
+ $data = $exception->getResponse();
+ }
+
+ $this->middlewareDispatcher->add(function (Request $request, $next) use ($data) {
+ // 输出数据到客户端
+ if ($data instanceof Response) {
+ $response = $data;
+ } elseif (!is_null($data)) {
+ // 默认自动识别响应输出类型
+ $isAjax = $request->isAjax();
+ $type = $isAjax ? $this->config('app.default_ajax_return') : $this->config('app.default_return_type');
+
+ $response = Response::create($data, $type);
+ } else {
+ $response = Response::create();
+ }
+ return $response;
+ });
+
+ $response = $this->middlewareDispatcher->dispatch($this->request);
+
+ // 监听app_end
+ $this->hook->listen('app_end', $response);
+
+ return $response;
+ }
+
+ /**
+ * 设置当前请求的调度信息
+ * @access public
+ * @param Dispatch $dispatch 调度信息
+ * @return $this
+ */
+ public function dispatch(Dispatch $dispatch)
+ {
+ $this->dispatch = $dispatch;
+ return $this;
+ }
+
+ /**
+ * 记录调试信息
+ * @access public
+ * @param mixed $msg 调试信息
+ * @param string $type 信息类型
+ * @return void
+ */
+ public function log($log, $type = 'info')
+ {
+ $this->debug && $this->log->record($log, $type);
+ }
+
+ /**
+ * 获取配置参数 为空则获取所有配置
+ * @access public
+ * @param string $name 配置参数名(支持二级配置 .号分割)
+ * @return mixed
+ */
+ public function config($name = '')
+ {
+ return $this->config->get($name);
+ }
+
+ /**
+ * URL路由检测(根据PATH_INFO)
+ * @access public
+ * @return Dispatch
+ */
+ public function routeCheck()
+ {
+ // 获取当前请求URL的pathinfo信息(不含URL后缀 如:.html)
+ $path = $this->request->path();
+ // pathinfo_depr 为 pathinfo分隔符,默认为'/'
+ $depr = $this->config('app.pathinfo_depr');
+
+ // 路由检测
+ $files = scandir($this->routePath); // D:\wamp\www\tp5/route/
+ foreach ($files as $file) {
+ if (strpos($file, '.php')) {
+ $filename = $this->routePath . $file;
+ var_dump($filename);
+ // 导入路由配置
+ $rules = include $filename;
+ // is_array() 检测变量是否是数组
+ if (is_array($rules)) {
+ $this->route->import($rules);
+
+ }
+ }
+ }
+ $this->route->routeinfo();
+// exit;
+
+ // app.route_annotation 使用注解路由 默认false
+ // 这个模式可以放弃使用
+ if ($this->config('app.route_annotation')) {
+ // 自动生成路由定义
+ if ($this->debug) {
+ $this->build->buildRoute($this->config('app.controller_suffix'));
+ }
+
+ $filename = $this->runtimePath . 'build_route.php';
+
+ if (is_file($filename)) {
+ include $filename;
+ }
+ }
+
+ // 是否强制路由模式
+ // 等于false 则使用
+ // $this->routeMust 默认为空 is_null($this->routeMust) 为 true
+ // $this->routeMust 默认为空
+ // app.url_route_must 是否强制使用路由 默认为false
+ $must = !is_null($this->routeMust) ? $this->routeMust : $this->config('app.url_route_must');
+ // $must 值为false
+
+ // 路由检测 返回一个Dispatch对象
+
+ // $path 请求URL 不含后缀(.HTML) 不含域名
+ // URL分隔符 默认为/
+ // $must 是否强制路由模式 默认值为false
+ // app.rote_complete_match 路由是否完全匹配 默认为false
+ return $this->route->check($path, $depr, $must, $this->config('app.route_complete_match'));
+ }
+
+ /**
+ * 设置应用的路由检测机制
+ * @access public
+ * @param bool $must 是否强制检测路由
+ * @return $this
+ */
+ public function routeMust($must = false)
+ {
+ $this->routeMust = $must;
+ return $this;
+ }
+
+ /**
+ * 解析模块和类名
+ * @access protected
+ * @param string $name 资源地址
+ * @param string $layer 验证层名称
+ * @param bool $appendSuffix 是否添加类名后缀
+ * @return array
+ */
+ protected function parseModuleAndClass($name, $layer, $appendSuffix)
+ {
+ if (false !== strpos($name, '\\')) {
+ $class = $name;
+ $module = $this->request->module();
+ } else {
+ if (strpos($name, '/')) {
+ list($module, $name) = explode('/', $name, 2);
+ } else {
+ $module = $this->request->module();
+ }
+
+ $class = $this->parseClass($module, $layer, $name, $appendSuffix);
+ }
+
+ return [$module, $class];
+ }
+
+ /**
+ * 实例化应用类库
+ * @access public
+ * @param string $name 类名称
+ * @param string $layer 业务层名称
+ * @param bool $appendSuffix 是否添加类名后缀
+ * @param string $common 公共模块名
+ * @return object
+ * @throws ClassNotFoundException
+ */
+ public function create($name, $layer, $appendSuffix = false, $common = 'common')
+ {
+ $guid = $name . $layer;
+
+ if ($this->__isset($guid)) {
+ return $this->__get($guid);
+ }
+
+ list($module, $class) = $this->parseModuleAndClass($name, $layer, $appendSuffix);
+
+ if (class_exists($class)) {
+ $object = $this->__get($class);
+ } else {
+ $class = str_replace('\\' . $module . '\\', '\\' . $common . '\\', $class);
+ if (class_exists($class)) {
+ $object = $this->__get($class);
+ } else {
+ throw new ClassNotFoundException('class not exists:' . $class, $class);
+ }
+ }
+
+ $this->__set($guid, $class);
+
+ return $object;
+ }
+
+ /**
+ * 实例化(分层)模型
+ * @access public
+ * @param string $name Model名称
+ * @param string $layer 业务层名称
+ * @param bool $appendSuffix 是否添加类名后缀
+ * @param string $common 公共模块名
+ * @return Model
+ * @throws ClassNotFoundException
+ */
+ public function model($name = '', $layer = 'model', $appendSuffix = false, $common = 'common')
+ {
+ return $this->create($name, $layer, $appendSuffix, $common);
+ }
+
+ /**
+ * 实例化(分层)控制器 格式:[模块名/]控制器名
+ * @access public
+ * @param string $name 资源地址
+ * @param string $layer 控制层名称
+ * @param bool $appendSuffix 是否添加类名后缀
+ * @param string $empty 空控制器名称
+ * @return object
+ * @throws ClassNotFoundException
+ */
+ public function controller($name, $layer = 'controller', $appendSuffix = false, $empty = '')
+ {
+ list($module, $class) = $this->parseModuleAndClass($name, $layer, $appendSuffix);
+
+ if (class_exists($class)) {
+ return $this->__get($class);
+ } elseif ($empty && class_exists($emptyClass = $this->parseClass($module, $layer, $empty, $appendSuffix))) {
+ return $this->__get($emptyClass);
+ } else {
+ throw new ClassNotFoundException('class not exists:' . $class, $class);
+ }
+ }
+
+ /**
+ * 实例化验证类 格式:[模块名/]验证器名
+ * @access public
+ * @param string $name 资源地址
+ * @param string $layer 验证层名称
+ * @param bool $appendSuffix 是否添加类名后缀
+ * @param string $common 公共模块名
+ * @return Validate
+ * @throws ClassNotFoundException
+ */
+ public function validate($name = '', $layer = 'validate', $appendSuffix = false, $common = 'common')
+ {
+ $name = $name ?: $this->config('default_validate');
+
+ if (empty($name)) {
+ return new Validate;
+ }
+
+ return $this->create($name, $layer, $appendSuffix, $common);
+ }
+
+ /**
+ * 数据库初始化
+ * @access public
+ * @param mixed $config 数据库配置
+ * @param bool|string $name 连接标识 true 强制重新连接
+ * @return \think\db\Query
+ */
+ public function db($config = [], $name = false)
+ {
+ return Db::connect($config, $name);
+ }
+
+ /**
+ * 远程调用模块的操作方法 参数格式 [模块/控制器/]操作
+ * @access public
+ * @param string $url 调用地址
+ * @param string|array $vars 调用参数 支持字符串和数组
+ * @param string $layer 要调用的控制层名称
+ * @param bool $appendSuffix 是否添加类名后缀
+ * @return mixed
+ * @throws ClassNotFoundException
+ */
+ public function action($url, $vars = [], $layer = 'controller', $appendSuffix = false)
+ {
+ $info = pathinfo($url);
+ $action = $info['basename'];
+ $module = '.' != $info['dirname'] ? $info['dirname'] : $this->request->controller();
+ $class = $this->controller($module, $layer, $appendSuffix);
+
+ if (is_scalar($vars)) {
+ if (strpos($vars, '=')) {
+ parse_str($vars, $vars);
+ } else {
+ $vars = [$vars];
+ }
+ }
+
+ return $this->container->invokeMethod([$class, $action . $this->config('action_suffix')], $vars);
+ }
+
+ /**
+ * 解析应用类的类名
+ * @access public
+ * @param string $module 模块名
+ * @param string $layer 层名 controller model ...
+ * @param string $name 类名
+ * @param bool $appendSuffix
+ * @return string
+ */
+ public function parseClass($module, $layer, $name, $appendSuffix = false)
+ {
+ $name = str_replace(['/', '.'], '\\', $name);
+ $array = explode('\\', $name);
+ $class = Loader::parseName(array_pop($array), 1) . ($this->suffix || $appendSuffix ? ucfirst($layer) : '');
+ $path = $array ? implode('\\', $array) . '\\' : '';
+
+ return $this->namespace . '\\' . ($module ? $module . '\\' : '') . $layer . '\\' . $path . $class;
+ }
+
+ /**
+ * 获取框架版本
+ * @access public
+ * @return string
+ */
+ public function version()
+ {
+ return static::VERSION;
+ }
+
+ /**
+ * 是否为调试模式
+ * @access public
+ * @return bool
+ */
+ public function isDebug()
+ {
+ return $this->debug;
+ }
+
+ /**
+ * 获取模块路径
+ * @access public
+ * @return string
+ */
+ public function getModulePath()
+ {
+ return $this->modulePath;
+ }
+
+ /**
+ * 设置模块路径
+ * @access public
+ * @param string $path 路径
+ * @return void
+ */
+ public function setModulePath($path)
+ {
+ $this->modulePath = $path;
+ $this->env->set('module_path', $path);
+ }
+
+ /**
+ * 获取应用根目录
+ * @access public
+ * @return string
+ */
+ public function getRootPath()
+ {
+ return $this->rootPath;
+ }
+
+ /**
+ * 获取应用类库目录
+ * @access public
+ * @return string
+ */
+ public function getAppPath()
+ {
+ return $this->appPath;
+ }
+
+ /**
+ * 获取应用运行时目录
+ * @access public
+ * @return string
+ */
+ public function getRuntimePath()
+ {
+ return $this->runtimePath;
+ }
+
+ /**
+ * 获取核心框架目录
+ * @access public
+ * @return string
+ */
+ public function getThinkPath()
+ {
+ return $this->thinkPath;
+ }
+
+ /**
+ * 获取路由目录
+ * @access public
+ * @return string
+ */
+ public function getRoutePath()
+ {
+ return $this->routePath;
+ }
+
+ /**
+ * 获取应用配置目录
+ * @access public
+ * @return string
+ */
+ public function getConfigPath()
+ {
+ return $this->configPath;
+ }
+
+ /**
+ * 获取配置后缀
+ * @access public
+ * @return string
+ */
+ public function getConfigExt()
+ {
+ return $this->configExt;
+ }
+
+ /**
+ * 获取应用类库命名空间
+ * @access public
+ * @return string
+ */
+ public function getNamespace()
+ {
+ return $this->namespace;
+ }
+
+ /**
+ * 设置应用类库命名空间
+ * @access public
+ * @param string $namespace 命名空间名称
+ * @return $this
+ */
+ public function setNamespace($namespace)
+ {
+ $this->namespace = $namespace;
+ return $this;
+ }
+
+ /**
+ * 是否启用类库后缀
+ * @access public
+ * @return bool
+ */
+ public function getSuffix()
+ {
+ return $this->suffix;
+ }
+
+ /**
+ * 获取应用开启时间
+ * @access public
+ * @return float
+ */
+ public function getBeginTime()
+ {
+ return $this->beginTime;
+ }
+
+ /**
+ * 获取应用初始内存占用
+ * @access public
+ * @return integer
+ */
+ public function getBeginMem()
+ {
+ return $this->beginMem;
+ }
+
+ /**
+ * 获取容器实例
+ * @access public
+ * @return Container
+ */
+ public function container()
+ {
+ return $this->container;
+ }
+
+ public function __set($name, $value)
+ {
+ $this->container->bind($name, $value);
+ }
+
+ public function __get($name)
+ {
+ return $this->container->make($name);
+ }
+
+ public function __isset($name)
+ {
+ return $this->container->bound($name);
+ }
+
+ public function __unset($name)
+ {
+ $this->container->__unset($name);
+ }
+
+ public function offsetExists($key)
+ {
+ return $this->__isset($key);
+ }
+
+ public function offsetGet($key)
+ {
+ return $this->__get($key);
+ }
+
+ public function offsetSet($key, $value)
+ {
+ $this->__set($key, $value);
+ }
+
+ public function offsetUnset($key)
+ {
+ $this->__unset($key);
+ }
+}
diff --git a/thinkphp/library/think/Build.php b/thinkphp/library/think/Build.php
new file mode 100644
index 0000000..decfc12
--- /dev/null
+++ b/thinkphp/library/think/Build.php
@@ -0,0 +1,376 @@
+
+// +----------------------------------------------------------------------
+
+namespace think;
+
+class Build
+{
+ /**
+ * 应用对象
+ * @var App
+ */
+ protected $app;
+
+ /**
+ * 应用目录
+ * @var string
+ */
+ protected $basePath;
+
+ public function __construct(App $app)
+ {
+ $this->app = $app;
+ $this->basePath = $this->app->getAppPath();
+ }
+
+ /**
+ * 根据传入的build资料创建目录和文件
+ * @access public
+ * @param array $build build列表
+ * @param string $namespace 应用类库命名空间
+ * @param bool $suffix 类库后缀
+ * @return void
+ */
+ public function run(array $build = [], $namespace = 'app', $suffix = false)
+ {
+ // 锁定
+ $lockfile = $this->basePath . 'build.lock';
+
+ if (is_writable($lockfile)) {
+ return;
+ } elseif (!touch($lockfile)) {
+ throw new Exception('应用目录[' . $this->basePath . ']不可写,目录无法自动生成!' . $label . $output . ''; + } + if ($echo) { + echo($output); + return; + } else { + return $output; + } + } + + public function inject(Response $response, &$content) + { + $config = $this->app['config']->pull('trace'); + $type = isset($config['type']) ? $config['type'] : 'Html'; + $class = false !== strpos($type, '\\') ? $type : '\\think\\debug\\' . ucwords($type); + unset($config['type']); + + if (class_exists($class)) { + $trace = new $class($config); + } else { + throw new ClassNotFoundException('class not exists:' . $class, $class); + } + + if ($response instanceof Redirect) { + //TODO 记录 + } else { + $output = $trace->output($response, $this->app['log']->getLog()); + if (is_string($output)) { + // trace调试信息注入 + $pos = strripos($content, '