This commit is contained in:
IQ 2019-04-13 14:06:05 +08:00
parent 166dd48921
commit 35351c49d5
231 changed files with 226 additions and 47598 deletions

9
.gitignore vendored
View File

@ -1,5 +1,6 @@
.idea
composer.lock
/.idea
/.vscode
/vendor
*.log
nbproject
.git
thinkphp
.env

143
README.md
View File

@ -1,144 +1,23 @@
ThinkPHP 5.1
ThinkPHP 6.0
===============
ThinkPHP5.1对底层架构做了进一步的改进,减少依赖,其主要特性包括:
+ 采用容器统一管理对象
+ 支持Facade
+ 注解路由支持
+ 路由跨域请求支持
+ 配置和路由目录独立
+ 取消系统常量
+ 助手函数增强
+ 类库别名机制
+ 增加条件查询
+ 改进查询机制
+ 配置采用二级
+ 依赖注入完善
> 运行环境要求PHP7.1+。
> 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 命令行入口文件
composer create-project topthink/think tp 6.0.*-dev
~~~
> 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`字段,不建议使用驼峰和中文作为数据表字段命名。
如果需要更新框架使用
~~~
composer update topthink/framework
~~~
## 参与开发
请参阅 [ThinkPHP5 核心框架包](https://github.com/top-think/framework)。
请参阅 [ThinkPHP 核心框架包](https://github.com/top-think/framework)。
## 版权信息
@ -146,7 +25,7 @@ ThinkPHP遵循Apache2开源协议发布并提供免费使用。
本项目包含的第三方源码和二进制文件之版权信息另行标注。
版权所有Copyright © 2006-2018 by ThinkPHP (http://thinkphp.cn)
版权所有Copyright © 2006-2019 by ThinkPHP (http://thinkphp.cn)
All rights reserved。

15
app/controller/Index.php Normal file
View File

@ -0,0 +1,15 @@
<?php
namespace app\controller;
class Index
{
public function index()
{
return '<style type="text/css">*{ 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 }</style><div style="padding: 24px 48px;"> <h1>:) </h1><p> ThinkPHP V6<br/><span style="font-size:30px">13载初心不改 - 你值得信赖的PHP框架</span></p></div><script type="text/javascript" src="https://tajs.qq.com/stats?sId=64890268" charset="UTF-8"></script><script type="text/javascript" src="https://e.topthink.com/Public/static/client.js"></script><think id="eab4b9f840753f8e7"></think>';
}
public function hello($name = 'ThinkPHP6')
{
return 'hello,' . $name;
}
}

View File

@ -9,14 +9,19 @@
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
//Route::get('think', function () {
// return 'hello,ThinkPHP5!';
//});
Route::get('hello/:name', 'index/hello');
Route::get('news', 'news/test/hello');
// 事件定义文件
return [
'bind' => [
],
'listen' => [
'AppInit' => [],
'AppBegin' => [],
'AppEnd' => [],
'LogLevel' => [],
'LogWrite' => [],
'ResponseSend' => [],
'ResponseEnd' => [],
],
'subscribe' => [
],
];

8
app/middleware.php Normal file
View File

@ -0,0 +1,8 @@
<?php
return [
'think\middleware\CheckRequestCache',
'think\middleware\LoadLangPack',
'think\middleware\SessionInit',
'think\middleware\TraceDebug',
];

View File

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

View File

@ -1,23 +0,0 @@
<?php
namespace app\index\behavior;
class Test
{
//这个是会执行的
public function __construct() {
echo '初始化<BR />';
}
//若位置名称对应的方法不存在,则执行这个
public function run($params)
{
echo 'run参数'.$params;
}
//根据执行的位置名称,方法名 对应位置名称,若存在下划线将去掉下划线
public function appInit($params)
{
echo 'appInit参数';
}
}

View File

@ -1,15 +0,0 @@
<?php
namespace app\index\controller;
class Index
{
public function index()
{
return '<style type="text/css">*{ 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 }</style><div style="padding: 24px 48px;"> <h1>:) 2018新年快乐</h1><p> ThinkPHP V5.1<br/><span style="font-size:30px">12载初心不改2006-2018 - 你值得信赖的PHP框架</span></p></div><script type="text/javascript" src="https://tajs.qq.com/stats?sId=64890268" charset="UTF-8"></script><script type="text/javascript" src="https://e.topthink.com/Public/static/client.js"></script><think id="eab4b9f840753f8e7"></think>';
}
public function hello($name = 'ThinkPHP5')
{
return 'hello,' . $name;
}
}

View File

@ -1,15 +0,0 @@
<?php
namespace app\news\controller;
class Index
{
public function index()
{
return 'news/INDEX';
}
public function hello($name = 'ThinkPHP5')
{
return 'hello,' . $name;
}
}

View File

@ -1,15 +0,0 @@
<?php
namespace app\news\controller;
class Test
{
public function index()
{
return 'TestIndex';
}
public function hello($name = 'ThinkPHP6')
{
return 'TestHello,' . $name;
}
}

View File

@ -1,31 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 应用行为扩展定义文件
return [
// 应用初始化
'app_init' => [
// function($ddd){echo 'app_init闭包函数<BR />'.$ddd[0].'<BR />'.$ddd[1].'<BR />';},
// 'app\\index\\behavior\\test'
],
// 应用开始
'app_begin' => [],
// 模块初始化
'module_init' => [],
// 操作开始执行
'action_begin' => [],
// 视图内容过滤
'view_filter' => [],
// 日志写入
'log_write' => [],
// 应用结束
'app_end' => [],
];

View File

@ -16,18 +16,25 @@
}
],
"require": {
"php": ">=5.6.0",
"topthink/framework": "5.1.*"
"php": ">=7.1.0",
"topthink/framework": "6.0.*-dev",
"topthink/think-view": "^1.0"
},
"autoload": {
"psr-4": {
"app\\": "application"
}
"app\\": "app"
},
"extra": {
"think-path": "thinkphp"
"psr-0": {
"": "extend/"
}
},
"config": {
"preferred-install": "dist"
},
"scripts": {
"post-autoload-dump": [
"@php think service:discover",
"@php think vendor:publish"
]
}
}

View File

@ -14,125 +14,42 @@
// +----------------------------------------------------------------------
return [
// 应用名称
'app_name' => '',
// 应用地址
'app_host' => '',
// 应用调试模式
'app_debug' => false,
// 应用Trace
// 应用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',
// 应用的命名空间
'app_namespace' => '',
// 是否启用路由
'with_route' => true,
// 是否启用事件
'with_event' => true,
// 自动多应用模式
'auto_multi_app' => false,
// 应用映射(自动多应用模式有效)
'app_map' => [],
// 域名绑定(自动多应用模式有效)
'domain_bind' => [],
// 默认应用
'default_app' => 'index',
// 默认时区
'default_timezone' => 'PRC',
'default_timezone' => 'Asia/Shanghai',
// 是否开启多语言
'lang_switch_on' => false,
// 默认全局过滤方法 用逗号分隔多个
'default_filter' => '',
// 默认语言
'default_lang' => 'zh-cn',
// 应用类库后缀
'class_suffix' => false,
// 控制器类后缀
'controller_suffix' => false,
// +----------------------------------------------------------------------
// | 模块设置
// +----------------------------------------------------------------------
// 默认模块名
'default_module' => 'index',
// 禁止访问模块
'deny_module_list' => ['common'],
// 默认控制器名
'default_controller' => 'Index',
// 默认操作名
'default_action' => 'index',
// 默认验证器
'default_validate' => '',
// 默认的空模块名
'empty_module' => '',
// 默认的空控制器名
'empty_controller' => 'Error',
// 操作方法前缀
'use_action_prefix' => false,
// 操作方法后缀
'action_suffix' => '',
// 自动搜索控制器
'controller_auto_search' => false,
// +----------------------------------------------------------------------
// | URL设置
// +----------------------------------------------------------------------
// PATHINFO变量名 用于兼容模式
'var_pathinfo' => 's',
// 兼容PATH_INFO获取
'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
// pathinfo分隔符
'pathinfo_depr' => '/',
// HTTPS代理标识
'https_agent_name' => '',
// URL伪静态后缀
'url_html_suffix' => 'html',
// URL普通方式参数 用于自动生成
'url_common_param' => false,
// URL参数方式 0 按名称成对解析 1 按顺序解析
'url_param_type' => 0,
// 是否开启路由延迟解析
'url_lazy_route' => false,
// 是否强制使用路由
'url_route_must' => true,
// 路由是否完全匹配
'route_complete_match' => false,
// 使用注解路由
'route_annotation' => false,
// 域名根如thinkphp.cn
'url_domain_root' => 'www.a.com',
// 是否自动转换URL中的控制器和操作名
'url_convert' => true,
// 默认的访问控制器层
'url_controller_layer' => 'controller',
// 表单请求类型伪装变量
'var_method' => '_method',
// 表单ajax伪装变量
'var_ajax' => '_ajax',
// 表单pjax伪装变量
'var_pjax' => '_pjax',
// 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
'request_cache' => true,
// 请求缓存有效期
'request_cache_expire' => null,
// 全局请求缓存排除规则
'request_cache_except' => [],
// 默认跳转页面对应的模板文件
'dispatch_success_tmpl' => Env::get('think_path') . 'tpl/dispatch_jump.tpl',
'dispatch_error_tmpl' => Env::get('think_path') . 'tpl/dispatch_jump.tpl',
'dispatch_success_tmpl' => app()->getThinkPath() . 'tpl/dispatch_jump.tpl',
'dispatch_error_tmpl' => app()->getThinkPath() . 'tpl/dispatch_jump.tpl',
// 异常页面的模板文件
'exception_tmpl' => Env::get('think_path') . 'tpl/think_exception.tpl',
'exception_tmpl' => app()->getThinkPath() . 'tpl/think_exception.tpl',
// 错误显示信息,非调试模式有效
'error_message' => '页面错误!请稍后再试~',
// 显示错误信息
'show_error_msg' => false,
// 异常处理handle类 留空使用 \think\exception\Handle
'exception_handle' => '',
];

View File

@ -9,8 +9,13 @@
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | 控制台配置
// +----------------------------------------------------------------------
return [
'test' => [
'news/test/index',[]
]
// 执行用户Windows下无效
'user' => null,
// 指令定义
'commands' => [
],
];

View File

@ -24,7 +24,7 @@ return [
// cookie 启用安全传输
'secure' => false,
// httponly设置
'httponly' => '',
'httponly' => false,
// 是否使用 setcookie
'setcookie' => true,
];

View File

@ -50,6 +50,12 @@ return [
'datetime_format' => 'Y-m-d H:i:s',
// 是否需要进行SQL性能分析
'sql_explain' => false,
// Builder类
'builder' => '',
// Query类
'query' => '\\think\\db\\Query',
// 是否需要断线重连
'break_reconnect' => false,
// 断线标识字符串
'break_match_str' => [],
];

View File

@ -19,4 +19,12 @@ return [
'path' => '',
// 日志记录级别
'level' => [],
// 单文件日志写入
'single' => false,
// 独立日志级别
'apart_level' => [],
// 最大日志文件数量
'max_files' => 0,
// 是否关闭日志写入
'close' => false,
];

79
config/route.php Normal file
View File

@ -0,0 +1,79 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | 应用设置
// +----------------------------------------------------------------------
return [
// 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_lazy_route' => false,
// 是否强制使用路由
'url_route_must' => false,
// 合并路由规则
'route_rule_merge' => false,
// 路由是否完全匹配
'route_complete_match' => false,
// 使用注解路由
'route_annotation' => false,
// 是否开启路由缓存
'route_check_cache' => false,
// 路由缓存连接参数
'route_cache_option' => [],
// 路由缓存Key
'route_check_cache_key' => '',
// 访问控制器层名称
'controller_layer' => 'controller',
// 空控制器名
'empty_controller' => 'Error',
// 是否使用控制器后缀
'controller_suffix' => false,
// 默认的路由变量规则
'default_route_pattern' => '[\w\.]+',
// 域名根如thinkphp.cn
'url_domain_root' => '',
// 是否自动转换URL中的控制器和操作名
'url_convert' => true,
// 表单请求类型伪装变量
'var_method' => '_method',
// 表单ajax伪装变量
'var_ajax' => '_ajax',
// 表单pjax伪装变量
'var_pjax' => '_pjax',
// 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
'request_cache' => false,
// 请求缓存有效期
'request_cache_expire' => null,
// 全局请求缓存排除规则
'request_cache_except' => [],
// 默认控制器名
'default_controller' => 'Index',
// 默认操作名
'default_action' => 'index',
// 操作方法后缀
'action_suffix' => '',
// 默认JSONP格式返回的处理方法
'default_jsonp_handler' => 'jsonpReturn',
// 默认JSONP处理方法
'var_jsonp_handler' => 'callback',
];

View File

@ -17,10 +17,11 @@ return [
'id' => '',
// SESSION_ID的提交变量,解决flash上传跨域
'var_session_id' => '',
// SESSION 前缀
'prefix' => 'think',
// 驱动方式 支持redis memcache memcached
'type' => '',
// 是否自动开启 SESSION
'auto_start' => true,
// Session配置参数
'options' => [
],
];

View File

@ -1,33 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | 模板设置
// +----------------------------------------------------------------------
return [
// 模板引擎类型 支持 php think 支持扩展
'type' => 'Think',
// 模板路径
'view_path' => '',
// 模板后缀
'view_suffix' => 'html',
// 模板文件名分隔符
'view_depr' => DIRECTORY_SEPARATOR,
// 模板引擎普通标签开始标记
'tpl_begin' => '{',
// 模板引擎普通标签结束标记
'tpl_end' => '}',
// 标签库标签开始标记
'taglib_begin' => '{',
// 标签库标签结束标记
'taglib_end' => '}',
];

View File

@ -0,0 +1,7 @@
include.path=${php.global.include.path}
php.version=PHP_56
source.encoding=UTF-8
src.dir=.
tags.asp=false
tags.short=false
web.root=.

9
nbproject/project.xml Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.php.project</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/php-project/1">
<name>thinkphp</name>
</data>
</configuration>
</project>

View File

@ -12,75 +12,13 @@
// [ 应用入口文件 ]
namespace think;
require __DIR__ . '/../vendor/autoload.php';
// 执行HTTP应用并响应
$http = (new App())->http;
$response = $http->run();
$response->send();
function langt($str = '',$lang = 'en'){
// $lang 要自动获取当前语言,并不需要靠赋值来区分语言
if($lang == 'cn') return $str;
$langarr = array(
'en' => array(
'Name of the merchant'=>'商户名称',
'Detailed address'=>'详细地址',
'Distribution area'=>'经销区域',
'Latitude and longitude orientation'=>'经纬度定位',
'Latitude and longitude orientation'=>'经纬度定位',
),
'tc' => array(
'Name of the merchant'=>'商戶名稱',
'Detailed address'=>'詳細地址',
'Distribution area'=>'經銷區域',
'Latitude and longitude orientation'=>'經緯度定位6',
)
);
$langkey = (string) array_search($str,$langarr['en']);
if($lang == 'en') return $langkey?:$str;
return isset($langarr[$lang][$langkey])?$langarr[$lang][$langkey]:$str;
}
/**
* 输出字符串或数组
* @param string/array $vars 输出字符串或数组
* @param string $label 提示标题
* @param string $return 是否有返回值
*/
function dump($vars, $return = false, $label = ''){
if (ini_get('html_errors')){
$content = "<pre>\n";
if ($label != '') {
$content .= "<strong>{$label} :</strong>\n";
}
$content .= htmlspecialchars(print_r($vars, true), ENT_COMPAT, 'ISO-8859-1');
$content .= "\n</pre>\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();
$http->end($response);

View File

@ -8,15 +8,10 @@
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
use think\facade\Route;
Route::get('think', function () {
return 'hello,ThinkPHP5!';
});
//Route::get('hello/:name', 'index/hello');
//
//Route::get('news', 'news/test/hello');
return [
];
Route::get('hello/:name', 'index/hello');

7
think
View File

@ -13,10 +13,7 @@
namespace think;
// 加载基础文件
require __DIR__ . '/thinkphp/base.php';
require __DIR__ . '/vendor/autoload.php';
// 应用初始化
Container::get('app')->path(__DIR__ . '/application/')->initialize();
// 控制台初始化
Console::init();
(new App())->console->run();

3
thinkphp/.gitignore vendored
View File

@ -1,3 +0,0 @@
/composer.lock
.idea
.DS_Store

View File

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

View File

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

View File

@ -1,32 +0,0 @@
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.

View File

@ -1,61 +0,0 @@
ThinkPHP 5.1
===============
[![StyleCI](https://styleci.io/repos/48530411/shield?style=flat&branch=master)](https://styleci.io/repos/48530411)
[![Build Status](https://travis-ci.org/top-think/framework.svg?branch=master)](https://travis-ci.org/top-think/framework)
[![codecov.io](http://codecov.io/github/top-think/framework/coverage.svg?branch=master)](http://codecov.io/github/github/top-think/framework?branch=master)
[![Total Downloads](https://poser.pugx.org/topthink/framework/downloads)](https://packagist.org/packages/topthink/framework)
[![Latest Stable Version](https://poser.pugx.org/topthink/framework/v/stable)](https://packagist.org/packages/topthink/framework)
[![Latest Unstable Version](https://poser.pugx.org/topthink/framework/v/unstable)](https://packagist.org/packages/topthink/framework)
[![License](https://poser.pugx.org/topthink/framework/license)](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)

View File

@ -1,108 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
// 载入Loader类
require __DIR__ . '/library/think/Loader.php';
// 注册自动加载
Loader::register();
//// 注册错误和异常处理机制
//Error::register();
//
//// 实现日志接口
//if (interface_exists('Psr\Log\LoggerInterface')) {
// interface LoggerInterface extends \Psr\Log\LoggerInterface
// {}
//} else {
// interface LoggerInterface
// {}
//}
//通过 Container::getInstance()->bind() 先将核心类库实例化后注册到容器内
//再通过 Facade::bind() 将核心类转成静态代理,
//最后使用 Loader::addClassAlias() 给静态代理注册类别名,方便直接静态调用
// 注册核心类到容器
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();

View File

@ -1,35 +0,0 @@
{
"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"
}
}

View File

@ -1,292 +0,0 @@
<?php
return [
// +----------------------------------------------------------------------
// | 应用设置
// +----------------------------------------------------------------------
'app' => [
// 应用名称
'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,
],
];

View File

@ -1,691 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
//------------------------
// ThinkPHP 助手函数
//-------------------------
use think\Container;
use think\Db;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\facade\Cache;
use think\facade\Config;
use think\facade\Cookie;
use think\facade\Debug;
use think\facade\Env;
use think\facade\Hook;
use think\facade\Lang;
use think\facade\Log;
use think\facade\Request;
use think\facade\Route;
use think\facade\Session;
use think\facade\Url;
use think\Response;
use think\route\RuleItem;
if (!function_exists('abort')) {
/**
* 抛出HTTP异常
* @param integer|Response $code 状态码 或者 Response对象实例
* @param string $message 错误信息
* @param array $header 参数
*/
function abort($code, $message = null, $header = [])
{
if ($code instanceof Response) {
throw new HttpResponseException($code);
} else {
throw new HttpException($code, $message, null, $header);
}
}
}
if (!function_exists('action')) {
/**
* 调用模块的操作方法 参数格式 [模块/控制器/]操作
* @param string $url 调用地址
* @param string|array $vars 调用参数 支持字符串和数组
* @param string $layer 要调用的控制层名称
* @param bool $appendSuffix 是否添加类名后缀
* @return mixed
*/
function action($url, $vars = [], $layer = 'controller', $appendSuffix = false)
{
return app()->action($url, $vars, $layer, $appendSuffix);
}
}
if (!function_exists('app')) {
/**
* 快速获取容器中的实例 支持依赖注入
* @param string $name 类名或标识 默认获取当前应用实例
* @param array $args 参数
* @param bool $newInstance 是否每次创建新的实例
* @return 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 '<input type="hidden" name="' . $name . '" value="' . $token . '" />';
}
}
if (!function_exists('trace')) {
/**
* 记录日志信息
* @param mixed $log log信息 支持字符串和数组
* @param string $level 日志级别
* @return array|void
*/
function trace($log = '[think]', $level = 'log')
{
if ('[think]' === $log) {
return Log::getLog();
} else {
Log::record($log, $level);
}
}
}
if (!function_exists('trait_uses_recursive')) {
/**
* 获取一个trait里所有引用到的trait
*
* @param string $trait
* @return array
*/
function trait_uses_recursive($trait)
{
$traits = class_uses($trait);
foreach ($traits as $trait) {
$traits += trait_uses_recursive($trait);
}
return $traits;
}
}
if (!function_exists('url')) {
/**
* Url生成
* @param string $url 路由地址
* @param string|array $vars 变量
* @param bool|string $suffix 生成的URL后缀
* @param bool|string $domain 域名
* @return string
*/
function url($url = '', $vars = '', $suffix = true, $domain = false)
{
return Url::build($url, $vars, $suffix, $domain);
}
}
if (!function_exists('validate')) {
/**
* 实例化验证器
* @param string $name 验证器名称
* @param string $layer 业务层名称
* @param bool $appendSuffix 是否添加类名后缀
* @return \think\Validate
*/
function validate($name = '', $layer = 'validate', $appendSuffix = false)
{
return app()->validate($name, $layer, $appendSuffix);
}
}
if (!function_exists('view')) {
/**
* 渲染模板输出
* @param string $template 模板文件
* @param array $vars 模板变量
* @param integer $code 状态码
* @param callable $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);
}
}

View File

@ -1,135 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 核心中文语言包
return [
// 系统错误提示
'Undefined variable' => '未定义变量',
'Undefined index' => '未定义数组索引',
'Undefined offset' => '未定义数组下标',
'Parse error' => '语法解析错误',
'Type error' => '类型错误',
'Fatal error' => '致命错误',
'syntax error' => '语法错误',
// 框架核心错误提示
'dispatch type not support' => '不支持的调度类型',
'method param miss' => '方法参数错误',
'method not exists' => '方法不存在',
'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' => '规则错误',
];

View File

@ -1,946 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
use think\exception\ClassNotFoundException;
use think\exception\HttpResponseException;
use think\route\Dispatch;
/**
* App 应用管理
*/
class App 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);
}
}

View File

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

View File

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

View File

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

View File

@ -1,330 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
class Config implements \ArrayAccess
{
/**
* 配置参数
* @var array
*/
private $config = [];
/**
* 缓存前缀
* @var string
*/
private $prefix = 'app';
/**
* 设置配置参数默认前缀
* @access public
* @param string $prefix 前缀
* @return void
*/
public function setDefaultPrefix($prefix)
{
$this->prefix = $prefix;
}
/**
* 解析配置文件或内容
* @access public
* @param string $config 配置文件路径或内容
* @param string $type 配置解析类型
* @param string $name 配置名(如设置即表示二级配置)
* @return mixed
*/
public function parse($config, $type = '', $name = '')
{
if (empty($type)) {
$type = pathinfo($config, PATHINFO_EXTENSION);
}
$class = false !== strpos($type, '\\') ? $type : '\\think\\config\\driver\\' . ucwords($type);
return $this->set((new $class())->parse($config), $name);
}
/**
* 加载配置文件(多种格式)
* @access public
* @param string $file 配置文件名
* @param string $name 一级配置名
* @return mixed
*/
public function load($file, $name = '')
{
//检测文件是否存在
if (is_file($file)) {
//$name 所有字符转换为小写
$name = strtolower($name);
//获取文件的后缀格式
$type = pathinfo($file, PATHINFO_EXTENSION);
if ('php' == $type) {
// 后缀为 php格式返回配置信息数组的值
return $this->set(include $file, $name);
} elseif ('yaml' == $type && function_exists('yaml_parse_file')) {
// yaml 后缀格式 并检测环境是否支持 yaml_parse_file 函数
return $this->set(yaml_parse_file($file), $name);
} else {
// 除以上两种格式以外的
return $this->parse($file, $type, $name);
}
} else {
// 文件不存在直接返回配置信息数组
return $this->config;
}
}
/**
* 自动加载配置文件PHP格式
* @access public
* @param string $name 配置名
* @return void
*/
protected function autoLoad($name)
{
// 如果尚未载入 则动态加载配置文件
$module = Container::get('request')->module();
$module = $module ? $module . '/' : '';
$app = Container::get('app');
$path = $app->getAppPath() . $module;
if (is_dir($path . 'config')) {
$file = $path . 'config/' . $name . $app->getConfigExt();
} elseif (is_dir($app->getConfigPath() . $module)) {
$file = $app->getConfigPath() . $module . $name . $app->getConfigExt();
}
if (isset($file) && is_file($file)) {
$this->load($file, $name);
}
}
/**
* 检测配置是否存在
* @access public
* @param string $name 配置参数名(支持多级配置 .号分割)
* @return bool
*/
public function has($name)
{
if (!strpos($name, '.')) {
$name = $this->prefix . '.' . $name;
}
return $this->get($name) ? true : false;
}
/**
* 获取一级配置
* @access public
* @param string $name 一级配置名
* @return array
*/
public function pull($name)
{
$name = strtolower($name);
if (!isset($this->config[$name])) {
// 如果尚未载入 则动态加载配置文件
$this->autoLoad($name);
}
return isset($this->config[$name]) ? $this->config[$name] : [];
}
/**
* 获取配置参数 为空则获取所有配置
* @access public
* @param string $name 配置参数名(支持多级配置 .号分割)
* @return mixed
*/
public function get($name = null)
{
// 无参数时获取所有
if (empty($name)) {
return $this->config;
}
//点在字符串中第一次出现的位置
if (!strpos($name, '.')) {
$name = $this->prefix . '.' . $name;
} elseif ('.' == substr($name, -1)) {
return $this->pull(substr($name, 0, -1));
}
$name = explode('.', $name);
$name[0] = strtolower($name[0]);
$config = $this->config;
if (!isset($config[$name[0]])) {
// 如果尚未载入 则动态加载配置文件
$this->autoLoad($name[0]);
}
// 按.拆分成多维数组进行判断
foreach ($name as $val) {
if (isset($config[$val])) {
$config = $config[$val];
} else {
return;
}
}
return $config;
}
/**
* 设置配置参数 name为数组则为批量设置
* @access public
* @param string|array $name 配置参数名(支持三级配置 .号分割)
* @param mixed $value 配置值
* @return mixed
*/
public function set($name, $value = null)
{
// PHP 后缀时 $value 标识为文件名 $name 文件内容(数组)
// 检测$name 是否是字符串 是为true
// php 时一般$name 为数组 非字符串
if (is_string($name)) {
if (!strpos($name, '.')) {
$name = $this->prefix . '.' . $name;
}
$name = explode('.', $name, 3);
if (count($name) == 2) {
$this->config[strtolower($name[0])][$name[1]] = $value;
} else {
$this->config[strtolower($name[0])][$name[1]][$name[2]] = $value;
}
return $value;
} elseif (is_array($name)) {
// 为数组时执行 批量设置
// 检测¥value 是否为空或者null 不为空才执行如下
if (!empty($value)) {
//检测 是否已经存在
if (isset($this->config[$value])) {
//存在则合并成新的
$result = array_merge($this->config[$value], $name);
} else {
//不存在则赋值
$result = $name;
}
//最终根据¥value值为键值
$this->config[$value] = $result;
} else {
// empty($value) 为空时执行 数组合并
$result = $this->config = array_merge($this->config, $name);
}
} else {
// 为空直接返回 已有配置
$result = $this->config;
}
//并且返回当前的值
return $result;
}
/**
* 移除配置
* @access public
* @param string $name 配置参数名(支持三级配置 .号分割)
* @return void
*/
public function remove($name)
{
if (!strpos($name, '.')) {
$name = $this->prefix . '.' . $name;
}
$name = explode('.', $name, 3);
if (count($name) == 2) {
unset($this->config[strtolower($name[0])][$name[1]]);
} else {
unset($this->config[strtolower($name[0])][$name[1]][$name[2]]);
}
}
/**
* 重置配置参数
* @access public
* @param string $prefix 配置前缀名
* @return void
*/
public function reset($prefix = '')
{
if ('' === $prefix) {
$this->config = [];
} else {
$this->config[$prefix] = [];
}
}
/**
* 设置配置
* @access public
* @param string $name 参数名
* @param mixed $value
*/
public function __set($name, $value)
{
return $this->set($name, $value);
}
/**
* 获取配置参数
* @access public
* @param string $name 参数名
* @return mixed
*/
public function __get($name)
{
return $this->get($name);
}
/**
* 检测是否存在参数
* @access public
* @param string $name 参数名
* @return bool
*/
public function __isset($name)
{
return $this->has($name);
}
// ArrayAccess
public function offsetSet($name, $value)
{
$this->set($name, $value);
}
public function offsetExists($name)
{
return $this->has($name);
}
public function offsetUnset($name)
{
$this->remove($name);
}
public function offsetGet($name)
{
return $this->get($name);
}
}

View File

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

View File

@ -1,320 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
use Closure;
use InvalidArgumentException;
use ReflectionClass;
use ReflectionFunction;
use ReflectionMethod;
class Container
{
/**
* 容器对象实例
* @var Container
*/
protected static $instance;
/**
* 容器中的对象实例
* @var array
*/
protected $instances = [];
/**
* 容器绑定标识
* @var array
*/
protected $bind = [];
/**
* 获取当前容器的实例(单例)
* @access public
* @return static
*/
public static function getInstance()
{
if (is_null(static::$instance)) {
static::$instance = new static;
}
return static::$instance;
}
/**
* 获取容器中的对象实例
* @access public
* @param string $abstract 类名或者标识
* @param array|true $vars 变量
* @param bool $newInstance 是否每次创建新的实例
* @return object
*/
public static function get($abstract, $vars = [], $newInstance = false)
{
return static::getInstance()->make($abstract, $vars, $newInstance);
}
/**
* 绑定一个类、闭包、实例、接口实现到容器
* @access public
* @param string $abstract 类标识、接口
* @param mixed $concrete 要绑定的类、闭包或者实例
* @return Container
*/
public static function set($abstract, $concrete = null)
{
return static::getInstance()->bind($abstract, $concrete);
}
/**
* 绑定一个类、闭包、实例、接口实现到容器
* @access public
* @param string|array $abstract 类标识、接口
* @param mixed $concrete 要绑定的类、闭包或者实例
* @return $this
*/
public function bind($abstract, $concrete = null)
{
if (is_array($abstract)) {
$this->bind = array_merge($this->bind, $abstract);
} elseif ($concrete instanceof Closure) {
$this->bind[$abstract] = $concrete;
} elseif (is_object($concrete)) {
$this->instances[$abstract] = $concrete;
} else {
$this->bind[$abstract] = $concrete;
}
return $this;
}
/**
* 绑定一个类实例当容器
* @access public
* @param string $abstract 类名或者标识
* @param object $instance 类的实例
* @return $this
*/
public function instance($abstract, $instance)
{
if (isset($this->bind[$abstract])) {
$abstract = $this->bind[$abstract];
}
$this->instances[$abstract] = $instance;
return $this;
}
/**
* 判断容器中是否存在类及标识
* @access public
* @param string $abstract 类名或者标识
* @return bool
*/
public function bound($abstract)
{
return isset($this->bind[$abstract]) || isset($this->instances[$abstract]);
}
/**
* 判断容器中是否存在类及标识
* @access public
* @param string $name 类名或者标识
* @return bool
*/
public function has($name)
{
return $this->bound($name);
}
/**
* 创建类的实例
* @access public
* @param string $abstract 类名或者标识
* @param array|true $args 变量
* @param bool $newInstance 是否每次创建新的实例
* @return object
*/
public function make($abstract, $vars = [], $newInstance = false)
{
if (true === $vars) {
// 总是创建新的实例化对象
$newInstance = true;
$vars = [];
}
if (isset($this->instances[$abstract]) && !$newInstance) {
$object = $this->instances[$abstract];
} else {
if (isset($this->bind[$abstract])) {
$concrete = $this->bind[$abstract];
if ($concrete instanceof Closure) {
$object = $this->invokeFunction($concrete, $vars);
} else {
$object = $this->make($concrete, $vars, $newInstance);
}
} else {
$object = $this->invokeClass($abstract, $vars);
}
if (!$newInstance) {
$this->instances[$abstract] = $object;
}
}
return $object;
}
/**
* 执行函数或者闭包方法 支持参数调用
* @access public
* @param string|array|\Closure $function 函数或者闭包
* @param array $vars 变量
* @return mixed
*/
public function invokeFunction($function, $vars = [])
{
//$vars 带入的参数
$reflect = new ReflectionFunction($function);
//整理参数
$args = $this->bindParams($reflect, $vars);
// 调用(执行)反射的方法并将其参数作为数组传递
return $reflect->invokeArgs($args);
}
/**
* 调用反射执行类的方法 支持参数绑定
* @access public
* @param string|array $method 方法
* @param array $vars 变量
* @return mixed
*/
public function invokeMethod($method, $vars = [])
{
if (is_array($method)) {
//检测变量是否是一个对象
//检测第一个值是否为实例化对象,是则采用,不是则获取生成实例化对象
$class = is_object($method[0]) ? $method[0] : $this->invokeClass($method[0]);
$reflect = new ReflectionMethod($class, $method[1]);
} else {
// 静态方法
$reflect = new ReflectionMethod($method);
}
//整理参数
$args = $this->bindParams($reflect, $vars);
// 调用(执行)反射的方法并将其参数作为数组传递
return $reflect->invokeArgs(isset($class) ? $class : null, $args);
}
/**
* 调用反射执行callable 支持参数绑定
* @access public
* @param mixed $callable
* @param array $vars 变量
* @return mixed
*/
public function invoke($callable, $vars = [])
{
// $callable 数组或者字符串,匿名函数,或者类命名空间 或者静态调用方法
// $vars 传递的参数
//是否为闭包,闭包则执行函数,否则执行类方法
if ($callable instanceof Closure) {
//执行闭包函数
$result = $this->invokeFunction($callable, $vars);
} else {
//执行类 方法操作
$result = $this->invokeMethod($callable, $vars);
}
return $result;
}
/**
* 调用反射执行类的实例化 支持依赖注入
* @access public
* @param string $class 类名
* @param array $vars 变量
* @return mixed
*/
public function invokeClass($class, $vars = [])
{
//给定命名空间或者类名,返回对应的实例对象
// $vars 实例时需要传递的值
$reflect = new ReflectionClass($class);
// 获取类的构造函数,返回类命名空间以及构造函数
$constructor = $reflect->getConstructor();
if ($constructor) {
//处理传递的参数
$args = $this->bindParams($constructor, $vars);
} else {
$args = [];
}
//返回创建的新实例 从给出的参数创建一个新的类实例
return $reflect->newInstanceArgs($args);
}
/**
* 绑定参数
* @access protected
* @param \ReflectionMethod|\ReflectionFunction $reflect 反射类
* @param array $vars 变量
* @return array
*/
protected function bindParams($reflect, $vars = [])
{
$args = [];
// $reflect 代表ReflectionFunction 或者 ReflectionMethod 实例
// getNumberOfParameters() 获取的是函数或者方法需要的参数个数 如function($1,$2,$3)
if ($reflect->getNumberOfParameters() > 0) {
// 判断数组类型 数字数组时按顺序绑定参数
// 将数组的内部指针指向第一个单元
reset($vars);
$type = key($vars) === 0 ? 1 : 0;
//获取函数或者方法内 参数额变量名
$params = $reflect->getParameters();
foreach ($params as $param) {
//变量名称
$name = $param->getName();
//所属类
$class = $param->getClass();
//判断类是否有值
if ($class) {
//获取类的命名空间名称
$className = $class->getName();
$args[] = $this->make($className);
} elseif (1 == $type && !empty($vars)) {
//删除数组中的第一个元素
$args[] = array_shift($vars);
} elseif (0 == $type && isset($vars[$name])) {
$args[] = $vars[$name];
} elseif ($param->isDefaultValueAvailable()) {
$args[] = $param->getDefaultValue();
} else {
throw new InvalidArgumentException('method param miss:' . $name);
}
}
}
return $args;
}
}

View File

@ -1,242 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
use think\exception\ValidateException;
use traits\controller\Jump;
class Controller
{
use Jump;
/**
* 视图类实例
* @var \think\View
*/
protected $view;
/**
* Request实例
* @var \think\Request
*/
protected $request;
/**
* 应用实例
* @var \think\App
*/
protected $app;
/**
* 验证失败是否抛出异常
* @var bool
*/
protected $failException = false;
/**
* 是否批量验证
* @var bool
*/
protected $batchValidate = false;
/**
* 前置操作方法列表
* @var array $beforeActionList
*/
protected $beforeActionList = [];
/**
* 构造方法
* @access public
*/
public function __construct()
{
$this->request = Container::get('request');
$this->app = Container::get('app');
$this->view = Container::get('view')->init(
$this->app['config']->pull('template')
);
// 控制器初始化
$this->initialize();
// 前置操作方法
if ($this->beforeActionList) {
foreach ($this->beforeActionList as $method => $options) {
is_numeric($method) ?
$this->beforeAction($options) :
$this->beforeAction($method, $options);
}
}
}
// 初始化
protected function initialize()
{}
/**
* 前置操作
* @access protected
* @param string $method 前置操作方法名
* @param array $options 调用参数 ['only'=>[...]] 或者['except'=>[...]]
*/
protected function beforeAction($method, $options = [])
{
if (isset($options['only'])) {
if (is_string($options['only'])) {
$options['only'] = explode(',', $options['only']);
}
if (!in_array($this->request->action(), $options['only'])) {
return;
}
} elseif (isset($options['except'])) {
if (is_string($options['except'])) {
$options['except'] = explode(',', $options['except']);
}
if (in_array($this->request->action(), $options['except'])) {
return;
}
}
call_user_func([$this, $method]);
}
/**
* 加载模板输出
* @access protected
* @param string $template 模板文件名
* @param array $vars 模板输出变量
* @param array $config 模板参数
* @return mixed
*/
protected function fetch($template = '', $vars = [], $config = [])
{
return $this->view->fetch($template, $vars, $config);
}
/**
* 渲染内容输出
* @access protected
* @param string $content 模板内容
* @param array $vars 模板输出变量
* @param array $config 模板参数
* @return mixed
*/
protected function display($content = '', $vars = [], $config = [])
{
return $this->view->display($content, $vars, $config);
}
/**
* 模板变量赋值
* @access protected
* @param mixed $name 要显示的模板变量
* @param mixed $value 变量的值
* @return $this
*/
protected function assign($name, $value = '')
{
$this->view->assign($name, $value);
return $this;
}
/**
* 视图过滤
* @access protected
* @param Callable $filter 过滤方法或闭包
* @return $this
*/
protected function filter($filter)
{
$this->view->filter($filter);
return $this;
}
/**
* 初始化模板引擎
* @access protected
* @param array|string $engine 引擎参数
* @return $this
*/
protected function engine($engine)
{
$this->view->engine($engine);
return $this;
}
/**
* 设置验证失败后是否抛出异常
* @access protected
* @param bool $fail 是否抛出异常
* @return $this
*/
protected function validateFailException($fail = true)
{
$this->failException = $fail;
return $this;
}
/**
* 验证数据
* @access protected
* @param array $data 数据
* @param string|array $validate 验证器名或者验证规则数组
* @param array $message 提示信息
* @param bool $batch 是否批量验证
* @param mixed $callback 回调方法(闭包)
* @return array|string|true
* @throws ValidateException
*/
protected function validate($data, $validate, $message = [], $batch = false, $callback = null)
{
if (is_array($validate)) {
$v = $this->app->validate();
$v->rule($validate);
} else {
if (strpos($validate, '.')) {
// 支持场景
list($validate, $scene) = explode('.', $validate);
}
$v = $this->app->validate($validate);
if (!empty($scene)) {
$v->scene($scene);
}
}
// 是否批量验证
if ($batch || $this->batchValidate) {
$v->batch(true);
}
if (is_array($message)) {
$v->message($message);
}
if ($callback && is_callable($callback)) {
call_user_func_array($callback, [$v, &$data]);
}
if (!$v->check($data)) {
if ($this->failException) {
throw new ValidateException($v->getError());
} else {
return $v->getError();
}
} else {
return true;
}
}
}

View File

@ -1,262 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
class Cookie
{
/**
* 配置参数
* @var array
*/
protected $config = [
// cookie 名称前缀
'prefix' => '',
// cookie 保存时间
'expire' => 0,
// cookie 保存路径
'path' => '/',
// cookie 有效域名
'domain' => '',
// cookie 启用安全传输
'secure' => false,
// httponly设置
'httponly' => false,
// 是否使用 setcookie
'setcookie' => true,
];
/**
* 是否初始化
* @var bool
*/
protected $init;
/**
* Cookie初始化
* @access public
* @param array $config
* @return void
*/
public function init(array $config = [])
{
if (empty($config)) {
$config = Container::get('config')->pull('cookie');
}
$this->config = array_merge($this->config, array_change_key_case($config));
if (!empty($this->config['httponly'])) {
ini_set('session.cookie_httponly', 1);
}
$this->init = true;
}
/**
* 设置或者获取cookie作用域前缀
* @access public
* @param string $prefix
* @return string|void
*/
public function prefix($prefix = '')
{
if (empty($prefix)) {
return $this->config['prefix'];
}
$this->config['prefix'] = $prefix;
}
/**
* Cookie 设置、获取、删除
*
* @access public
* @param string $name cookie名称
* @param mixed $value cookie值
* @param mixed $option 可选参数 可能会是 null|integer|string
* @return void
*/
public function set($name, $value = '', $option = null)
{
!isset($this->init) && $this->init();
// 参数设置(会覆盖黙认设置)
if (!is_null($option)) {
if (is_numeric($option)) {
$option = ['expire' => $option];
} elseif (is_string($option)) {
parse_str($option, $option);
}
$config = array_merge($this->config, array_change_key_case($option));
} else {
$config = $this->config;
}
$name = $config['prefix'] . $name;
// 设置cookie
if (is_array($value)) {
array_walk_recursive($value, [$this, 'jsonFormatProtect'], 'encode');
$value = 'think:' . json_encode($value);
}
$expire = !empty($config['expire']) ? $_SERVER['REQUEST_TIME'] + intval($config['expire']) : 0;
if ($config['setcookie']) {
setcookie($name, $value, $expire, $config['path'], $config['domain'], $config['secure'], $config['httponly']);
}
$_COOKIE[$name] = $value;
}
/**
* 永久保存Cookie数据
* @access public
* @param string $name cookie名称
* @param mixed $value cookie值
* @param mixed $option 可选参数 可能会是 null|integer|string
* @return void
*/
public function forever($name, $value = '', $option = null)
{
if (is_null($option) || is_numeric($option)) {
$option = [];
}
$option['expire'] = 315360000;
$this->set($name, $value, $option);
}
/**
* 判断Cookie数据
* @access public
* @param string $name cookie名称
* @param string|null $prefix cookie前缀
* @return bool
*/
public function has($name, $prefix = null)
{
!isset($this->init) && $this->init();
$prefix = !is_null($prefix) ? $prefix : $this->config['prefix'];
$name = $prefix . $name;
return isset($_COOKIE[$name]);
}
/**
* Cookie获取
* @access public
* @param string $name cookie名称 留空获取全部
* @param string|null $prefix cookie前缀
* @return mixed
*/
public function get($name = '', $prefix = null)
{
!isset($this->init) && $this->init();
$prefix = !is_null($prefix) ? $prefix : $this->config['prefix'];
$key = $prefix . $name;
if ('' == $name) {
if ($prefix) {
$value = [];
foreach ($_COOKIE as $k => $val) {
if (0 === strpos($k, $prefix)) {
$value[$k] = $val;
}
}
} else {
$value = $_COOKIE;
}
} elseif (isset($_COOKIE[$key])) {
$value = $_COOKIE[$key];
if (0 === strpos($value, 'think:')) {
$value = substr($value, 6);
$value = json_decode($value, true);
array_walk_recursive($value, [$this, 'jsonFormatProtect'], 'decode');
}
} else {
$value = null;
}
return $value;
}
/**
* Cookie删除
* @access public
* @param string $name cookie名称
* @param string|null $prefix cookie前缀
* @return void
*/
public function delete($name, $prefix = null)
{
!isset($this->init) && $this->init();
$config = $this->config;
$prefix = !is_null($prefix) ? $prefix : $config['prefix'];
$name = $prefix . $name;
if ($config['setcookie']) {
setcookie($name, '', $_SERVER['REQUEST_TIME'] - 3600, $config['path'], $config['domain'], $config['secure'], $config['httponly']);
}
// 删除指定cookie
unset($_COOKIE[$name]);
}
/**
* Cookie清空
* @access public
* @param string|null $prefix cookie前缀
* @return void
*/
public function clear($prefix = null)
{
// 清除指定前缀的所有cookie
if (empty($_COOKIE)) {
return;
}
!isset($this->init) && $this->init();
// 要删除的cookie前缀不指定则删除config设置的指定前缀
$config = $this->config;
$prefix = !is_null($prefix) ? $prefix : $config['prefix'];
if ($prefix) {
// 如果前缀为空字符串将不作处理直接返回
foreach ($_COOKIE as $key => $val) {
if (0 === strpos($key, $prefix)) {
if ($config['setcookie']) {
setcookie($key, '', $_SERVER['REQUEST_TIME'] - 3600, $config['path'], $config['domain'], $config['secure'], $config['httponly']);
}
unset($_COOKIE[$key]);
}
}
}
return;
}
private function jsonFormatProtect(&$val, $key, $type = 'encode')
{
if (!empty($val) && true !== $val) {
$val = 'decode' == $type ? urldecode($val) : urlencode($val);
}
}
}

View File

@ -1,69 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
/**
* Class Db
* @package think
* @method \think\db\Query table(string $table) static 指定数据表(含前缀)
* @method \think\db\Query name(string $name) static 指定数据表(不含前缀)
* @method \think\db\Query where(mixed $field, string $op = null, mixed $condition = null) static 查询条件
* @method \think\db\Query join(mixed $join, mixed $condition = null, string $type = 'INNER') static JOIN查询
* @method \think\db\Query view(mixed $join, mixed $field = null, mixed $on = null, string $type = 'INNER') static 视图查询
* @method \think\db\Query union(mixed $union, boolean $all = false) static UNION查询
* @method \think\db\Query limit(mixed $offset, integer $length = null) static 查询LIMIT
* @method \think\db\Query order(mixed $field, string $order = null) static 查询ORDER
* @method \think\db\Query cache(mixed $key = null , integer $expire = null) static 设置查询缓存
* @method mixed value(string $field) static 获取某个字段的值
* @method array column(string $field, string $key = '') static 获取某个列的值
* @method mixed find(mixed $data = null) static 查询单个记录
* @method mixed select(mixed $data = null) static 查询多个记录
* @method integer insert(array $data, boolean $replace = false, boolean $getLastInsID = false, string $sequence = null) static 插入一条记录
* @method integer insertGetId(array $data, boolean $replace = false, string $sequence = null) static 插入一条记录并返回自增ID
* @method integer insertAll(array $dataSet) static 插入多条记录
* @method integer update(array $data) static 更新记录
* @method integer delete(mixed $data = null) static 删除记录
* @method boolean chunk(integer $count, callable $callback, string $column = null) static 分块获取数据
* @method \Generator cursor(mixed $data = null) static 使用游标查找记录
* @method mixed query(string $sql, array $bind = [], boolean $master = false, bool $pdo = false) static SQL查询
* @method integer execute(string $sql, array $bind = [], boolean $fetch = false, boolean $getLastInsID = false, string $sequence = null) static SQL执行
* @method \think\Paginator paginate(integer $listRows = 15, mixed $simple = null, array $config = []) static 分页查询
* @method mixed transaction(callable $callback) static 执行数据库事务
* @method void startTrans() static 启动事务
* @method void commit() static 用于非自动提交状态下面的查询提交
* @method void rollback() static 事务回滚
* @method boolean batchQuery(array $sqlArray) static 批处理执行SQL语句
* @method string getLastInsID($sequence = null) static 获取最近插入的ID
*/
class Db
{
/**
* 查询次数
* @var integer
*/
public static $queryTimes = 0;
/**
* 执行次数
* @var integer
*/
public static $executeTimes = 0;
public static function __callStatic($method, $args)
{
$class = Container::get('config')->get('database.query') ?: '\\think\\db\\Query';
$query = new $class();
return call_user_func_array([$query, $method], $args);
}
}

View File

@ -1,259 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
use think\exception\ClassNotFoundException;
use think\model\Collection as ModelCollection;
use think\response\Redirect;
class Debug
{
/**
* 区间时间信息
* @var array
*/
protected $info = [];
/**
* 区间内存信息
* @var array
*/
protected $mem = [];
/**
* 应用对象
* @var App
*/
protected $app;
public function __construct(App $app)
{
$this->app = $app;
}
/**
* 记录时间(微秒)和内存使用情况
* @access public
* @param string $name 标记位置
* @param mixed $value 标记值 留空则取当前 time 表示仅记录时间 否则同时记录时间和内存
* @return void
*/
public function remark($name, $value = '')
{
// 记录时间和内存使用
$this->info[$name] = is_float($value) ? $value : microtime(true);
if ('time' != $value) {
$this->mem['mem'][$name] = is_float($value) ? $value : memory_get_usage();
$this->mem['peak'][$name] = memory_get_peak_usage();
}
}
/**
* 统计某个区间的时间(微秒)使用情况
* @access public
* @param string $start 开始标签
* @param string $end 结束标签
* @param integer|string $dec 小数位
* @return integer
*/
public function getRangeTime($start, $end, $dec = 6)
{
if (!isset($this->info[$end])) {
$this->info[$end] = microtime(true);
}
return number_format(($this->info[$end] - $this->info[$start]), $dec);
}
/**
* 统计从开始到统计时的时间(微秒)使用情况
* @access public
* @param integer|string $dec 小数位
* @return integer
*/
public function getUseTime($dec = 6)
{
return number_format((microtime(true) - $this->app->getBeginTime()), $dec);
}
/**
* 获取当前访问的吞吐率情况
* @access public
* @return string
*/
public function getThroughputRate()
{
return number_format(1 / $this->getUseTime(), 2) . 'req/s';
}
/**
* 记录区间的内存使用情况
* @access public
* @param string $start 开始标签
* @param string $end 结束标签
* @param integer|string $dec 小数位
* @return string
*/
public function getRangeMem($start, $end, $dec = 2)
{
if (!isset($this->mem['mem'][$end])) {
$this->mem['mem'][$end] = memory_get_usage();
}
$size = $this->mem['mem'][$end] - $this->mem['mem'][$start];
$a = ['B', 'KB', 'MB', 'GB', 'TB'];
$pos = 0;
while ($size >= 1024) {
$size /= 1024;
$pos++;
}
return round($size, $dec) . " " . $a[$pos];
}
/**
* 统计从开始到统计时的内存使用情况
* @access public
* @param integer|string $dec 小数位
* @return string
*/
public function getUseMem($dec = 2)
{
$size = memory_get_usage() - $this->app->getBeginMem();
$a = ['B', 'KB', 'MB', 'GB', 'TB'];
$pos = 0;
while ($size >= 1024) {
$size /= 1024;
$pos++;
}
return round($size, $dec) . " " . $a[$pos];
}
/**
* 统计区间的内存峰值情况
* @access public
* @param string $start 开始标签
* @param string $end 结束标签
* @param integer|string $dec 小数位
* @return string
*/
public function getMemPeak($start, $end, $dec = 2)
{
if (!isset($this->mem['peak'][$end])) {
$this->mem['peak'][$end] = memory_get_peak_usage();
}
$size = $this->mem['peak'][$end] - $this->mem['peak'][$start];
$a = ['B', 'KB', 'MB', 'GB', 'TB'];
$pos = 0;
while ($size >= 1024) {
$size /= 1024;
$pos++;
}
return round($size, $dec) . " " . $a[$pos];
}
/**
* 获取文件加载信息
* @access public
* @param bool $detail 是否显示详细
* @return integer|array
*/
public function getFile($detail = false)
{
if ($detail) {
$files = get_included_files();
$info = [];
foreach ($files as $key => $file) {
$info[] = $file . ' ( ' . number_format(filesize($file) / 1024, 2) . ' KB )';
}
return $info;
}
return count(get_included_files());
}
/**
* 浏览器友好的变量输出
* @access public
* @param mixed $var 变量
* @param boolean $echo 是否输出 默认为true 如果为false 则返回输出字符串
* @param string $label 标签 默认为空
* @param integer $flags htmlspecialchars flags
* @return void|string
*/
public function dump($var, $echo = true, $label = null, $flags = ENT_SUBSTITUTE)
{
$label = (null === $label) ? '' : rtrim($label) . ':';
if ($var instanceof Model || $var instanceof ModelCollection) {
$var = $var->toArray();
}
ob_start();
var_dump($var);
$output = ob_get_clean();
$output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', $output);
if (PHP_SAPI == 'cli') {
$output = PHP_EOL . $label . $output . PHP_EOL;
} else {
if (!extension_loaded('xdebug')) {
$output = htmlspecialchars($output, $flags);
}
$output = '<pre>' . $label . $output . '</pre>';
}
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, '</body>');
if (false !== $pos) {
$content = substr($content, 0, $pos) . $output . substr($content, $pos);
} else {
$content = $content . $output;
}
}
}
}
}

View File

@ -1,108 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
class Env
{
/**
* 环境变量数据
* @var array
*/
protected $data = [];
public function __construct()
{
$this->data = $_ENV;
}
/**
* 读取环境变量定义文件
* @access public
* @param string $file 环境变量定义文件
* @return void
*/
public function load($file)
{
$env = parse_ini_file($file, true);
$this->set($env);
}
/**
* 获取环境变量值
* @access public
* @param string $name 环境变量名
* @param mixed $default 默认值
* @return mixed
*/
public function get($name = null, $default = null)
{
if (is_null($name)) {
return $this->data;
}
//替换字符内的.为_ 然后将字符串转为大写
$name = strtoupper(str_replace('.', '_', $name));
if (isset($this->data[$name])) {
return $this->data[$name];
}
return $this->getEnv($name, $default);
}
protected function getEnv($name, $default = null)
{
$result = getenv('PHP_' . $name);
if (false !== $result) {
if ('false' === $result) {
$result = false;
} elseif ('true' === $result) {
$result = true;
}
if (!isset($this->data[$name])) {
$this->data[$name] = $result;
}
return $result;
} else {
return $default;
}
}
/**
* 设置环境变量值
* @access public
* @param string|array $env 环境变量
* @param mixed $value
* @return void
*/
public function set($env, $value = null)
{
if (is_array($env)) {
$env = array_change_key_case($env, CASE_UPPER);
foreach ($env as $key => $val) {
if (is_array($val)) {
foreach ($val as $k => $v) {
$this->data[$key . '_' . strtoupper($k)] = $v;
}
} else {
$this->data[$key] = $val;
}
}
} else {
$name = strtoupper(str_replace('.', '_', $env));
$this->data[$name] = $value;
}
}
}

View File

@ -1,128 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://zjzit.cn>
// +----------------------------------------------------------------------
namespace think;
use think\console\Output as ConsoleOutput;
use think\exception\ErrorException;
use think\exception\Handle;
use think\exception\ThrowableError;
class Error
{
/**
* 注册异常处理
* @access public
* @return void
*/
public static function register()
{
error_reporting(E_ALL);
set_error_handler([__CLASS__, 'appError']);
set_exception_handler([__CLASS__, 'appException']);
register_shutdown_function([__CLASS__, 'appShutdown']);
}
/**
* Exception Handler
* @access public
* @param \Exception|\Throwable $e
*/
public static function appException($e)
{
if (!$e instanceof \Exception) {
$e = new ThrowableError($e);
}
self::getExceptionHandler()->report($e);
if (PHP_SAPI == 'cli') {
self::getExceptionHandler()->renderForConsole(new ConsoleOutput, $e);
} else {
self::getExceptionHandler()->render($e)->send();
}
}
/**
* Error Handler
* @access public
* @param integer $errno 错误编号
* @param integer $errstr 详细错误信息
* @param string $errfile 出错的文件
* @param integer $errline 出错行号
* @throws ErrorException
*/
public static function appError($errno, $errstr, $errfile = '', $errline = 0)
{
$exception = new ErrorException($errno, $errstr, $errfile, $errline);
if (error_reporting() & $errno) {
// 将错误信息托管至 think\exception\ErrorException
throw $exception;
} else {
self::getExceptionHandler()->report($exception);
}
}
/**
* Shutdown Handler
* @access public
*/
public static function appShutdown()
{
if (!is_null($error = error_get_last()) && self::isFatal($error['type'])) {
// 将错误信息托管至think\ErrorException
$exception = new ErrorException($error['type'], $error['message'], $error['file'], $error['line']);
self::appException($exception);
}
// 写入日志
Container::get('log')->save();
}
/**
* 确定错误类型是否致命
*
* @access protected
* @param int $type
* @return bool
*/
protected static function isFatal($type)
{
return in_array($type, [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE]);
}
/**
* Get an instance of the exception handler.
*
* @access public
* @return Handle
*/
public static function getExceptionHandler()
{
static $handle;
if (!$handle) {
// 异常处理handle
$class = Container::get('config')->get('exception_handle');
if ($class && is_string($class) && class_exists($class) && is_subclass_of($class, "\\think\\exception\\Handle")) {
$handle = new $class;
} else {
$handle = new Handle;
if ($class instanceof \Closure) {
$handle->setRender($class);
}
}
}
return $handle;
}
}

View File

@ -1,56 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://zjzit.cn>
// +----------------------------------------------------------------------
namespace think;
class Exception extends \Exception
{
/**
* 保存异常页面显示的额外Debug数据
* @var array
*/
protected $data = [];
/**
* 设置异常额外的Debug数据
* 数据将会显示为下面的格式
*
* Exception Data
* --------------------------------------------------
* Label 1
* key1 value1
* key2 value2
* Label 2
* key1 value1
* key2 value2
*
* @access protected
* @param string $label 数据分类,用于异常页面显示
* @param array $data 需要显示的数据,必须为关联数组
*/
final protected function setData($label, array $data)
{
$this->data[$label] = $data;
}
/**
* 获取异常额外Debug数据
* 主要用于输出到异常页面便于调试
* @access public
* @return array 由setData设置的Debug数据
*/
final public function getData()
{
return $this->data;
}
}

View File

@ -1,122 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
class Facade
{
/**
* 绑定对象
* @var array
*/
protected static $bind = [];
/**
* 始终创建新的对象实例
* @var bool
*/
protected static $alwaysNewInstance;
/**
* 绑定类的静态代理
* @static
* @access public
* @param string|array $name 类标识
* @param string $class 类名
* @return object
*/
public static function bind($name, $class = null)
{
if (__CLASS__ != static::class) {
return self::__callStatic('bind', func_get_args());
}
if (is_array($name)) {
self::$bind = array_merge(self::$bind, $name);
} else {
self::$bind[$name] = $class;
}
}
/**
* 创建Facade实例
* @static
* @access protected
* @param string $class 类名或标识
* @param array $args 变量
* @param bool $newInstance 是否每次创建新的实例
* @return object
*/
protected static function createFacade($class = '', $args = [], $newInstance = false)
{
$class = $class ?: static::class;
$facadeClass = static::getFacadeClass();
if ($facadeClass) {
$class = $facadeClass;
} elseif (isset(self::$bind[$class])) {
$class = self::$bind[$class];
}
if (static::$alwaysNewInstance) {
$newInstance = true;
}
return Container::getInstance()->make($class, $args, $newInstance);
}
/**
* 获取当前Facade对应类名
* @access protected
* @return string
*/
protected static function getFacadeClass()
{}
/**
* 带参数实例化当前Facade类
* @access public
* @return object
*/
public static function instance(...$args)
{
return self::createFacade('', $args);
}
/**
* 调用类的实例
* @access public
* @param string $class 类名或者标识
* @param array|true $args 变量
* @param bool $newInstance 是否每次创建新的实例
* @return object
*/
public static function make($class, $args = [], $newInstance = false)
{
if (__CLASS__ != static::class) {
return self::__callStatic('make', func_get_args());
}
if (true === $args) {
// 总是创建新的实例化对象
$newInstance = true;
$args = [];
}
return self::createFacade($class, $args, $newInstance);
}
// 调用实际类的方法
public static function __callStatic($method, $params)
{
return call_user_func_array([static::createFacade(), $method], $params);
}
}

View File

@ -1,494 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
use SplFileObject;
class File extends SplFileObject
{
/**
* 错误信息
* @var string
*/
private $error = '';
/**
* 当前完整文件名
* @var string
*/
protected $filename;
/**
* 上传文件名
* @var string
*/
protected $saveName;
/**
* 上传文件命名规则
* @var string
*/
protected $rule = 'date';
/**
* 上传文件验证规则
* @var array
*/
protected $validate = [];
/**
* 是否单元测试
* @var bool
*/
protected $isTest;
/**
* 上传文件信息
* @var array
*/
protected $info = [];
/**
* 文件hash规则
* @var array
*/
protected $hash = [];
public function __construct($filename, $mode = 'r')
{
parent::__construct($filename, $mode);
$this->filename = $this->getRealPath() ?: $this->getPathname();
}
/**
* 是否测试
* @access public
* @param bool $test 是否测试
* @return $this
*/
public function isTest($test = false)
{
$this->isTest = $test;
return $this;
}
/**
* 设置上传信息
* @access public
* @param array $info 上传文件信息
* @return $this
*/
public function setUploadInfo($info)
{
$this->info = $info;
return $this;
}
/**
* 获取上传文件的信息
* @access public
* @param string $name
* @return array|string
*/
public function getInfo($name = '')
{
return isset($this->info[$name]) ? $this->info[$name] : $this->info;
}
/**
* 获取上传文件的文件名
* @access public
* @return string
*/
public function getSaveName()
{
return $this->saveName;
}
/**
* 设置上传文件的保存文件名
* @access public
* @param string $saveName
* @return $this
*/
public function setSaveName($saveName)
{
$this->saveName = $saveName;
return $this;
}
/**
* 获取文件的哈希散列值
* @access public
* @param string $type
* @return string
*/
public function hash($type = 'sha1')
{
if (!isset($this->hash[$type])) {
$this->hash[$type] = hash_file($type, $this->filename);
}
return $this->hash[$type];
}
/**
* 检查目录是否可写
* @access public
* @param string $path 目录
* @return boolean
*/
protected function checkPath($path)
{
if (is_dir($path)) {
return true;
}
if (mkdir($path, 0755, true)) {
return true;
} else {
$this->error = ['directory {:path} creation failed', ['path' => $path]];
return false;
}
}
/**
* 获取文件类型信息
* @access public
* @return string
*/
public function getMime()
{
$finfo = finfo_open(FILEINFO_MIME_TYPE);
return finfo_file($finfo, $this->filename);
}
/**
* 设置文件的命名规则
* @access public
* @param string $rule 文件命名规则
* @return $this
*/
public function rule($rule)
{
$this->rule = $rule;
return $this;
}
/**
* 设置上传文件的验证规则
* @access public
* @param array $rule 验证规则
* @return $this
*/
public function validate($rule = [])
{
$this->validate = $rule;
return $this;
}
/**
* 检测是否合法的上传文件
* @access public
* @return bool
*/
public function isValid()
{
if ($this->isTest) {
return is_file($this->filename);
}
return is_uploaded_file($this->filename);
}
/**
* 检测上传文件
* @access public
* @param array $rule 验证规则
* @return bool
*/
public function check($rule = [])
{
$rule = $rule ?: $this->validate;
/* 检查文件大小 */
if (isset($rule['size']) && !$this->checkSize($rule['size'])) {
$this->error = 'filesize not match';
return false;
}
/* 检查文件Mime类型 */
if (isset($rule['type']) && !$this->checkMime($rule['type'])) {
$this->error = 'mimetype to upload is not allowed';
return false;
}
/* 检查文件后缀 */
if (isset($rule['ext']) && !$this->checkExt($rule['ext'])) {
$this->error = 'extensions to upload is not allowed';
return false;
}
/* 检查图像文件 */
if (!$this->checkImg()) {
$this->error = 'illegal image files';
return false;
}
return true;
}
/**
* 检测上传文件后缀
* @access public
* @param array|string $ext 允许后缀
* @return bool
*/
public function checkExt($ext)
{
if (is_string($ext)) {
$ext = explode(',', $ext);
}
$extension = strtolower(pathinfo($this->getInfo('name'), PATHINFO_EXTENSION));
if (!in_array($extension, $ext)) {
return false;
}
return true;
}
/**
* 检测图像文件
* @access public
* @return bool
*/
public function checkImg()
{
$extension = strtolower(pathinfo($this->getInfo('name'), PATHINFO_EXTENSION));
/* 对图像文件进行严格检测 */
if (in_array($extension, ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'swf']) && !in_array($this->getImageType($this->filename), [1, 2, 3, 4, 6, 13])) {
return false;
}
return true;
}
// 判断图像类型
protected function getImageType($image)
{
if (function_exists('exif_imagetype')) {
return exif_imagetype($image);
} else {
try {
$info = getimagesize($image);
return $info ? $info[2] : false;
} catch (\Exception $e) {
return false;
}
}
}
/**
* 检测上传文件大小
* @access public
* @param integer $size 最大大小
* @return bool
*/
public function checkSize($size)
{
if ($this->getSize() > $size) {
return false;
}
return true;
}
/**
* 检测上传文件类型
* @access public
* @param array|string $mime 允许类型
* @return bool
*/
public function checkMime($mime)
{
if (is_string($mime)) {
$mime = explode(',', $mime);
}
if (!in_array(strtolower($this->getMime()), $mime)) {
return false;
}
return true;
}
/**
* 移动文件
* @access public
* @param string $path 保存路径
* @param string|bool $savename 保存的文件名 默认自动生成
* @param boolean $replace 同名文件是否覆盖
* @return false|File false-失败 否则返回File实例
*/
public function move($path, $savename = true, $replace = true)
{
// 文件上传失败,捕获错误代码
if (!empty($this->info['error'])) {
$this->error($this->info['error']);
return false;
}
// 检测合法性
if (!$this->isValid()) {
$this->error = 'upload illegal files';
return false;
}
// 验证上传
if (!$this->check()) {
return false;
}
$path = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
// 文件保存命名规则
$saveName = $this->buildSaveName($savename);
$filename = $path . $saveName;
// 检测目录
if (false === $this->checkPath(dirname($filename))) {
return false;
}
/* 不覆盖同名文件 */
if (!$replace && is_file($filename)) {
$this->error = ['has the same filename: {:filename}', ['filename' => $filename]];
return false;
}
/* 移动文件 */
if ($this->isTest) {
rename($this->filename, $filename);
} elseif (!move_uploaded_file($this->filename, $filename)) {
$this->error = 'upload write error';
return false;
}
// 返回 File对象实例
$file = new self($filename);
$file->setSaveName($saveName);
$file->setUploadInfo($this->info);
return $file;
}
/**
* 获取保存文件名
* @access public
* @param string|bool $savename 保存的文件名 默认自动生成
* @return string
*/
protected function buildSaveName($savename)
{
if (true === $savename) {
// 自动生成文件名
if ($this->rule instanceof \Closure) {
$savename = call_user_func_array($this->rule, [$this]);
} else {
switch ($this->rule) {
case 'date':
$savename = date('Ymd') . '/' . md5(microtime(true));
break;
default:
if (in_array($this->rule, hash_algos())) {
$hash = $this->hash($this->rule);
$savename = substr($hash, 0, 2) . '/' . substr($hash, 2);
} elseif (is_callable($this->rule)) {
$savename = call_user_func($this->rule);
} else {
$savename = date('Ymd') . '/' . md5(microtime(true));
}
}
}
} elseif ('' === $savename || false === $savename) {
$savename = $this->getInfo('name');
}
if (!strpos($savename, '.')) {
$savename .= '.' . pathinfo($this->getInfo('name'), PATHINFO_EXTENSION);
}
return $savename;
}
/**
* 获取错误代码信息
* @access public
* @param int $errorNo 错误号
*/
private function error($errorNo)
{
switch ($errorNo) {
case 1:
case 2:
$this->error = 'upload File size exceeds the maximum value';
break;
case 3:
$this->error = 'only the portion of file is uploaded';
break;
case 4:
$this->error = 'no file to uploaded';
break;
case 6:
$this->error = 'upload temp dir not found';
break;
case 7:
$this->error = 'file write error';
break;
default:
$this->error = 'unknown upload error';
}
}
/**
* 获取错误信息(支持多语言)
* @access public
* @return string
*/
public function getError()
{
$lang = Container::get('lang');
if (is_array($this->error)) {
list($msg, $vars) = $this->error;
} else {
$msg = $this->error;
$vars = [];
}
return $lang->has($msg) ? $lang->get($msg, $vars) : $msg;
}
public function __call($method, $args)
{
return $this->hash($method);
}
}

View File

@ -1,250 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
class Hook
{
/**
* 钩子行为定义
* @var array
*/
private $tags = [];
/**
* 绑定行为列表
* @var array
*/
protected $bind = [];
/**
* 入口方法名称
* @var string
*/
private static $portal = 'run';
/**
* 指定入口方法名称
* @access public
* @param string $name 方法名
* @return $this
*/
public function portal($name)
{
self::$portal = $name;
return $this;
}
/**
* 指定行为标识 便于调用
* @access public
* @param string|array $name 行为标识
* @param mixed $behavior 行为
* @return $this
*/
public function alias($name, $behavior = null)
{
if (is_array($name)) {
$this->bind = array_merge($this->bind, $name);
} else {
$this->bind[$name] = $behavior;
}
return $this;
}
/**
* 动态添加行为扩展到某个标签
* @access public
* @param string $tag 标签名称
* @param mixed $behavior 行为名称
* @param bool $first 是否放到开头执行
* @return void
*/
public function add($tag, $behavior, $first = false)
{
// isset($this->tags[$tag]) 为空 后面执行 $this->tags[$tag] = [];
// 值为空或者不存在则赋值为数组
isset($this->tags[$tag]) || $this->tags[$tag] = [];
// is_callable 检测参数是否为合法的可调用结构 可调用则返回 TRUE
// $behavior 是数组且不可调用时执行
if (is_array($behavior) && !is_callable($behavior)) {
// 检查键名内是否包含 _overlay 不包含时执行
if (!array_key_exists('_overlay', $behavior)) {
//执行合并
$this->tags[$tag] = array_merge($this->tags[$tag], $behavior);
} else {
//包含时执行注销
unset($behavior['_overlay']);
$this->tags[$tag] = $behavior;
}
//开头执行
} elseif ($first) {
//$behavior 插入到 $this->tags 数组内
array_unshift($this->tags[$tag], $behavior);
} else {
$this->tags[$tag][] = $behavior;
}
}
/**
* 批量导入插件
* @access public
* @param array $tags 插件信息
* @param bool $recursive 是否递归合并
* @return void
*/
public function import(array $tags, $recursive = true)
{
if ($recursive) {
foreach ($tags as $tag => $behavior) {
//将插件信息添加
$this->add($tag, $behavior);
}
} else {
//数组合并
$this->tags = $tags + $this->tags;
}
}
/**
* 获取插件信息
* @access public
* @param string $tag 插件位置 留空获取全部
* @return array
*/
public function get($tag = '')
{
if (empty($tag)) {
//获取全部的插件信息
return $this->tags;
} else {
return array_key_exists($tag, $this->tags) ? $this->tags[$tag] : [];
}
}
/**
* 监听标签的行为
* @access public
* @param string $tag 标签名称
* @param mixed $params 传入参数
* @param bool $once 只获取一个有效返回值
* @return mixed
*/
public function listen($tag, $params = null, $once = false)
{
// $results 用来存放返回的值
$results = [];
//获取这个钩子需要执行的所有代码
$tags = $this->get($tag);
//若数组内有值,则循环
foreach ($tags as $key => $name) {
//根据值执行代码并获取返回值
// $name 可理解为 需要执行的代码,或者类空间名,或者理解为执行方法
// $tag 可理解为钩子名称
// $params 需要传递的参数
$results[$key] = $this->execTag($name, $tag, $params);
if (false === $results[$key]) {
// 如果返回false 则中断行为执行
break;
} elseif (!is_null($results[$key]) && $once) {
//返回值 是 null 则返回 TRUE
//返回值 不为空,则只要一个有效值时跳出
break;
}
}
return $once ? end($results) : $results;
}
/**
* 执行行为
* @access public
* @param mixed $class 行为
* @param mixed $params 参数
* @return mixed
*/
public function exec($class, $params = null)
{
if ($class instanceof \Closure || is_array($class)) {
$method = $class;
} else {
if (isset($this->bind[$class])) {
$class = $this->bind[$class];
}
$method = [$class, self::$portal];
}
return Container::getInstance()->invoke($method, [$params]);
}
/**
* 执行某个标签的行为
* @access protected
* @param mixed $class 要执行的行为
* @param string $tag 方法名(标签名)
* @param mixed $params 参数
* @return mixed
*/
protected function execTag($class, $tag = '', $params = null)
{
//返回app的实例化
$app = Container::get('app');
//是否为调试模式,开启调试模式则进行赋值
$app->isDebug() && $app['debug']->remark('behavior_start', 'time');
// 字符串命名风格转换
// 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格,去掉下划线
// $tag 可理解为钩子名称
$method = Loader::parseName($tag, 1, false);
// instanceof 判断一个对象是否是某个类的实例
if ($class instanceof \Closure) {
// 闭包调用
$call = $class;
$class = 'Closure'; //调试才使用此值
} elseif (strpos($class, '::')) {
// 静态调用
// strpos 在字符串中第一次出现的位置
$call = $class;
} else {
// 动态调用
//根据$class 获取此类的实例化
$obj = Container::get($class); //会导致先初始化一次,应该缓存一下
//is_callable 检测回调函数 可调用则返回 TRUE
if (!is_callable([$obj, $method])) {
// 不可回调 赋默认值
$method = self::$portal; // 默认值run() 方法
}
$call = [$class, $method]; // 类或者空间名称 执行方法
$class = $class . '->' . $method; //只针对调试使用,拼接成 空间名称执行的例子
}
//以上代码主要获取 $call--正常要的参数 和 $class--调试时才需要的参数
// Container::getInstance() 获取的实例 think\Container执行 container 内的 invoke()方法
$result = Container::getInstance()->invoke($call, [$params]);
//调试模式
if ($app->isDebug()) {
$debug = $app['debug'];
$debug->remark('behavior_end', 'time');
$app->log('[ BEHAVIOR ] Run ' . $class . ' @' . $tag . ' [ RunTime:' . $debug->getRangeTime('behavior_start', 'behavior_end') . 's ]');
}
return $result;
}
}

View File

@ -1,265 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
class Lang
{
/**
* 多语言信息
* @var array
*/
private $lang = [];
/**
* 当前语言
* @var string
*/
private $range = 'zh-cn';
/**
* 多语言自动侦测变量名
* @var string
*/
protected $langDetectVar = 'lang';
/**
* 多语言cookie变量
* @var string
*/
protected $langCookieVar = 'think_var';
/**
* 允许的多语言列表
* @var array
*/
protected $allowLangList = [];
/**
* Accept-Language转义为对应语言包名称 系统默认配置
* @var string
*/
protected $acceptLanguage = [
'zh-hans-cn' => 'zh-cn',
];
// 设定当前的语言
public function range($range = '')
{
if ('' == $range) {
return $this->range;
} else {
$this->range = $range;
}
}
/**
* 设置语言定义(不区分大小写)
* @access public
* @param string|array $name 语言变量
* @param string $value 语言值
* @param string $range 语言作用域
* @return mixed
*/
public function set($name, $value = null, $range = '')
{
$range = $range ?: $this->range;
// 批量定义
if (!isset($this->lang[$range])) {
$this->lang[$range] = [];
}
if (is_array($name)) {
return $this->lang[$range] = array_change_key_case($name) + $this->lang[$range];
} else {
return $this->lang[$range][strtolower($name)] = $value;
}
}
/**
* 加载语言定义(不区分大小写)
* @access public
* @param string|array $file 语言文件
* @param string $range 语言作用域
* @return array
*/
public function load($file, $range = '')
{
$range = $range ?: $this->range;
if (!isset($this->lang[$range])) {
$this->lang[$range] = [];
}
// 批量定义
if (is_string($file)) {
$file = [$file];
}
$lang = [];
foreach ($file as $_file) {
if (is_file($_file)) {
// 记录加载信息
Container::get('app')->log('[ LANG ] ' . $_file);
$_lang = include $_file;
if (is_array($_lang)) {
$lang = array_change_key_case($_lang) + $lang;
}
}
}
if (!empty($lang)) {
$this->lang[$range] = $lang + $this->lang[$range];
}
return $this->lang[$range];
}
/**
* 获取语言定义(不区分大小写)
* @access public
* @param string|null $name 语言变量
* @param string $range 语言作用域
* @return bool
*/
public function has($name, $range = '')
{
$range = $range ?: $this->range;
return isset($this->lang[$range][strtolower($name)]);
}
/**
* 获取语言定义(不区分大小写)
* @access public
* @param string|null $name 语言变量
* @param array $vars 变量替换
* @param string $range 语言作用域
* @return mixed
*/
public function get($name = null, $vars = [], $range = '')
{
$range = $range ?: $this->range;
// 空参数返回所有定义
if (empty($name)) {
return $this->lang[$range];
}
$key = strtolower($name);
$value = isset($this->lang[$range][$key]) ? $this->lang[$range][$key] : $name;
// 变量解析
if (!empty($vars) && is_array($vars)) {
/**
* Notes:
* 为了检测的方便数字索引的判断仅仅是参数数组的第一个元素的key为数字0
* 数字索引采用的是系统的 sprintf 函数替换,用法请参考 sprintf 函数
*/
if (key($vars) === 0) {
// 数字索引解析
array_unshift($vars, $value);
$value = call_user_func_array('sprintf', $vars);
} else {
// 关联索引解析
$replace = array_keys($vars);
foreach ($replace as &$v) {
$v = "{:{$v}}";
}
$value = str_replace($replace, $vars, $value);
}
}
return $value;
}
/**
* 自动侦测设置获取语言选择
* @access public
* @return string
*/
public function detect()
{
// 自动侦测设置获取语言选择
$langSet = '';
if (isset($_GET[$this->langDetectVar])) {
// url中设置了语言变量
$langSet = strtolower($_GET[$this->langDetectVar]);
} elseif (isset($_COOKIE[$this->langCookieVar])) {
// Cookie中设置了语言变量
$langSet = strtolower($_COOKIE[$this->langCookieVar]);
} elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
// 自动侦测浏览器语言
preg_match('/^([a-z\d\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
$langSet = strtolower($matches[1]);
$acceptLangs = Container::get('config')->get('header_accept_lang');
if (isset($acceptLangs[$langSet])) {
$langSet = $acceptLangs[$langSet];
} elseif (isset($this->acceptLanguage[$langSet])) {
$langSet = $this->acceptLanguage[$langSet];
}
}
if (empty($this->allowLangList) || in_array($langSet, $this->allowLangList)) {
// 合法的语言
$this->range = $langSet ?: $this->range;
}
return $this->range;
}
/**
* 设置当前语言到Cookie
* @access public
* @param string $lang 语言
* @return void
*/
public function saveToCookie($lang = null)
{
$range = $lang ?: $this->range;
$_COOKIE[$this->langCookieVar] = $range;
}
/**
* 设置语言自动侦测的变量
* @access public
* @param string $var 变量名称
* @return void
*/
public function setLangDetectVar($var)
{
$this->langDetectVar = $var;
}
/**
* 设置语言的cookie保存变量
* @access public
* @param string $var 变量名称
* @return void
*/
public function setLangCookieVar($var)
{
$this->langCookieVar = $var;
}
/**
* 设置允许的语言列表
* @access public
* @param array $list 语言列表
* @return void
*/
public function setAllowLangList($list)
{
$this->allowLangList = $list;
}
}

View File

@ -1,428 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
class Loader
{
/**
* 类名映射信息
* @var array
*/
protected static $map = [];
/**
* 类库别名
* @var array
*/
protected static $classAlias = [];
/**
* PSR-4
* @var array
*/
private static $prefixLengthsPsr4 = [];
private static $prefixDirsPsr4 = [];
private static $fallbackDirsPsr4 = [];
/**
* PSR-0
* @var array
*/
private static $prefixesPsr0 = [];
private static $fallbackDirsPsr0 = [];
/**
* 自动加载的文件列表
* @var array
*/
private static $autoloadFiles = [];
/**
* Composer安装路径
* @var string
*/
private static $composerPath;
public static function dinfo(){
var_dump('---------------map 类名映射信息-------------------');
var_dump(self::$map);
var_dump('---------------classAlias 类库别名-------------------');
var_dump(self::$classAlias);
var_dump('---------------prefixLengthsPsr4-------------------');
var_dump(self::$prefixLengthsPsr4);
var_dump('---------------prefixDirsPsr4-------------------');
var_dump(self::$prefixDirsPsr4);
var_dump('---------------fallbackDirsPsr4-------------------');
var_dump(self::$fallbackDirsPsr4);
var_dump('---------------prefixesPsr0-------------------');
var_dump(self::$prefixesPsr0);
var_dump('---------------fallbackDirsPsr0-------------------');
var_dump(self::$fallbackDirsPsr0);
var_dump('---------------autoloadFiles 自动加载的文件列表-------------------');
var_dump(self::$autoloadFiles);
var_dump('---------------composerPath-------------------');
var_dump(self::$composerPath);
}
// 注册自动加载机制
public static function register($autoload = '')
{
// 注册系统自动加载
spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);
// 注册命名空间定义
self::addNamespace([
//核心目录
'think' => __DIR__ . '/',
//复用目录
'traits' => __DIR__ . '/../traits/',
]);
// 获取程序根目录
// $_SERVER['SCRIPT_FILENAME'] 当前执行脚本的绝对路径,并非当前文件的绝对路径
$path = dirname($_SERVER['SCRIPT_FILENAME']);
// is_file() 函数检查指定的文件名是否是正常的文件
// realpath() 函数返回绝对路径。
if (is_file('./think')) {
$rootPath = realpath($path) . '/';
} else {
$rootPath = realpath($path . '/../') . '/';
}
// $rootPath 程序所在根目录
// 加载类库映射文件
if (is_file($rootPath . 'runtime/classmap.php')) {
self::addClassMap(__include_file($rootPath . 'runtime/classmap.php'));
}
// Composer安装路径
self::$composerPath = $rootPath . 'vendor/composer/';
// Composer自动加载支持
if (is_dir(self::$composerPath)) {
self::registerComposerLoader(self::$composerPath);
}
// 自动加载extend目录
self::addAutoLoadDir($rootPath . 'extend');
}
// 自动加载
public static function autoload($class)
{
if (isset(self::$classAlias[$class])) {
return class_alias(self::$classAlias[$class], $class);
}
if ($file = self::findFile($class)) {
// Win环境严格区分大小写
if (strpos(PHP_OS, 'WIN') !== false && pathinfo($file, PATHINFO_FILENAME) != pathinfo(realpath($file), PATHINFO_FILENAME)) {
return false;
}
__include_file($file);
return true;
}
}
/**
* 查找文件
* @access private
* @param string $class
* @return string|false
*/
private static function findFile($class)
{
if (!empty(self::$map[$class])) {
// 类库映射
return self::$map[$class];
}
// 查找 PSR-4
// 将$class 字符串中的字符 内的\\ 替换成系统默认的文件目录,再拼接上文件后缀
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . '.php';
// var_dump($logicalPathPsr4);
$first = $class[0];
// var_dump($first);
if (isset(self::$prefixLengthsPsr4[$first])) {
foreach (self::$prefixLengthsPsr4[$first] as $prefix => $length) {
// strpos() 字符串中第一次出现的位置
if (0 === strpos($class, $prefix)) {
foreach (self::$prefixDirsPsr4[$prefix] as $dir) {
// var_dump(substr($logicalPathPsr4, $length));
// substr() 从字符串中返回
if (is_file($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
// echo $file.'<br />';
return $file;
}
}
}
}
}
// 查找 PSR-4 fallback dirs
foreach (self::$fallbackDirsPsr4 as $dir) {
if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
echo $file.'---------------<br />';
return $file;
}
}
// // 查找 PSR-0
// if (false !== $pos = strrpos($class, '\\')) {
// // namespaced class name
// $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
// . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
// } else {
// // PEAR-like class name
// $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . '.php';
// }
//
// if (isset(self::$prefixesPsr0[$first])) {
// foreach (self::$prefixesPsr0[$first] as $prefix => $dirs) {
// if (0 === strpos($class, $prefix)) {
// foreach ($dirs as $dir) {
// if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
// return $file;
// }
// }
// }
// }
// }
//
// // 查找 PSR-0 fallback dirs
// foreach (self::$fallbackDirsPsr0 as $dir) {
// if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
// return $file;
// }
// }
//
// return self::$map[$class] = false;
}
// 注册classmap
public static function addClassMap($class, $map = '')
{
if (is_array($class)) {
self::$map = array_merge(self::$map, $class);
} else {
self::$map[$class] = $map;
}
}
// 注册命名空间
public static function addNamespace($namespace, $path = '')
{
// 检测是否为数组
if (is_array($namespace)) {
foreach ($namespace as $prefix => $paths) {
self::addPsr4($prefix . '\\', rtrim($paths, DIRECTORY_SEPARATOR), true);
// 会增加一次IF判断
// self::addNamespace($prefix, $paths);
}
} else {
// 非数组则执行这个
self::addPsr4($namespace . '\\', rtrim($path, DIRECTORY_SEPARATOR), true);
}
}
// 添加Ps0空间
private static function addPsr0($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
self::$fallbackDirsPsr0 = array_merge(
(array) $paths,
self::$fallbackDirsPsr0
);
} else {
self::$fallbackDirsPsr0 = array_merge(
self::$fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset(self::$prefixesPsr0[$first][$prefix])) {
self::$prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
self::$prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
self::$prefixesPsr0[$first][$prefix]
);
} else {
self::$prefixesPsr0[$first][$prefix] = array_merge(
self::$prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
// 添加Psr4空间
// $prefix 别名
// $paths 路径
private static function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// 无值 则执行
// 为根命名空间注册目录。 Register directories for the root namespace.
// array_merge() 数组元素有相同的键名,则最后的元素会覆盖其他元素
if ($prepend) {
// 为真执行,数组合并
self::$fallbackDirsPsr4 = array_merge(
(array) $paths,
self::$fallbackDirsPsr4
);
} else {
self::$fallbackDirsPsr4 = array_merge(
self::$fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset(self::$prefixDirsPsr4[$prefix])) {
// isset() 检测变量是否已设置 存在并且值不是 NULL 则返回 TRUE
// self::$prefixDirsPsr4[$prefix] 为空执行
// 为新名称空间注册目录。 Register directories for a new namespace.
// 计算字符长度
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
// 判断最后以为是否为\ 符号,若不是则报错
// 在非空的PSR - 4字头端必须用命名空间separator
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
// 取$prefix 第一个字符做键值,$prefix 最后将$prefix的长度赋值
self::$prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
// $prefix 作为键值,将 $paths 转成数组做值
self::$prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// 以上条件都不满足条件,判断为真 则执行
// 在目录已经注册的命名空间。 Prepend directories for an already registered namespace.
self::$prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
self::$prefixDirsPsr4[$prefix]
);
} else {
// 为已注册的命名空间追加目录。 Append directories for an already registered namespace.
self::$prefixDirsPsr4[$prefix] = array_merge(
self::$prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
// 注册自动加载类库目录
public static function addAutoLoadDir($path)
{
self::$fallbackDirsPsr4[] = $path;
}
// 注册类别名
public static function addClassAlias($alias, $class = null)
{
if (is_array($alias)) {
self::$classAlias = array_merge(self::$classAlias, $alias);
} else {
self::$classAlias[$alias] = $class;
}
}
// 注册composer自动加载
public static function registerComposerLoader($composerPath)
{
if (is_file($composerPath . 'autoload_namespaces.php')) {
$map = require $composerPath . 'autoload_namespaces.php';
foreach ($map as $namespace => $path) {
self::addPsr0($namespace, $path);
}
}
if (is_file($composerPath . 'autoload_psr4.php')) {
$map = require $composerPath . 'autoload_psr4.php';
foreach ($map as $namespace => $path) {
self::addPsr4($namespace, $path);
}
}
if (is_file($composerPath . 'autoload_classmap.php')) {
$classMap = require $composerPath . 'autoload_classmap.php';
if ($classMap) {
self::addClassMap($classMap);
}
}
}
// 加载composer autofile文件
public static function loadComposerAutoloadFiles()
{
if (is_file(self::$composerPath . 'autoload_files.php')) {
$includeFiles = require self::$composerPath . 'autoload_files.php';
foreach ($includeFiles as $fileIdentifier => $file) {
if (empty(self::$autoloadFiles[$fileIdentifier])) {
__require_file($file);
self::$autoloadFiles[$fileIdentifier] = true;
}
}
}
}
/**
* 字符串命名风格转换
* type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
* @access public
* @param string $name 字符串
* @param integer $type 转换类型
* @param bool $ucfirst 首字母是否大写(驼峰规则)
* @return string
*/
public static function parseName($name, $type = 0, $ucfirst = true)
{
if ($type) {
//strtoupper 把所有字符转换为大写
$name = preg_replace_callback('/_([a-zA-Z])/', function ($match) {
return strtoupper($match[1]);
}, $name);
// ucfirst() 首字符转换为大写
// lcfirst() 首字符转换为小写
return $ucfirst ? ucfirst($name) : lcfirst($name);
} else {
// strtolower 所有字符转成小写
return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
}
}
}
/**
* 作用范围隔离
*
* @param $file
* @return mixed
*/
function __include_file($file)
{
return include $file;
}
function __require_file($file)
{
return require $file;
}

View File

@ -1,372 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
use think\exception\ClassNotFoundException;
class Log implements LoggerInterface
{
const EMERGENCY = 'emergency';
const ALERT = 'alert';
const CRITICAL = 'critical';
const ERROR = 'error';
const WARNING = 'warning';
const NOTICE = 'notice';
const INFO = 'info';
const DEBUG = 'debug';
const SQL = 'sql';
/**
* 日志信息
* @var array
*/
protected $log = [];
/**
* 配置参数
* @var array
*/
protected $config = [];
/**
* 日志写入驱动
* @var object
*/
protected $driver;
/**
* 日志授权key
* @var string
*/
protected $key;
/**
* 应用对象
* @var App
*/
protected $app;
public function __construct(App $app)
{
$this->app = $app;
}
/**
* 日志初始化
* @access public
* @param array $config
* @return $this
*/
public function init($config = [])
{
$type = isset($config['type']) ? $config['type'] : 'File';
$class = false !== strpos($type, '\\') ? $type : '\\think\\log\\driver\\' . ucwords($type);
$this->config = $config;
unset($config['type']);
if (class_exists($class)) {
$this->driver = new $class($config);
} else {
throw new ClassNotFoundException('class not exists:' . $class, $class);
}
// 记录初始化信息
$this->app->isDebug() && $this->record('[ LOG ] INIT ' . $type);
return $this;
}
/**
* 获取日志信息
* @access public
* @param string $type 信息类型
* @return array
*/
public function getLog($type = '')
{
return $type ? $this->log[$type] : $this->log;
}
/**
* 记录日志信息
* @access public
* @param mixed $msg 日志信息
* @param string $type 日志级别
* @param array $context 替换内容
* @return $this
*/
public function record($msg, $type = 'info', array $context = [])
{
if (is_string($msg)) {
$replace = [];
foreach ($context as $key => $val) {
$replace['{' . $key . '}'] = $val;
}
$msg = strtr($msg, $replace);
}
$this->log[$type][] = $msg;
if (PHP_SAPI == 'cli') {
// 命令行日志实时写入
$this->save();
}
return $this;
}
/**
* 清空日志信息
* @access public
* @return $this
*/
public function clear()
{
$this->log = [];
return $this;
}
/**
* 当前日志记录的授权key
* @access public
* @param string $key 授权key
* @return $this
*/
public function key($key)
{
$this->key = $key;
return $this;
}
/**
* 检查日志写入权限
* @access public
* @param array $config 当前日志配置参数
* @return bool
*/
public function check($config)
{
if ($this->key && !empty($config['allow_key']) && !in_array($this->key, $config['allow_key'])) {
return false;
}
return true;
}
/**
* 保存调试信息
* @access public
* @return bool
*/
public function save()
{
if (!empty($this->log)) {
if (is_null($this->driver)) {
$this->init($this->app['config']->pull('log'));
}
if (!$this->check($this->config)) {
// 检测日志写入权限
return false;
}
if (empty($this->config['level'])) {
// 获取全部日志
$log = $this->log;
if (!$this->app->isDebug() && isset($log['debug'])) {
unset($log['debug']);
}
} else {
// 记录允许级别
$log = [];
foreach ($this->config['level'] as $level) {
if (isset($this->log[$level])) {
$log[$level] = $this->log[$level];
}
}
}
$result = $this->driver->save($log);
if ($result) {
$this->log = [];
}
return $result;
}
return true;
}
/**
* 实时写入日志信息 并支持行为
* @access public
* @param mixed $msg 调试信息
* @param string $type 日志级别
* @param bool $force 是否强制写入
* @return bool
*/
public function write($msg, $type = 'info', $force = false)
{
// 封装日志信息
$log = $this->log;
if (true === $force || empty($this->config['level'])) {
$log[$type][] = $msg;
} elseif (in_array($type, $this->config['level'])) {
$log[$type][] = $msg;
} else {
return false;
}
// 监听log_write
$this->app['hook']->listen('log_write', $log);
if (is_null($this->driver)) {
$this->init($this->app['config']->pull('log'));
}
// 写入日志
$result = $this->driver->save($log);
if ($result) {
$this->log = [];
}
return $result;
}
/**
* 记录日志信息
* @access public
* @param string $level 日志级别
* @param mixed $message 日志信息
* @param array $context 替换内容
* @return void
*/
public function log($level, $message, array $context = [])
{
$this->record($message, $level, $context);
}
/**
* 记录emergency信息
* @access public
* @param mixed $message 日志信息
* @param array $context 替换内容
* @return void
*/
public function emergency($message, array $context = [])
{
$this->log(__FUNCTION__, $message, $context);
}
/**
* 记录警报信息
* @access public
* @param mixed $message 日志信息
* @param array $context 替换内容
* @return void
*/
public function alert($message, array $context = [])
{
$this->log(__FUNCTION__, $message, $context);
}
/**
* 记录紧急情况
* @access public
* @param mixed $message 日志信息
* @param array $context 替换内容
* @return void
*/
public function critical($message, array $context = [])
{
$this->log(__FUNCTION__, $message, $context);
}
/**
* 记录错误信息
* @access public
* @param mixed $message 日志信息
* @param array $context 替换内容
* @return void
*/
public function error($message, array $context = [])
{
$this->log(__FUNCTION__, $message, $context);
}
/**
* 记录warning信息
* @access public
* @param mixed $message 日志信息
* @param array $context 替换内容
* @return void
*/
public function warning($message, array $context = [])
{
$this->log(__FUNCTION__, $message, $context);
}
/**
* 记录notice信息
* @access public
* @param mixed $message 日志信息
* @param array $context 替换内容
* @return void
*/
public function notice($message, array $context = [])
{
$this->log(__FUNCTION__, $message, $context);
}
/**
* 记录一般信息
* @access public
* @param mixed $message 日志信息
* @param array $context 替换内容
* @return void
*/
public function info($message, array $context = [])
{
$this->log(__FUNCTION__, $message, $context);
}
/**
* 记录调试信息
* @access public
* @param mixed $message 日志信息
* @param array $context 替换内容
* @return void
*/
public function debug($message, array $context = [])
{
$this->log(__FUNCTION__, $message, $context);
}
/**
* 记录sql信息
* @access public
* @param mixed $message 日志信息
* @param array $context 替换内容
* @return void
*/
public function sql($message, array $context = [])
{
$this->log(__FUNCTION__, $message, $context);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,437 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: zhangyajun <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think;
use ArrayAccess;
use ArrayIterator;
use Countable;
use IteratorAggregate;
use JsonSerializable;
use Traversable;
abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable
{
/**
* 是否简洁模式
* @var bool
*/
protected $simple = false;
/**
* 数据集
* @var Collection
*/
protected $items;
/**
* 当前页
* @var integer
*/
protected $currentPage;
/**
* 最后一页
* @var integer
*/
protected $lastPage;
/**
* 数据总数
* @var integer|null
*/
protected $total;
/**
* 每页数量
* @var integer
*/
protected $listRows;
/**
* 是否有下一页
* @var bool
*/
protected $hasMore;
/**
* 分页配置
* @var array
*/
protected $options = [
'var_page' => 'page',
'path' => '/',
'query' => [],
'fragment' => '',
];
public function __construct($items, $listRows, $currentPage = null, $total = null, $simple = false, $options = [])
{
$this->options = array_merge($this->options, $options);
$this->options['path'] = '/' != $this->options['path'] ? rtrim($this->options['path'], '/') : $this->options['path'];
$this->simple = $simple;
$this->listRows = $listRows;
if (!$items instanceof Collection) {
$items = Collection::make($items);
}
if ($simple) {
$this->currentPage = $this->setCurrentPage($currentPage);
$this->hasMore = count($items) > ($this->listRows);
$items = $items->slice(0, $this->listRows);
} else {
$this->total = $total;
$this->lastPage = (int) ceil($total / $listRows);
$this->currentPage = $this->setCurrentPage($currentPage);
$this->hasMore = $this->currentPage < $this->lastPage;
}
$this->items = $items;
}
/**
* @access public
* @param $items
* @param $listRows
* @param null $currentPage
* @param bool $simple
* @param null $total
* @param array $options
* @return Paginator
*/
public static function make($items, $listRows, $currentPage = null, $total = null, $simple = false, $options = [])
{
return new static($items, $listRows, $currentPage, $total, $simple, $options);
}
protected function setCurrentPage($currentPage)
{
if (!$this->simple && $currentPage > $this->lastPage) {
return $this->lastPage > 0 ? $this->lastPage : 1;
}
return $currentPage;
}
/**
* 获取页码对应的链接
*
* @access protected
* @param $page
* @return string
*/
protected function url($page)
{
if ($page <= 0) {
$page = 1;
}
if (strpos($this->options['path'], '[PAGE]') === false) {
$parameters = [$this->options['var_page'] => $page];
$path = $this->options['path'];
} else {
$parameters = [];
$path = str_replace('[PAGE]', $page, $this->options['path']);
}
if (count($this->options['query']) > 0) {
$parameters = array_merge($this->options['query'], $parameters);
}
$url = $path;
if (!empty($parameters)) {
$url .= '?' . urldecode(http_build_query($parameters, null, '&'));
}
return $url . $this->buildFragment();
}
/**
* 自动获取当前页码
* @access public
* @param string $varPage
* @param int $default
* @return int
*/
public static function getCurrentPage($varPage = 'page', $default = 1)
{
$page = Container::get('request')->param($varPage);
if (filter_var($page, FILTER_VALIDATE_INT) !== false && (int) $page >= 1) {
return $page;
}
return $default;
}
/**
* 自动获取当前的path
* @access public
* @return string
*/
public static function getCurrentPath()
{
return Container::get('request')->baseUrl();
}
public function total()
{
if ($this->simple) {
throw new \DomainException('not support total');
}
return $this->total;
}
public function listRows()
{
return $this->listRows;
}
public function currentPage()
{
return $this->currentPage;
}
public function lastPage()
{
if ($this->simple) {
throw new \DomainException('not support last');
}
return $this->lastPage;
}
/**
* 数据是否足够分页
* @access public
* @return boolean
*/
public function hasPages()
{
return !(1 == $this->currentPage && !$this->hasMore);
}
/**
* 创建一组分页链接
*
* @access public
* @param int $start
* @param int $end
* @return array
*/
public function getUrlRange($start, $end)
{
$urls = [];
for ($page = $start; $page <= $end; $page++) {
$urls[$page] = $this->url($page);
}
return $urls;
}
/**
* 设置URL锚点
*
* @access public
* @param string|null $fragment
* @return $this
*/
public function fragment($fragment)
{
$this->options['fragment'] = $fragment;
return $this;
}
/**
* 添加URL参数
*
* @access public
* @param array|string $key
* @param string|null $value
* @return $this
*/
public function appends($key, $value = null)
{
if (!is_array($key)) {
$queries = [$key => $value];
} else {
$queries = $key;
}
foreach ($queries as $k => $v) {
if ($k !== $this->options['var_page']) {
$this->options['query'][$k] = $v;
}
}
return $this;
}
/**
* 构造锚点字符串
*
* @access public
* @return string
*/
protected function buildFragment()
{
return $this->options['fragment'] ? '#' . $this->options['fragment'] : '';
}
/**
* 渲染分页html
* @access public
* @return mixed
*/
abstract public function render();
public function items()
{
return $this->items->all();
}
public function getCollection()
{
return $this->items;
}
public function isEmpty()
{
return $this->items->isEmpty();
}
/**
* 给每个元素执行个回调
*
* @access public
* @param callable $callback
* @return $this
*/
public function each(callable $callback)
{
foreach ($this->items as $key => $item) {
$result = $callback($item, $key);
if (false === $result) {
break;
} elseif (!is_object($item)) {
$this->items[$key] = $result;
}
}
return $this;
}
/**
* Retrieve an external iterator
* @access public
* @return Traversable An instance of an object implementing <b>Iterator</b> or
* <b>Traversable</b>
*/
public function getIterator()
{
return new ArrayIterator($this->items->all());
}
/**
* Whether a offset exists
* @access public
* @param mixed $offset
* @return bool
*/
public function offsetExists($offset)
{
return $this->items->offsetExists($offset);
}
/**
* Offset to retrieve
* @access public
* @param mixed $offset
* @return mixed
*/
public function offsetGet($offset)
{
return $this->items->offsetGet($offset);
}
/**
* Offset to set
* @access public
* @param mixed $offset
* @param mixed $value
*/
public function offsetSet($offset, $value)
{
$this->items->offsetSet($offset, $value);
}
/**
* Offset to unset
* @access public
* @param mixed $offset
* @return void
* @since 5.0.0
*/
public function offsetUnset($offset)
{
$this->items->offsetUnset($offset);
}
/**
* Count elements of an object
*/
public function count()
{
return $this->items->count();
}
public function __toString()
{
return (string) $this->render();
}
public function toArray()
{
try {
$total = $this->total();
} catch (\DomainException $e) {
$total = null;
}
return [
'total' => $total,
'per_page' => $this->listRows(),
'current_page' => $this->currentPage(),
'last_page' => $this->lastPage,
'data' => $this->items->toArray(),
];
}
/**
* Specify data which should be serialized to JSON
*/
public function jsonSerialize()
{
return $this->toArray();
}
public function __call($name, $arguments)
{
return call_user_func_array([$this->getCollection(), $name], $arguments);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,403 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
use think\response\Redirect as RedirectResponse;
class Response
{
/**
* 原始数据
* @var mixed
*/
protected $data;
/**
* 当前contentType
* @var string
*/
protected $contentType = 'text/html';
/**
* 字符集
* @var string
*/
protected $charset = 'utf-8';
/**
* 状态码
* @var integer
*/
protected $code = 200;
/**
* 是否允许请求缓存
* @var bool
*/
protected $allowCache = true;
/**
* 输出参数
* @var array
*/
protected $options = [];
/**
* header参数
* @var array
*/
protected $header = [];
/**
* 输出内容
* @var string
*/
protected $content = null;
/**
* 架构函数
* @access public
* @param mixed $data 输出数据
* @param int $code
* @param array $header
* @param array $options 输出参数
*/
public function __construct($data = '', $code = 200, array $header = [], $options = [])
{
$this->data($data);
if (!empty($options)) {
$this->options = array_merge($this->options, $options);
}
$this->contentType($this->contentType, $this->charset);
$this->code = $code;
$this->header = array_merge($this->header, $header);
}
/**
* 创建Response对象
* @access public
* @param mixed $data 输出数据
* @param string $type 输出类型
* @param int $code
* @param array $header
* @param array $options 输出参数
* @return Response
*/
public static function create($data = '', $type = '', $code = 200, array $header = [], $options = [])
{
$type = empty($type) ? 'null' : strtolower($type);
$class = false !== strpos($type, '\\') ? $type : '\\think\\response\\' . ucfirst($type);
if (class_exists($class)) {
return new $class($data, $code, $header, $options);
} else {
return new static($data, $code, $header, $options);
}
}
/**
* 发送数据到客户端
* @access public
* @return void
* @throws \InvalidArgumentException
*/
public function send()
{
// 监听response_send
Container::get('hook')->listen('response_send', $this);
// 处理输出数据
$data = $this->getContent();
// Trace调试注入
if (Container::get('env')->get('app_trace', Container::get('app')->config('app.app_trace'))) {
Container::get('debug')->inject($this, $data);
}
if (200 == $this->code && $this->allowCache) {
$cache = Container::get('request')->getCache();
if ($cache) {
$this->header['Cache-Control'] = 'max-age=' . $cache[1] . ',must-revalidate';
$this->header['Last-Modified'] = gmdate('D, d M Y H:i:s') . ' GMT';
$this->header['Expires'] = gmdate('D, d M Y H:i:s', $_SERVER['REQUEST_TIME'] + $cache[1]) . ' GMT';
Container::get('cache')->tag($cache[2])->set($cache[0], [$data, $this->header], $cache[1]);
}
}
if (!headers_sent() && !empty($this->header)) {
// 发送状态码
http_response_code($this->code);
// 发送头部信息
foreach ($this->header as $name => $val) {
header($name . (!is_null($val) ? ':' . $val : ''));
}
}
$this->sendData($data);
if (function_exists('fastcgi_finish_request')) {
// 提高页面响应
fastcgi_finish_request();
}
// 监听response_end
Container::get('hook')->listen('response_end', $this);
// 清空当次请求有效的数据
if (!($this instanceof RedirectResponse)) {
Container::get('session')->flush();
}
}
/**
* 处理数据
* @access protected
* @param mixed $data 要处理的数据
* @return mixed
*/
protected function output($data)
{
return $data;
}
/**
* 输出数据
* @access protected
* @param string $data 要处理的数据
* @return void
*/
protected function sendData($data)
{
echo $data;
}
/**
* 输出的参数
* @access public
* @param mixed $options 输出参数
* @return $this
*/
public function options($options = [])
{
$this->options = array_merge($this->options, $options);
return $this;
}
/**
* 输出数据设置
* @access public
* @param mixed $data 输出数据
* @return $this
*/
public function data($data)
{
$this->data = $data;
return $this;
}
/**
* 是否允许请求缓存
* @access public
* @param bool $cache 允许请求缓存
* @return $this
*/
public function allowCache($cache)
{
$this->allowCache = $cache;
return $this;
}
/**
* 设置响应头
* @access public
* @param string|array $name 参数名
* @param string $value 参数值
* @return $this
*/
public function header($name, $value = null)
{
if (is_array($name)) {
$this->header = array_merge($this->header, $name);
} else {
$this->header[$name] = $value;
}
return $this;
}
/**
* 设置页面输出内容
* @access public
* @param mixed $content
* @return $this
*/
public function content($content)
{
if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([
$content,
'__toString',
])
) {
throw new \InvalidArgumentException(sprintf('variable type error %s', gettype($content)));
}
$this->content = (string) $content;
return $this;
}
/**
* 发送HTTP状态
* @access public
* @param integer $code 状态码
* @return $this
*/
public function code($code)
{
$this->code = $code;
return $this;
}
/**
* LastModified
* @access public
* @param string $time
* @return $this
*/
public function lastModified($time)
{
$this->header['Last-Modified'] = $time;
return $this;
}
/**
* Expires
* @access public
* @param string $time
* @return $this
*/
public function expires($time)
{
$this->header['Expires'] = $time;
return $this;
}
/**
* ETag
* @access public
* @param string $eTag
* @return $this
*/
public function eTag($eTag)
{
$this->header['ETag'] = $eTag;
return $this;
}
/**
* 页面缓存控制
* @access public
* @param string $cache 状态码
* @return $this
*/
public function cacheControl($cache)
{
$this->header['Cache-control'] = $cache;
return $this;
}
/**
* 页面输出类型
* @access public
* @param string $contentType 输出类型
* @param string $charset 输出编码
* @return $this
*/
public function contentType($contentType, $charset = 'utf-8')
{
$this->header['Content-Type'] = $contentType . '; charset=' . $charset;
return $this;
}
/**
* 获取头部信息
* @access public
* @param string $name 头部名称
* @return mixed
*/
public function getHeader($name = '')
{
if (!empty($name)) {
return isset($this->header[$name]) ? $this->header[$name] : null;
} else {
return $this->header;
}
}
/**
* 获取原始数据
* @access public
* @return mixed
*/
public function getData()
{
return $this->data;
}
/**
* 获取输出数据
* @access public
* @return mixed
*/
public function getContent()
{
if (null == $this->content) {
$content = $this->output($this->data);
if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([
$content,
'__toString',
])
) {
throw new \InvalidArgumentException(sprintf('variable type error %s', gettype($content)));
}
$this->content = (string) $content;
}
return $this->content;
}
/**
* 获取状态码
* @access public
* @return integer
*/
public function getCode()
{
return $this->code;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,531 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
use think\exception\ClassNotFoundException;
class Session
{
/**
* 前缀
* @var string
*/
protected $prefix = '';
/**
* 是否初始化
* @var bool
*/
protected $init = null;
/**
* 锁驱动
* @var object
*/
protected $lockDriver = null;
/**
* 锁key
* @var string
*/
protected $sessKey = 'PHPSESSID';
/**
* 锁超时时间
* @var integer
*/
protected $lockTimeout = 3;
/**
* 是否启用锁机制
* @var bool
*/
protected $lock = false;
/**
* 设置或者获取session作用域前缀
* @access public
* @param string $prefix
* @return string|void
*/
public function prefix($prefix = '')
{
empty($this->init) && $this->boot();
if (empty($prefix) && null !== $prefix) {
return $this->prefix;
} else {
$this->prefix = $prefix;
}
}
/**
* session初始化
* @access public
* @param array $config
* @return void
* @throws \think\Exception
*/
public function init(array $config = [])
{
if (empty($config)) {
$config = Container::get('config')->pull('session');
}
// 记录初始化信息
Container::get('app')->log('[ SESSION ] INIT ' . var_export($config, true));
$isDoStart = false;
if (isset($config['use_trans_sid'])) {
ini_set('session.use_trans_sid', $config['use_trans_sid'] ? 1 : 0);
}
// 启动session
if (!empty($config['auto_start']) && PHP_SESSION_ACTIVE != session_status()) {
ini_set('session.auto_start', 0);
$isDoStart = true;
}
if (isset($config['prefix'])) {
$this->prefix = $config['prefix'];
}
if (isset($config['use_lock'])) {
$this->lock = $config['use_lock'];
}
if (isset($config['var_session_id']) && isset($_REQUEST[$config['var_session_id']])) {
session_id($_REQUEST[$config['var_session_id']]);
} elseif (isset($config['id']) && !empty($config['id'])) {
session_id($config['id']);
}
if (isset($config['name'])) {
session_name($config['name']);
}
if (isset($config['path'])) {
session_save_path($config['path']);
}
if (isset($config['domain'])) {
ini_set('session.cookie_domain', $config['domain']);
}
if (isset($config['expire'])) {
ini_set('session.gc_maxlifetime', $config['expire']);
ini_set('session.cookie_lifetime', $config['expire']);
}
if (isset($config['secure'])) {
ini_set('session.cookie_secure', $config['secure']);
}
if (isset($config['httponly'])) {
ini_set('session.cookie_httponly', $config['httponly']);
}
if (isset($config['use_cookies'])) {
ini_set('session.use_cookies', $config['use_cookies'] ? 1 : 0);
}
if (isset($config['cache_limiter'])) {
session_cache_limiter($config['cache_limiter']);
}
if (isset($config['cache_expire'])) {
session_cache_expire($config['cache_expire']);
}
if (!empty($config['type'])) {
// 读取session驱动
$class = false !== strpos($config['type'], '\\') ? $config['type'] : '\\think\\session\\driver\\' . ucwords($config['type']);
// 检查驱动类
if (!class_exists($class) || !session_set_save_handler(new $class($config))) {
throw new ClassNotFoundException('error session handler:' . $class, $class);
}
}
if ($isDoStart) {
session_start();
$this->init = true;
} else {
$this->init = false;
}
}
/**
* session自动启动或者初始化
* @access public
* @return void
*/
public function boot()
{
if (is_null($this->init)) {
$this->init();
} elseif (false === $this->init) {
if (PHP_SESSION_ACTIVE != session_status()) {
session_start();
}
$this->init = true;
}
}
/**
* session设置
* @access public
* @param string $name session名称
* @param mixed $value session值
* @param string|null $prefix 作用域(前缀)
* @return void
*/
public function set($name, $value, $prefix = null)
{
$this->lock();
empty($this->init) && $this->boot();
$prefix = !is_null($prefix) ? $prefix : $this->prefix;
if (strpos($name, '.')) {
// 二维数组赋值
list($name1, $name2) = explode('.', $name);
if ($prefix) {
$_SESSION[$prefix][$name1][$name2] = $value;
} else {
$_SESSION[$name1][$name2] = $value;
}
} elseif ($prefix) {
$_SESSION[$prefix][$name] = $value;
} else {
$_SESSION[$name] = $value;
}
$this->unlock();
}
/**
* session获取
* @access public
* @param string $name session名称
* @param string|null $prefix 作用域(前缀)
* @return mixed
*/
public function get($name = '', $prefix = null)
{
$this->lock();
empty($this->init) && $this->boot();
$prefix = !is_null($prefix) ? $prefix : $this->prefix;
$value = $prefix ? (!empty($_SESSION[$prefix]) ? $_SESSION[$prefix] : []) : $_SESSION;
if ('' != $name) {
$name = explode('.', $name);
foreach ($name as $val) {
if (isset($value[$val])) {
$value = $value[$val];
} else {
$value = null;
break;
}
}
}
$this->unlock();
return $value;
}
/**
* session 读写锁驱动实例化
*/
protected function initDriver()
{
// 不在 init 方法中实例化lockDriver是因为 init 方法不一定先于 set 或 get 方法调用
$config = Container::get('config')->pull('session');
if (!empty($config['type']) && isset($config['use_lock']) && $config['use_lock']) {
// 读取session驱动
$class = false !== strpos($config['type'], '\\') ? $config['type'] : '\\think\\session\\driver\\' . ucwords($config['type']);
// 检查驱动类及类中是否存在 lock 和 unlock 函数
if (class_exists($class) && method_exists($class, 'lock') && method_exists($class, 'unlock')) {
$this->lockDriver = new $class($config);
}
}
// 通过cookie获得session_id
if (isset($config['name']) && $config['name']) {
$this->sessKey = $config['name'];
}
if (isset($config['lock_timeout']) && $config['lock_timeout'] > 0) {
$this->lockTimeout = $config['lock_timeout'];
}
}
/**
* session 读写加锁
* @access protected
* @return void
*/
protected function lock()
{
if (empty($this->lock)) {
return;
}
$this->initDriver();
if (null !== $this->lockDriver && method_exists($this->lockDriver, 'lock')) {
$t = time();
// 使用 session_id 作为互斥条件,即只对同一 session_id 的会话互斥。第一次请求没有 session_id
$sessID = isset($_COOKIE[$this->sessKey]) ? $_COOKIE[$this->sessKey] : '';
do {
if (time() - $t > $this->lockTimeout) {
$this->unlock();
}
} while (!$this->lockDriver->lock($sessID, $this->lockTimeout));
}
}
/**
* session 读写解锁
* @access protected
* @return void
*/
protected function unlock()
{
if (empty($this->lock)) {
return;
}
$this->pause();
if ($this->lockDriver && method_exists($this->lockDriver, 'unlock')) {
$sessID = isset($_COOKIE[$this->sessKey]) ? $_COOKIE[$this->sessKey] : '';
$this->lockDriver->unlock($sessID);
}
}
/**
* session获取并删除
* @access public
* @param string $name session名称
* @param string|null $prefix 作用域(前缀)
* @return mixed
*/
public function pull($name, $prefix = null)
{
$result = $this->get($name, $prefix);
if ($result) {
$this->delete($name, $prefix);
return $result;
} else {
return;
}
}
/**
* session设置 下一次请求有效
* @access public
* @param string $name session名称
* @param mixed $value session值
* @param string|null $prefix 作用域(前缀)
* @return void
*/
public function flash($name, $value)
{
$this->set($name, $value);
if (!$this->has('__flash__.__time__')) {
$this->set('__flash__.__time__', $_SERVER['REQUEST_TIME_FLOAT']);
}
$this->push('__flash__', $name);
}
/**
* 清空当前请求的session数据
* @access public
* @return void
*/
public function flush()
{
if (!$this->init) {
return;
}
$item = $this->get('__flash__');
if (!empty($item)) {
$time = $item['__time__'];
if ($_SERVER['REQUEST_TIME_FLOAT'] > $time) {
unset($item['__time__']);
$this->delete($item);
$this->set('__flash__', []);
}
}
}
/**
* 删除session数据
* @access public
* @param string|array $name session名称
* @param string|null $prefix 作用域(前缀)
* @return void
*/
public function delete($name, $prefix = null)
{
empty($this->init) && $this->boot();
$prefix = !is_null($prefix) ? $prefix : $this->prefix;
if (is_array($name)) {
foreach ($name as $key) {
$this->delete($key, $prefix);
}
} elseif (strpos($name, '.')) {
list($name1, $name2) = explode('.', $name);
if ($prefix) {
unset($_SESSION[$prefix][$name1][$name2]);
} else {
unset($_SESSION[$name1][$name2]);
}
} else {
if ($prefix) {
unset($_SESSION[$prefix][$name]);
} else {
unset($_SESSION[$name]);
}
}
}
/**
* 清空session数据
* @access public
* @param string|null $prefix 作用域(前缀)
* @return void
*/
public function clear($prefix = null)
{
empty($this->init) && $this->boot();
$prefix = !is_null($prefix) ? $prefix : $this->prefix;
if ($prefix) {
unset($_SESSION[$prefix]);
} else {
$_SESSION = [];
}
}
/**
* 判断session数据
* @access public
* @param string $name session名称
* @param string|null $prefix
* @return bool
*/
public function has($name, $prefix = null)
{
empty($this->init) && $this->boot();
$prefix = !is_null($prefix) ? $prefix : $this->prefix;
if (strpos($name, '.')) {
// 支持数组
list($name1, $name2) = explode('.', $name);
return $prefix ? isset($_SESSION[$prefix][$name1][$name2]) : isset($_SESSION[$name1][$name2]);
} else {
return $prefix ? isset($_SESSION[$prefix][$name]) : isset($_SESSION[$name]);
}
}
/**
* 添加数据到一个session数组
* @access public
* @param string $key
* @param mixed $value
* @return void
*/
public function push($key, $value)
{
$array = $this->get($key);
if (is_null($array)) {
$array = [];
}
$array[] = $value;
$this->set($key, $array);
}
/**
* 启动session
* @access public
* @return void
*/
public function start()
{
session_start();
$this->init = true;
}
/**
* 销毁session
* @access public
* @return void
*/
public function destroy()
{
if (!empty($_SESSION)) {
$_SESSION = [];
}
session_unset();
session_destroy();
$this->init = null;
$this->lockDriver = null;
}
/**
* 重新生成session_id
* @access public
* @param bool $delete 是否删除关联会话文件
* @return void
*/
public function regenerate($delete = false)
{
session_regenerate_id($delete);
}
/**
* 暂停session
* @access public
* @return void
*/
public function pause()
{
// 暂停session
session_write_close();
$this->init = false;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,356 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
class Url
{
/**
* ROOT地址
* @var string
*/
protected $root;
/**
* 绑定检查
* @var bool
*/
protected $bindCheck;
/**
* 应用对象
* @var App
*/
protected $app;
public function __construct(App $app)
{
$this->app = $app;
if (is_file($app->getRuntimePath() . 'route.php')) {
// 读取路由映射文件
$app['route']->setName(include $app->getRuntimePath() . 'route.php');
}
}
/**
* URL生成 支持路由反射
* @access public
* @param string $url 路由地址
* @param string|array $vars 参数支持数组和字符串a=val&b=val2... ['a'=>'val1', 'b'=>'val2']
* @param string|bool $suffix 伪静态后缀默认为true表示获取配置值
* @param boolean|string $domain 是否显示域名 或者直接传入域名
* @return string
*/
public function build($url = '', $vars = '', $suffix = true, $domain = false)
{
// 解析URL
if (0 === strpos($url, '[') && $pos = strpos($url, ']')) {
// [name] 表示使用路由命名标识生成URL
$name = substr($url, 1, $pos - 1);
$url = 'name' . substr($url, $pos + 1);
}
if (false === strpos($url, '://') && 0 !== strpos($url, '/')) {
$info = parse_url($url);
$url = !empty($info['path']) ? $info['path'] : '';
if (isset($info['fragment'])) {
// 解析锚点
$anchor = $info['fragment'];
if (false !== strpos($anchor, '?')) {
// 解析参数
list($anchor, $info['query']) = explode('?', $anchor, 2);
}
if (false !== strpos($anchor, '@')) {
// 解析域名
list($anchor, $domain) = explode('@', $anchor, 2);
}
} elseif (strpos($url, '@') && false === strpos($url, '\\')) {
// 解析域名
list($url, $domain) = explode('@', $url, 2);
}
}
// 解析参数
if (is_string($vars)) {
// aaa=1&bbb=2 转换成数组
parse_str($vars, $vars);
}
if ($url) {
$rule = $this->app['route']->getName(isset($name) ? $name : $url . (isset($info['query']) ? '?' . $info['query'] : ''));
if (is_null($rule) && isset($info['query'])) {
$rule = $this->app['route']->getName($url);
// 解析地址里面参数 合并到vars
parse_str($info['query'], $params);
$vars = array_merge($params, $vars);
unset($info['query']);
}
}
if (!empty($rule) && $match = $this->getRuleUrl($rule, $vars)) {
// 匹配路由命名标识
$url = $match[0];
if (!empty($match[1])) {
$host = $this->app['config']->get('app_host') ?: $this->app['request']->host();
if ($domain || $match[1] != $host) {
$domain = $match[1];
}
}
if (!is_null($match[2])) {
$suffix = $match[2];
}
} elseif (!empty($rule) && isset($name)) {
throw new \InvalidArgumentException('route name not exists:' . $name);
} else {
// 检查别名路由
$alias = $this->app['route']->getAlias();
$matchAlias = false;
if ($alias) {
// 别名路由解析
foreach ($alias as $key => $val) {
if (is_array($val)) {
$val = $val[0];
}
if (0 === strpos($url, $val)) {
$url = $key . substr($url, strlen($val));
$matchAlias = true;
break;
}
}
}
if (!$matchAlias) {
// 路由标识不存在 直接解析
$url = $this->parseUrl($url);
}
if (isset($info['query'])) {
// 解析地址里面参数 合并到vars
parse_str($info['query'], $params);
$vars = array_merge($params, $vars);
}
}
// 检测URL绑定
if (!$this->bindCheck) {
$bind = $this->app['route']->getBind();
if ($bind && 0 === strpos($url, $bind)) {
$url = substr($url, strlen($bind) + 1);
}
}
// 还原URL分隔符
$depr = $this->app['config']->get('pathinfo_depr');
$url = str_replace('/', $depr, $url);
// URL后缀
if ('/' == substr($url, -1) || '' == $url) {
$suffix = '';
} else {
$suffix = $this->parseSuffix($suffix);
}
// 锚点
$anchor = !empty($anchor) ? '#' . $anchor : '';
// 参数组装
if (!empty($vars)) {
// 添加参数
if ($this->app['config']->get('url_common_param')) {
$vars = http_build_query($vars);
$url .= $suffix . '?' . $vars . $anchor;
} else {
$paramType = $this->app['config']->get('url_param_type');
foreach ($vars as $var => $val) {
if ('' !== trim($val)) {
if ($paramType) {
$url .= $depr . urlencode($val);
} else {
$url .= $depr . $var . $depr . urlencode($val);
}
}
}
$url .= $suffix . $anchor;
}
} else {
$url .= $suffix . $anchor;
}
// 检测域名
$domain = $this->parseDomain($url, $domain);
// URL组装
$url = $domain . rtrim($this->root ?: $this->app['request']->root(), '/') . '/' . ltrim($url, '/');
$this->bindCheck = false;
return $url;
}
// 直接解析URL地址
protected function parseUrl($url)
{
$request = $this->app['request'];
if (0 === strpos($url, '/')) {
// 直接作为路由地址解析
$url = substr($url, 1);
} elseif (false !== strpos($url, '\\')) {
// 解析到类
$url = ltrim(str_replace('\\', '/', $url), '/');
} elseif (0 === strpos($url, '@')) {
// 解析到控制器
$url = substr($url, 1);
} else {
// 解析到 模块/控制器/操作
$module = $request->module();
$module = $module ? $module . '/' : '';
$controller = $request->controller();
if ('' == $url) {
$action = $request->action();
} else {
$path = explode('/', $url);
$action = array_pop($path);
$controller = empty($path) ? $controller : array_pop($path);
$module = empty($path) ? $module : array_pop($path) . '/';
}
if ($this->app['config']->get('url_convert')) {
$action = strtolower($action);
$controller = Loader::parseName($controller);
}
$url = $module . $controller . '/' . $action;
}
return $url;
}
// 检测域名
protected function parseDomain(&$url, $domain)
{
if (!$domain) {
return '';
}
if (true === $domain) {
// 自动判断域名
$domain = $this->app['config']->get('app_host') ?: $this->app['request']->host();
$rootDomain = $this->app['config']->get('url_domain_root');
$domains = $this->app['route']->getDomains();
if ($domains) {
$route_domain = array_keys($domains);
foreach ($route_domain as $domain_prefix) {
if (0 === strpos($domain_prefix, '*.') && strpos($domain, ltrim($domain_prefix, '*.')) !== false) {
foreach ($domains as $key => $rule) {
$rule = is_array($rule) ? $rule[0] : $rule;
if (is_string($rule) && false === strpos($key, '*') && 0 === strpos($url, $rule)) {
$url = ltrim($url, $rule);
$domain = $key;
// 生成对应子域名
if (!empty($rootDomain)) {
$domain .= $rootDomain;
}
break;
} elseif (false !== strpos($key, '*')) {
if (!empty($rootDomain)) {
$domain .= $rootDomain;
}
break;
}
}
}
}
}
}
if (false !== strpos($domain, '://')) {
$scheme = '';
} else {
$scheme = $this->app['request']->isSsl() || $this->app['config']->get('is_https') ? 'https://' : 'http://';
}
return $scheme . $domain;
}
// 解析URL后缀
protected function parseSuffix($suffix)
{
if ($suffix) {
$suffix = true === $suffix ? $this->app['config']->get('url_html_suffix') : $suffix;
if ($pos = strpos($suffix, '|')) {
$suffix = substr($suffix, 0, $pos);
}
}
return (empty($suffix) || 0 === strpos($suffix, '.')) ? $suffix : '.' . $suffix;
}
// 匹配路由地址
public function getRuleUrl($rule, &$vars = [])
{
foreach ($rule as $item) {
list($url, $pattern, $domain, $suffix) = $item;
if (empty($pattern)) {
return [rtrim($url, '$'), $domain, $suffix];
}
$type = $this->app['config']->get('url_common_param');
foreach ($pattern as $key => $val) {
if (isset($vars[$key])) {
$url = str_replace(['[:' . $key . ']', '[:' . $key . '$]', '<' . $key . '?>$', '<' . $key . '?>', ':' . $key . '$', ':' . $key . '', '<' . $key . '>$', '<' . $key . '>'], $type ? $vars[$key] : urlencode($vars[$key]), $url);
unset($vars[$key]);
$result = [$url, $domain, $suffix];
} elseif (2 == $val) {
$url = str_replace(['/[:' . $key . ']', '/[:' . $key . '$]', '[:' . $key . ']', '[:' . $key . '$]', '<' . $key . '?>$', '<' . $key . '?>'], '', $url);
$result = [$url, $domain, $suffix];
} else {
break;
}
}
if (isset($result)) {
return $result;
}
}
return false;
}
// 指定当前生成URL地址的root
public function root($root)
{
$this->root = $root;
$this->app['request']->root($root);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,236 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
class View
{
/**
* 模板引擎实例
* @var object
*/
public $engine;
/**
* 模板变量
* @var array
*/
protected $data = [];
/**
* 内容过滤
* @var mixed
*/
protected $filter;
/**
* 全局模板变量
* @var array
*/
protected static $var = [];
/**
* 初始化
* @access public
* @param mixed $engine 模板引擎参数
* @return $this
*/
public function init($engine = [])
{
// 初始化模板引擎
$this->engine($engine);
return $this;
}
/**
* 模板变量静态赋值
* @access public
* @param mixed $name 变量名
* @param mixed $value 变量值
* @return $this
*/
public function share($name, $value = '')
{
if (is_array($name)) {
self::$var = array_merge(self::$var, $name);
} else {
self::$var[$name] = $value;
}
return $this;
}
/**
* 模板变量赋值
* @access public
* @param mixed $name 变量名
* @param mixed $value 变量值
* @return $this
*/
public function assign($name, $value = '')
{
if (is_array($name)) {
$this->data = array_merge($this->data, $name);
} else {
$this->data[$name] = $value;
}
return $this;
}
/**
* 设置当前模板解析的引擎
* @access public
* @param array|string $options 引擎参数
* @return $this
*/
public function engine($options = [])
{
if (is_string($options)) {
$type = $options;
$options = [];
} else {
$type = !empty($options['type']) ? $options['type'] : 'Think';
}
$class = false !== strpos($type, '\\') ? $type : '\\think\\view\\driver\\' . ucfirst($type);
if (isset($options['type'])) {
unset($options['type']);
}
$this->engine = new $class($options);
return $this;
}
/**
* 配置模板引擎
* @access public
* @param string|array $name 参数名
* @param mixed $value 参数值
* @return $this
*/
public function config($name, $value = null)
{
$this->engine->config($name, $value);
return $this;
}
/**
* 检查模板是否存在
* @access public
* @param string|array $name 参数名
* @return bool
*/
public function exists($name)
{
return $this->engine->exists($name);
}
/**
* 视图过滤
* @access public
* @param Callable $filter 过滤方法或闭包
* @return $this
*/
public function filter($filter)
{
$this->filter = $filter;
return $this;
}
/**
* 解析和获取模板内容 用于输出
* @access public
* @param string $template 模板文件名或者内容
* @param array $vars 模板输出变量
* @param array $config 模板参数
* @param bool $renderContent 是否渲染内容
* @return string
* @throws \Exception
*/
public function fetch($template = '', $vars = [], $config = [], $renderContent = false)
{
// 模板变量
$vars = array_merge(self::$var, $this->data, $vars);
// 页面缓存
ob_start();
ob_implicit_flush(0);
// 渲染输出
try {
$method = $renderContent ? 'display' : 'fetch';
$this->engine->$method($template, $vars, $config);
} catch (\Exception $e) {
ob_end_clean();
throw $e;
}
// 获取并清空缓存
$content = ob_get_clean();
if ($this->filter) {
$content = call_user_func_array($this->filter, [$content]);
}
return $content;
}
/**
* 渲染内容输出
* @access public
* @param string $content 内容
* @param array $vars 模板输出变量
* @param array $config 模板参数
* @return mixed
*/
public function display($content, $vars = [], $config = [])
{
return $this->fetch($content, $vars, $config, true);
}
/**
* 模板变量赋值
* @access public
* @param string $name 变量名
* @param mixed $value 变量值
*/
public function __set($name, $value)
{
$this->data[$name] = $value;
}
/**
* 取得模板显示变量的值
* @access protected
* @param string $name 模板变量
* @return mixed
*/
public function __get($name)
{
return $this->data[$name];
}
/**
* 检测模板变量是否设置
* @access public
* @param string $name 模板变量名
* @return bool
*/
public function __isset($name)
{
return isset($this->data[$name]);
}
}

View File

@ -1,353 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\cache;
use think\Container;
/**
* 缓存基础类
*/
abstract class Driver
{
/**
* 驱动句柄
* @var object
*/
protected $handler = null;
/**
* 缓存读取次数
* @var integer
*/
protected $readTimes = 0;
/**
* 缓存写入次数
* @var integer
*/
protected $writeTimes = 0;
/**
* 缓存参数
* @var array
*/
protected $options = [];
/**
* 缓存标签
* @var string
*/
protected $tag;
/**
* 序列化方法
* @var array
*/
protected static $serialize = ['serialize', 'unserialize', 'think_serialize:', 16];
/**
* 判断缓存是否存在
* @access public
* @param string $name 缓存变量名
* @return bool
*/
abstract public function has($name);
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $default 默认值
* @return mixed
*/
abstract public function get($name, $default = false);
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param int $expire 有效时间 0为永久
* @return boolean
*/
abstract public function set($name, $value, $expire = null);
/**
* 自增缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
abstract public function inc($name, $step = 1);
/**
* 自减缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
abstract public function dec($name, $step = 1);
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @return boolean
*/
abstract public function rm($name);
/**
* 清除缓存
* @access public
* @param string $tag 标签名
* @return boolean
*/
abstract public function clear($tag = null);
/**
* 获取有效期
* @access protected
* @param integer|\DateTime $expire 有效期
* @return integer
*/
protected function getExpireTime($expire)
{
if ($expire instanceof \DateTime) {
$expire = $expire->getTimestamp() - time();
}
return $expire;
}
/**
* 获取实际的缓存标识
* @access protected
* @param string $name 缓存名
* @return string
*/
protected function getCacheKey($name)
{
return $this->options['prefix'] . $name;
}
/**
* 读取缓存并删除
* @access public
* @param string $name 缓存变量名
* @return mixed
*/
public function pull($name)
{
$result = $this->get($name, false);
if ($result) {
$this->rm($name);
return $result;
} else {
return;
}
}
/**
* 如果不存在则写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param int $expire 有效时间 0为永久
* @return mixed
*/
public function remember($name, $value, $expire = null)
{
if (!$this->has($name)) {
$time = time();
while ($time + 5 > time() && $this->has($name . '_lock')) {
// 存在锁定则等待
usleep(200000);
}
try {
// 锁定
$this->set($name . '_lock', true);
if ($value instanceof \Closure) {
// 获取缓存数据
$value = Container::getInstance()->invokeFunction($value);
}
// 缓存数据
$this->set($name, $value, $expire);
// 解锁
$this->rm($name . '_lock');
} catch (\Exception $e) {
$this->rm($name . '_lock');
throw $e;
} catch (\throwable $e) {
$this->rm($name . '_lock');
throw $e;
}
} else {
$value = $this->get($name);
}
return $value;
}
/**
* 缓存标签
* @access public
* @param string $name 标签名
* @param string|array $keys 缓存标识
* @param bool $overlay 是否覆盖
* @return $this
*/
public function tag($name, $keys = null, $overlay = false)
{
if (is_null($name)) {
} elseif (is_null($keys)) {
$this->tag = $name;
} else {
$key = 'tag_' . md5($name);
if (is_string($keys)) {
$keys = explode(',', $keys);
}
$keys = array_map([$this, 'getCacheKey'], $keys);
if ($overlay) {
$value = $keys;
} else {
$value = array_unique(array_merge($this->getTagItem($name), $keys));
}
$this->set($key, implode(',', $value), 0);
}
return $this;
}
/**
* 更新标签
* @access protected
* @param string $name 缓存标识
* @return void
*/
protected function setTagItem($name)
{
if ($this->tag) {
$key = 'tag_' . md5($this->tag);
$prev = $this->tag;
$this->tag = null;
if ($this->has($key)) {
$value = explode(',', $this->get($key));
$value[] = $name;
$value = implode(',', array_unique($value));
} else {
$value = $name;
}
$this->set($key, $value, 0);
$this->tag = $prev;
}
}
/**
* 获取标签包含的缓存标识
* @access protected
* @param string $tag 缓存标签
* @return array
*/
protected function getTagItem($tag)
{
$key = 'tag_' . md5($tag);
$value = $this->get($key);
if ($value) {
return array_filter(explode(',', $value));
} else {
return [];
}
}
/**
* 序列化数据
* @access protected
* @param mixed $data
* @return string
*/
protected function serialize($data)
{
if (is_scalar($data) || !$this->options['serialize']) {
return $data;
}
$serialize = self::$serialize[0];
return self::$serialize[2] . $serialize($data);
}
/**
* 反序列化数据
* @access protected
* @param string $data
* @return mixed
*/
protected function unserialize($data)
{
if ($this->options['serialize'] && 0 === strpos($data, self::$serialize[2])) {
$unserialize = self::$serialize[1];
return $unserialize(substr($data, self::$serialize[3]));
} else {
return $data;
}
}
/**
* 注册序列化机制
* @access public
* @param callable $serialize 序列化方法
* @param callable $unserialize 反序列化方法
* @param string $prefix 序列化前缀标识
* @return $this
*/
public static function registerSerialize($serialize, $unserialize, $prefix = 'think_serialize:')
{
self::$serialize = [$serialize, $unserialize, $prefix, strlen($prefix)];
}
/**
* 返回句柄对象,可执行其它高级方法
*
* @access public
* @return object
*/
public function handler()
{
return $this->handler;
}
public function getReadTimes()
{
return $this->readTimes;
}
public function getWriteTimes()
{
return $this->writeTimes;
}
}

View File

@ -1,298 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\cache\driver;
use think\cache\Driver;
use think\Container;
/**
* 文件类型缓存类
* @author liu21st <liu21st@gmail.com>
*/
class File extends Driver
{
protected $options = [
'expire' => 0,
'cache_subdir' => true,
'prefix' => '',
'path' => '',
'hash_type' => 'md5',
'data_compress' => false,
'serialize' => true,
];
protected $expire;
/**
* 架构函数
* @param array $options
*/
public function __construct($options = [])
{
if (!empty($options)) {
$this->options = array_merge($this->options, $options);
}
if (empty($this->options['path'])) {
$this->options['path'] = Container::get('app')->getRuntimePath() . 'cache/';
} elseif (substr($this->options['path'], -1) != DIRECTORY_SEPARATOR) {
$this->options['path'] .= DIRECTORY_SEPARATOR;
}
$this->init();
}
/**
* 初始化检查
* @access private
* @return boolean
*/
private function init()
{
// 创建项目缓存目录
if (!is_dir($this->options['path'])) {
if (mkdir($this->options['path'], 0755, true)) {
return true;
}
}
return false;
}
/**
* 取得变量的存储文件名
* @access protected
* @param string $name 缓存变量名
* @param bool $auto 是否自动创建目录
* @return string
*/
protected function getCacheKey($name, $auto = false)
{
$name = hash($this->options['hash_type'], $name);
if ($this->options['cache_subdir']) {
// 使用子目录
$name = substr($name, 0, 2) . DIRECTORY_SEPARATOR . substr($name, 2);
}
if ($this->options['prefix']) {
$name = $this->options['prefix'] . DIRECTORY_SEPARATOR . $name;
}
$filename = $this->options['path'] . $name . '.php';
$dir = dirname($filename);
if ($auto && !is_dir($dir)) {
mkdir($dir, 0755, true);
}
return $filename;
}
/**
* 判断缓存是否存在
* @access public
* @param string $name 缓存变量名
* @return bool
*/
public function has($name)
{
return $this->get($name) ? true : false;
}
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $default 默认值
* @return mixed
*/
public function get($name, $default = false)
{
$this->readTimes++;
$filename = $this->getCacheKey($name);
if (!is_file($filename)) {
return $default;
}
$content = file_get_contents($filename);
$this->expire = null;
if (false !== $content) {
$expire = (int) substr($content, 8, 12);
if (0 != $expire && time() > filemtime($filename) + $expire) {
//缓存过期删除缓存文件
$this->unlink($filename);
return $default;
}
$this->expire = $expire;
$content = substr($content, 32);
if ($this->options['data_compress'] && function_exists('gzcompress')) {
//启用数据压缩
$content = gzuncompress($content);
}
return $this->unserialize($content);
} else {
return $default;
}
}
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param int|\DateTime $expire 有效时间 0为永久
* @return boolean
*/
public function set($name, $value, $expire = null)
{
$this->writeTimes++;
if (is_null($expire)) {
$expire = $this->options['expire'];
}
$expire = $this->getExpireTime($expire);
$filename = $this->getCacheKey($name, true);
if ($this->tag && !is_file($filename)) {
$first = true;
}
$data = $this->serialize($value);
if ($this->options['data_compress'] && function_exists('gzcompress')) {
//数据压缩
$data = gzcompress($data, 3);
}
$data = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;
$result = file_put_contents($filename, $data);
if ($result) {
isset($first) && $this->setTagItem($filename);
clearstatcache();
return true;
} else {
return false;
}
}
/**
* 自增缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
public function inc($name, $step = 1)
{
if ($this->has($name)) {
$value = $this->get($name) + $step;
$expire = $this->expire;
} else {
$value = $step;
$expire = 0;
}
return $this->set($name, $value, $expire) ? $value : false;
}
/**
* 自减缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
public function dec($name, $step = 1)
{
if ($this->has($name)) {
$value = $this->get($name) - $step;
$expire = $this->expire;
} else {
$value = -$step;
$expire = 0;
}
return $this->set($name, $value, $expire) ? $value : false;
}
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @return boolean
*/
public function rm($name)
{
$this->writeTimes++;
return $this->unlink($this->getCacheKey($name));
}
/**
* 清除缓存
* @access public
* @param string $tag 标签名
* @return boolean
*/
public function clear($tag = null)
{
if ($tag) {
// 指定标签清除
$keys = $this->getTagItem($tag);
foreach ($keys as $key) {
$this->unlink($key);
}
$this->rm('tag_' . md5($tag));
return true;
}
$this->writeTimes++;
$files = (array) glob($this->options['path'] . ($this->options['prefix'] ? $this->options['prefix'] . DIRECTORY_SEPARATOR : '') . '*');
foreach ($files as $path) {
if (is_dir($path)) {
$matches = glob($path . '/*.php');
if (is_array($matches)) {
array_map('unlink', $matches);
}
rmdir($path);
} else {
unlink($path);
}
}
return true;
}
/**
* 判断文件是否存在后,删除
* @access private
* @param string $path
* @return bool
* @author byron sampson <xiaobo.sun@qq.com>
* @return boolean
*/
private function unlink($path)
{
return is_file($path) && unlink($path);
}
}

View File

@ -1,209 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\cache\driver;
use think\cache\Driver;
/**
* 文件类型缓存类
* @author liu21st <liu21st@gmail.com>
*/
class Lite extends Driver
{
protected $options = [
'prefix' => '',
'path' => '',
'expire' => 0, // 等于 10*365*24*360010年
];
/**
* 架构函数
* @access public
*
* @param array $options
*/
public function __construct($options = [])
{
if (!empty($options)) {
$this->options = array_merge($this->options, $options);
}
if (substr($this->options['path'], -1) != DIRECTORY_SEPARATOR) {
$this->options['path'] .= DIRECTORY_SEPARATOR;
}
}
/**
* 取得变量的存储文件名
* @access protected
* @param string $name 缓存变量名
* @return string
*/
protected function getCacheKey($name)
{
return $this->options['path'] . $this->options['prefix'] . md5($name) . '.php';
}
/**
* 判断缓存是否存在
* @access public
* @param string $name 缓存变量名
* @return mixed
*/
public function has($name)
{
return $this->get($name) ? true : false;
}
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $default 默认值
* @return mixed
*/
public function get($name, $default = false)
{
$this->readTimes++;
$filename = $this->getCacheKey($name);
if (is_file($filename)) {
// 判断是否过期
$mtime = filemtime($filename);
if ($mtime < time()) {
// 清除已经过期的文件
unlink($filename);
return $default;
}
return include $filename;
} else {
return $default;
}
}
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param int|\DateTime $expire 有效时间 0为永久
* @return bool
*/
public function set($name, $value, $expire = null)
{
$this->writeTimes++;
if (is_null($expire)) {
$expire = $this->options['expire'];
}
if ($expire instanceof \DateTime) {
$expire = $expire->getTimestamp();
} else {
$expire = 0 === $expire ? 10 * 365 * 24 * 3600 : $expire;
$expire = time() + $expire;
}
$filename = $this->getCacheKey($name);
if ($this->tag && !is_file($filename)) {
$first = true;
}
$ret = file_put_contents($filename, ("<?php return " . var_export($value, true) . ";"));
// 通过设置修改时间实现有效期
if ($ret) {
isset($first) && $this->setTagItem($filename);
touch($filename, $expire);
}
return $ret;
}
/**
* 自增缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
public function inc($name, $step = 1)
{
if ($this->has($name)) {
$value = $this->get($name) + $step;
} else {
$value = $step;
}
return $this->set($name, $value, 0) ? $value : false;
}
/**
* 自减缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
public function dec($name, $step = 1)
{
if ($this->has($name)) {
$value = $this->get($name) - $step;
} else {
$value = -$step;
}
return $this->set($name, $value, 0) ? $value : false;
}
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @return boolean
*/
public function rm($name)
{
$this->writeTimes++;
return unlink($this->getCacheKey($name));
}
/**
* 清除缓存
* @access public
* @param string $tag 标签名
* @return bool
*/
public function clear($tag = null)
{
if ($tag) {
// 指定标签清除
$keys = $this->getTagItem($tag);
foreach ($keys as $key) {
unlink($key);
}
$this->rm('tag_' . md5($tag));
return true;
}
$this->writeTimes++;
array_map("unlink", glob($this->options['path'] . ($this->options['prefix'] ? $this->options['prefix'] . DIRECTORY_SEPARATOR : '') . '*.php'));
}
}

View File

@ -1,203 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\cache\driver;
use think\cache\Driver;
class Memcache extends Driver
{
protected $options = [
'host' => '127.0.0.1',
'port' => 11211,
'expire' => 0,
'timeout' => 0, // 超时时间(单位:毫秒)
'persistent' => true,
'prefix' => '',
'serialize' => true,
];
/**
* 架构函数
* @access public
* @param array $options 缓存参数
* @throws \BadFunctionCallException
*/
public function __construct($options = [])
{
if (!extension_loaded('memcache')) {
throw new \BadFunctionCallException('not support: memcache');
}
if (!empty($options)) {
$this->options = array_merge($this->options, $options);
}
$this->handler = new \Memcache;
// 支持集群
$hosts = explode(',', $this->options['host']);
$ports = explode(',', $this->options['port']);
if (empty($ports[0])) {
$ports[0] = 11211;
}
// 建立连接
foreach ((array) $hosts as $i => $host) {
$port = isset($ports[$i]) ? $ports[$i] : $ports[0];
$this->options['timeout'] > 0 ?
$this->handler->addServer($host, $port, $this->options['persistent'], 1, $this->options['timeout']) :
$this->handler->addServer($host, $port, $this->options['persistent'], 1);
}
}
/**
* 判断缓存
* @access public
* @param string $name 缓存变量名
* @return bool
*/
public function has($name)
{
$key = $this->getCacheKey($name);
return $this->handler->get($key) ? true : false;
}
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $default 默认值
* @return mixed
*/
public function get($name, $default = false)
{
$this->readTimes++;
$result = $this->handler->get($this->getCacheKey($name));
return false !== $result ? $this->unserialize($result) : $default;
}
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param int|DateTime $expire 有效时间(秒)
* @return bool
*/
public function set($name, $value, $expire = null)
{
$this->writeTimes++;
if (is_null($expire)) {
$expire = $this->options['expire'];
}
if ($this->tag && !$this->has($name)) {
$first = true;
}
$key = $this->getCacheKey($name);
$expire = $this->getExpireTime($expire);
$value = $this->serialize($value);
if ($this->handler->set($key, $value, 0, $expire)) {
isset($first) && $this->setTagItem($key);
return true;
}
return false;
}
/**
* 自增缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
public function inc($name, $step = 1)
{
$this->writeTimes++;
$key = $this->getCacheKey($name);
if ($this->handler->get($key)) {
return $this->handler->increment($key, $step);
}
return $this->handler->set($key, $step);
}
/**
* 自减缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
public function dec($name, $step = 1)
{
$this->writeTimes++;
$key = $this->getCacheKey($name);
$value = $this->handler->get($key) - $step;
$res = $this->handler->set($key, $value);
return !$res ? false : $value;
}
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @param bool|false $ttl
* @return bool
*/
public function rm($name, $ttl = false)
{
$this->writeTimes++;
$key = $this->getCacheKey($name);
return false === $ttl ?
$this->handler->delete($key) :
$this->handler->delete($key, $ttl);
}
/**
* 清除缓存
* @access public
* @param string $tag 标签名
* @return bool
*/
public function clear($tag = null)
{
if ($tag) {
// 指定标签清除
$keys = $this->getTagItem($tag);
foreach ($keys as $key) {
$this->handler->delete($key);
}
$this->rm('tag_' . md5($tag));
return true;
}
$this->writeTimes++;
return $this->handler->flush();
}
}

View File

@ -1,216 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\cache\driver;
use think\cache\Driver;
class Memcached extends Driver
{
protected $options = [
'host' => '127.0.0.1',
'port' => 11211,
'expire' => 0,
'timeout' => 0, // 超时时间(单位:毫秒)
'prefix' => '',
'username' => '', //账号
'password' => '', //密码
'option' => [],
'serialize' => true,
];
/**
* 架构函数
* @access public
* @param array $options 缓存参数
*/
public function __construct($options = [])
{
if (!extension_loaded('memcached')) {
throw new \BadFunctionCallException('not support: memcached');
}
if (!empty($options)) {
$this->options = array_merge($this->options, $options);
}
$this->handler = new \Memcached;
if (!empty($this->options['option'])) {
$this->handler->setOptions($this->options['option']);
}
// 设置连接超时时间(单位:毫秒)
if ($this->options['timeout'] > 0) {
$this->handler->setOption(\Memcached::OPT_CONNECT_TIMEOUT, $this->options['timeout']);
}
// 支持集群
$hosts = explode(',', $this->options['host']);
$ports = explode(',', $this->options['port']);
if (empty($ports[0])) {
$ports[0] = 11211;
}
// 建立连接
$servers = [];
foreach ((array) $hosts as $i => $host) {
$servers[] = [$host, (isset($ports[$i]) ? $ports[$i] : $ports[0]), 1];
}
$this->handler->addServers($servers);
if ('' != $this->options['username']) {
$this->handler->setOption(\Memcached::OPT_BINARY_PROTOCOL, true);
$this->handler->setSaslAuthData($this->options['username'], $this->options['password']);
}
}
/**
* 判断缓存
* @access public
* @param string $name 缓存变量名
* @return bool
*/
public function has($name)
{
$key = $this->getCacheKey($name);
return $this->handler->get($key) ? true : false;
}
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $default 默认值
* @return mixed
*/
public function get($name, $default = false)
{
$this->readTimes++;
$result = $this->handler->get($this->getCacheKey($name));
return false !== $result ? $this->unserialize($result) : $default;
}
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param integer|\DateTime $expire 有效时间(秒)
* @return bool
*/
public function set($name, $value, $expire = null)
{
$this->writeTimes++;
if (is_null($expire)) {
$expire = $this->options['expire'];
}
if ($this->tag && !$this->has($name)) {
$first = true;
}
$key = $this->getCacheKey($name);
$expire = $this->getExpireTime($expire);
$value = $this->serialize($value);
if ($this->handler->set($key, $value, $expire)) {
isset($first) && $this->setTagItem($key);
return true;
}
return false;
}
/**
* 自增缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
public function inc($name, $step = 1)
{
$this->writeTimes++;
$key = $this->getCacheKey($name);
if ($this->handler->get($key)) {
return $this->handler->increment($key, $step);
}
return $this->handler->set($key, $step);
}
/**
* 自减缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
public function dec($name, $step = 1)
{
$this->writeTimes++;
$key = $this->getCacheKey($name);
$value = $this->handler->get($key) - $step;
$res = $this->handler->set($key, $value);
return !$res ? false : $value;
}
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @param bool|false $ttl
* @return bool
*/
public function rm($name, $ttl = false)
{
$this->writeTimes++;
$key = $this->getCacheKey($name);
return false === $ttl ?
$this->handler->delete($key) :
$this->handler->delete($key, $ttl);
}
/**
* 清除缓存
* @access public
* @param string $tag 标签名
* @return bool
*/
public function clear($tag = null)
{
if ($tag) {
// 指定标签清除
$keys = $this->getTagItem($tag);
$this->handler->deleteMulti($keys);
$this->rm('tag_' . md5($tag));
return true;
}
$this->writeTimes++;
return $this->handler->flush();
}
}

View File

@ -1,206 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\cache\driver;
use think\cache\Driver;
/**
* Redis缓存驱动适合单机部署、有前端代理实现高可用的场景性能最好
* 有需要在业务层实现读写分离、或者使用RedisCluster的需求请使用Redisd驱动
*
* 要求安装phpredis扩展https://github.com/nicolasff/phpredis
* @author 尘缘 <130775@qq.com>
*/
class Redis extends Driver
{
protected $options = [
'host' => '127.0.0.1',
'port' => 6379,
'password' => '',
'select' => 0,
'timeout' => 0,
'expire' => 0,
'persistent' => false,
'prefix' => '',
'serialize' => true,
];
/**
* 架构函数
* @access public
* @param array $options 缓存参数
*/
public function __construct($options = [])
{
if (!extension_loaded('redis')) {
throw new \BadFunctionCallException('not support: redis');
}
if (!empty($options)) {
$this->options = array_merge($this->options, $options);
}
$this->handler = new \Redis;
if ($this->options['persistent']) {
$this->handler->pconnect($this->options['host'], $this->options['port'], $this->options['timeout'], 'persistent_id_' . $this->options['select']);
} else {
$this->handler->connect($this->options['host'], $this->options['port'], $this->options['timeout']);
}
if ('' != $this->options['password']) {
$this->handler->auth($this->options['password']);
}
if (0 != $this->options['select']) {
$this->handler->select($this->options['select']);
}
}
/**
* 判断缓存
* @access public
* @param string $name 缓存变量名
* @return bool
*/
public function has($name)
{
return $this->handler->get($this->getCacheKey($name)) ? true : false;
}
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $default 默认值
* @return mixed
*/
public function get($name, $default = false)
{
$this->readTimes++;
$value = $this->handler->get($this->getCacheKey($name));
if (is_null($value) || false === $value) {
return $default;
}
return $this->unserialize($value);
}
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param integer|\DateTime $expire 有效时间(秒)
* @return boolean
*/
public function set($name, $value, $expire = null)
{
$this->writeTimes++;
if (is_null($expire)) {
$expire = $this->options['expire'];
}
if ($this->tag && !$this->has($name)) {
$first = true;
}
$key = $this->getCacheKey($name);
$expire = $this->getExpireTime($expire);
$value = $this->serialize($value);
if ($expire) {
$result = $this->handler->setex($key, $expire, $value);
} else {
$result = $this->handler->set($key, $value);
}
isset($first) && $this->setTagItem($key);
return $result;
}
/**
* 自增缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
public function inc($name, $step = 1)
{
$this->writeTimes++;
$key = $this->getCacheKey($name);
return $this->handler->incrby($key, $step);
}
/**
* 自减缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
public function dec($name, $step = 1)
{
$this->writeTimes++;
$key = $this->getCacheKey($name);
return $this->handler->decrby($key, $step);
}
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @return boolean
*/
public function rm($name)
{
$this->writeTimes++;
return $this->handler->delete($this->getCacheKey($name));
}
/**
* 清除缓存
* @access public
* @param string $tag 标签名
* @return boolean
*/
public function clear($tag = null)
{
if ($tag) {
// 指定标签清除
$keys = $this->getTagItem($tag);
foreach ($keys as $key) {
$this->handler->delete($key);
}
$this->rm('tag_' . md5($tag));
return true;
}
$this->writeTimes++;
return $this->handler->flushDB();
}
}

View File

@ -1,233 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\cache\driver;
use think\cache\Driver;
/**
* Sqlite缓存驱动
* @author liu21st <liu21st@gmail.com>
*/
class Sqlite extends Driver
{
protected $options = [
'db' => ':memory:',
'table' => 'sharedmemory',
'prefix' => '',
'expire' => 0,
'persistent' => false,
'serialize' => true,
];
/**
* 架构函数
* @access public
* @param array $options 缓存参数
* @throws \BadFunctionCallException
*/
public function __construct($options = [])
{
if (!extension_loaded('sqlite')) {
throw new \BadFunctionCallException('not support: sqlite');
}
if (!empty($options)) {
$this->options = array_merge($this->options, $options);
}
$func = $this->options['persistent'] ? 'sqlite_popen' : 'sqlite_open';
$this->handler = $func($this->options['db']);
}
/**
* 获取实际的缓存标识
* @access public
* @param string $name 缓存名
* @return string
*/
protected function getCacheKey($name)
{
return $this->options['prefix'] . sqlite_escape_string($name);
}
/**
* 判断缓存
* @access public
* @param string $name 缓存变量名
* @return bool
*/
public function has($name)
{
$name = $this->getCacheKey($name);
$sql = 'SELECT value FROM ' . $this->options['table'] . ' WHERE var=\'' . $name . '\' AND (expire=0 OR expire >' . time() . ') LIMIT 1';
$result = sqlite_query($this->handler, $sql);
return sqlite_num_rows($result);
}
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $default 默认值
* @return mixed
*/
public function get($name, $default = false)
{
$this->readTimes++;
$name = $this->getCacheKey($name);
$sql = 'SELECT value FROM ' . $this->options['table'] . ' WHERE var=\'' . $name . '\' AND (expire=0 OR expire >' . time() . ') LIMIT 1';
$result = sqlite_query($this->handler, $sql);
if (sqlite_num_rows($result)) {
$content = sqlite_fetch_single($result);
if (function_exists('gzcompress')) {
//启用数据压缩
$content = gzuncompress($content);
}
return $this->unserialize($content);
}
return $default;
}
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param integer|\DateTime $expire 有效时间(秒)
* @return boolean
*/
public function set($name, $value, $expire = null)
{
$this->writeTimes++;
$name = $this->getCacheKey($name);
$value = sqlite_escape_string($this->serialize($value));
if (is_null($expire)) {
$expire = $this->options['expire'];
}
if ($expire instanceof \DateTime) {
$expire = $expire->getTimestamp();
} else {
$expire = (0 == $expire) ? 0 : (time() + $expire); //缓存有效期为0表示永久缓存
}
if (function_exists('gzcompress')) {
//数据压缩
$value = gzcompress($value, 3);
}
if ($this->tag) {
$tag = $this->tag;
$this->tag = null;
} else {
$tag = '';
}
$sql = 'REPLACE INTO ' . $this->options['table'] . ' (var, value, expire, tag) VALUES (\'' . $name . '\', \'' . $value . '\', \'' . $expire . '\', \'' . $tag . '\')';
if (sqlite_query($this->handler, $sql)) {
return true;
}
return false;
}
/**
* 自增缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
public function inc($name, $step = 1)
{
if ($this->has($name)) {
$value = $this->get($name) + $step;
} else {
$value = $step;
}
return $this->set($name, $value, 0) ? $value : false;
}
/**
* 自减缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
public function dec($name, $step = 1)
{
if ($this->has($name)) {
$value = $this->get($name) - $step;
} else {
$value = -$step;
}
return $this->set($name, $value, 0) ? $value : false;
}
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @return boolean
*/
public function rm($name)
{
$this->writeTimes++;
$name = $this->getCacheKey($name);
$sql = 'DELETE FROM ' . $this->options['table'] . ' WHERE var=\'' . $name . '\'';
sqlite_query($this->handler, $sql);
return true;
}
/**
* 清除缓存
* @access public
* @param string $tag 标签名
* @return boolean
*/
public function clear($tag = null)
{
if ($tag) {
$name = sqlite_escape_string($tag);
$sql = 'DELETE FROM ' . $this->options['table'] . ' WHERE tag=\'' . $name . '\'';
sqlite_query($this->handler, $sql);
return true;
}
$this->writeTimes++;
$sql = 'DELETE FROM ' . $this->options['table'];
sqlite_query($this->handler, $sql);
return true;
}
}

View File

@ -1,174 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\cache\driver;
use think\cache\Driver;
/**
* Wincache缓存驱动
* @author liu21st <liu21st@gmail.com>
*/
class Wincache extends Driver
{
protected $options = [
'prefix' => '',
'expire' => 0,
'serialize' => true,
];
/**
* 架构函数
* @access public
* @param array $options 缓存参数
* @throws \BadFunctionCallException
*/
public function __construct($options = [])
{
if (!function_exists('wincache_ucache_info')) {
throw new \BadFunctionCallException('not support: WinCache');
}
if (!empty($options)) {
$this->options = array_merge($this->options, $options);
}
}
/**
* 判断缓存
* @access public
* @param string $name 缓存变量名
* @return bool
*/
public function has($name)
{
$this->readTimes++;
$key = $this->getCacheKey($name);
return wincache_ucache_exists($key);
}
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $default 默认值
* @return mixed
*/
public function get($name, $default = false)
{
$this->readTimes++;
$key = $this->getCacheKey($name);
return wincache_ucache_exists($key) ? $this->unserialize(wincache_ucache_get($key)) : $default;
}
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param integer|\DateTime $expire 有效时间(秒)
* @return boolean
*/
public function set($name, $value, $expire = null)
{
$this->writeTimes++;
if (is_null($expire)) {
$expire = $this->options['expire'];
}
$key = $this->getCacheKey($name);
$expire = $this->getExpireTime($expire);
$value = $this->serialize($value);
if ($this->tag && !$this->has($name)) {
$first = true;
}
if (wincache_ucache_set($key, $value, $expire)) {
isset($first) && $this->setTagItem($key);
return true;
}
return false;
}
/**
* 自增缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
public function inc($name, $step = 1)
{
$this->writeTimes++;
$key = $this->getCacheKey($name);
return wincache_ucache_inc($key, $step);
}
/**
* 自减缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
public function dec($name, $step = 1)
{
$this->writeTimes++;
$key = $this->getCacheKey($name);
return wincache_ucache_dec($key, $step);
}
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @return boolean
*/
public function rm($name)
{
$this->writeTimes++;
return wincache_ucache_delete($this->getCacheKey($name));
}
/**
* 清除缓存
* @access public
* @param string $tag 标签名
* @return boolean
*/
public function clear($tag = null)
{
if ($tag) {
$keys = $this->getTagItem($tag);
foreach ($keys as $key) {
wincache_ucache_delete($key);
}
$this->rm('tag_' . md5($tag));
return true;
} else {
$this->writeTimes++;
return wincache_ucache_clear();
}
}
}

View File

@ -1,177 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\cache\driver;
use think\cache\Driver;
/**
* Xcache缓存驱动
* @author liu21st <liu21st@gmail.com>
*/
class Xcache extends Driver
{
protected $options = [
'prefix' => '',
'expire' => 0,
'serialize' => true,
];
/**
* 架构函数
* @access public
* @param array $options 缓存参数
* @throws \BadFunctionCallException
*/
public function __construct($options = [])
{
if (!function_exists('xcache_info')) {
throw new \BadFunctionCallException('not support: Xcache');
}
if (!empty($options)) {
$this->options = array_merge($this->options, $options);
}
}
/**
* 判断缓存
* @access public
* @param string $name 缓存变量名
* @return bool
*/
public function has($name)
{
$key = $this->getCacheKey($name);
return xcache_isset($key);
}
/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $default 默认值
* @return mixed
*/
public function get($name, $default = false)
{
$this->readTimes++;
$key = $this->getCacheKey($name);
return xcache_isset($key) ? $this->unserialize(xcache_get($key)) : $default;
}
/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param integer|\DateTime $expire 有效时间(秒)
* @return boolean
*/
public function set($name, $value, $expire = null)
{
$this->writeTimes++;
if (is_null($expire)) {
$expire = $this->options['expire'];
}
if ($this->tag && !$this->has($name)) {
$first = true;
}
$key = $this->getCacheKey($name);
$expire = $this->getExpireTime($expire);
$value = $this->serialize($value);
if (xcache_set($key, $value, $expire)) {
isset($first) && $this->setTagItem($key);
return true;
}
return false;
}
/**
* 自增缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
public function inc($name, $step = 1)
{
$this->writeTimes++;
$key = $this->getCacheKey($name);
return xcache_inc($key, $step);
}
/**
* 自减缓存(针对数值缓存)
* @access public
* @param string $name 缓存变量名
* @param int $step 步长
* @return false|int
*/
public function dec($name, $step = 1)
{
$this->writeTimes++;
$key = $this->getCacheKey($name);
return xcache_dec($key, $step);
}
/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @return boolean
*/
public function rm($name)
{
$this->writeTimes++;
return xcache_unset($this->getCacheKey($name));
}
/**
* 清除缓存
* @access public
* @param string $tag 标签名
* @return boolean
*/
public function clear($tag = null)
{
if ($tag) {
// 指定标签清除
$keys = $this->getTagItem($tag);
foreach ($keys as $key) {
xcache_unset($key);
}
$this->rm('tag_' . md5($tag));
return true;
}
$this->writeTimes++;
if (function_exists('xcache_unset_by_prefix')) {
return xcache_unset_by_prefix($this->options['prefix']);
} else {
return false;
}
}
}

View File

@ -1,24 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\config\driver;
class Ini
{
public function parse($config)
{
if (is_file($config)) {
return parse_ini_file($config, true);
} else {
return parse_ini_string($config, true);
}
}
}

View File

@ -1,26 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\config\driver;
class Json
{
public function parse($config)
{
if (is_file($config)) {
$config = file_get_contents($config);
}
$result = json_decode($config, true);
return $result;
}
}

View File

@ -1,33 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\config\driver;
class Xml
{
public function parse($config)
{
if (is_file($config)) {
$content = simplexml_load_file($config);
} else {
$content = simplexml_load_string($config);
}
$result = (array) $content;
foreach ($result as $key => $val) {
if (is_object($val)) {
$result[$key] = (array) $val;
}
}
return $result;
}
}

View File

@ -1,470 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think\console;
use think\Console;
use think\console\input\Argument;
use think\console\input\Definition;
use think\console\input\Option;
class Command
{
/** @var Console */
private $console;
private $name;
private $aliases = [];
private $definition;
private $help;
private $description;
private $ignoreValidationErrors = false;
private $consoleDefinitionMerged = false;
private $consoleDefinitionMergedWithArgs = false;
private $code;
private $synopsis = [];
private $usages = [];
/** @var Input */
protected $input;
/** @var Output */
protected $output;
/**
* 构造方法
* @param string|null $name 命令名称,如果没有设置则比如在 configure() 里设置
* @throws \LogicException
* @api
*/
public function __construct($name = null)
{
$this->definition = new Definition();
if (null !== $name) {
$this->setName($name);
}
$this->configure();
if (!$this->name) {
throw new \LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this)));
}
}
/**
* 忽略验证错误
*/
public function ignoreValidationErrors()
{
$this->ignoreValidationErrors = true;
}
/**
* 设置控制台
* @param Console $console
*/
public function setConsole(Console $console = null)
{
$this->console = $console;
}
/**
* 获取控制台
* @return Console
* @api
*/
public function getConsole()
{
return $this->console;
}
/**
* 是否有效
* @return bool
*/
public function isEnabled()
{
return true;
}
/**
* 配置指令
*/
protected function configure()
{
}
/**
* 执行指令
* @param Input $input
* @param Output $output
* @return null|int
* @throws \LogicException
* @see setCode()
*/
protected function execute(Input $input, Output $output)
{
throw new \LogicException('You must override the execute() method in the concrete command class.');
}
/**
* 用户验证
* @param Input $input
* @param Output $output
*/
protected function interact(Input $input, Output $output)
{
}
/**
* 初始化
* @param Input $input An InputInterface instance
* @param Output $output An OutputInterface instance
*/
protected function initialize(Input $input, Output $output)
{
}
/**
* 执行
* @param Input $input
* @param Output $output
* @return int
* @throws \Exception
* @see setCode()
* @see execute()
*/
public function run(Input $input, Output $output)
{
$this->input = $input;
$this->output = $output;
$this->getSynopsis(true);
$this->getSynopsis(false);
$this->mergeConsoleDefinition();
try {
$input->bind($this->definition);
} catch (\Exception $e) {
if (!$this->ignoreValidationErrors) {
throw $e;
}
}
$this->initialize($input, $output);
if ($input->isInteractive()) {
$this->interact($input, $output);
}
$input->validate();
if ($this->code) {
$statusCode = call_user_func($this->code, $input, $output);
} else {
$statusCode = $this->execute($input, $output);
}
return is_numeric($statusCode) ? (int) $statusCode : 0;
}
/**
* 设置执行代码
* @param callable $code callable(InputInterface $input, OutputInterface $output)
* @return Command
* @throws \InvalidArgumentException
* @see execute()
*/
public function setCode(callable $code)
{
if (!is_callable($code)) {
throw new \InvalidArgumentException('Invalid callable provided to Command::setCode.');
}
if (PHP_VERSION_ID >= 50400 && $code instanceof \Closure) {
$r = new \ReflectionFunction($code);
if (null === $r->getClosureThis()) {
$code = \Closure::bind($code, $this);
}
}
$this->code = $code;
return $this;
}
/**
* 合并参数定义
* @param bool $mergeArgs
*/
public function mergeConsoleDefinition($mergeArgs = true)
{
if (null === $this->console
|| (true === $this->consoleDefinitionMerged
&& ($this->consoleDefinitionMergedWithArgs || !$mergeArgs))
) {
return;
}
if ($mergeArgs) {
$currentArguments = $this->definition->getArguments();
$this->definition->setArguments($this->console->getDefinition()->getArguments());
$this->definition->addArguments($currentArguments);
}
$this->definition->addOptions($this->console->getDefinition()->getOptions());
$this->consoleDefinitionMerged = true;
if ($mergeArgs) {
$this->consoleDefinitionMergedWithArgs = true;
}
}
/**
* 设置参数定义
* @param array|Definition $definition
* @return Command
* @api
*/
public function setDefinition($definition)
{
if ($definition instanceof Definition) {
$this->definition = $definition;
} else {
$this->definition->setDefinition($definition);
}
$this->consoleDefinitionMerged = false;
return $this;
}
/**
* 获取参数定义
* @return Definition
* @api
*/
public function getDefinition()
{
return $this->definition;
}
/**
* 获取当前指令的参数定义
* @return Definition
*/
public function getNativeDefinition()
{
return $this->getDefinition();
}
/**
* 添加参数
* @param string $name 名称
* @param int $mode 类型
* @param string $description 描述
* @param mixed $default 默认值
* @return Command
*/
public function addArgument($name, $mode = null, $description = '', $default = null)
{
$this->definition->addArgument(new Argument($name, $mode, $description, $default));
return $this;
}
/**
* 添加选项
* @param string $name 选项名称
* @param string $shortcut 别名
* @param int $mode 类型
* @param string $description 描述
* @param mixed $default 默认值
* @return Command
*/
public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
{
$this->definition->addOption(new Option($name, $shortcut, $mode, $description, $default));
return $this;
}
/**
* 设置指令名称
* @param string $name
* @return Command
* @throws \InvalidArgumentException
*/
public function setName($name)
{
$this->validateName($name);
$this->name = $name;
return $this;
}
/**
* 获取指令名称
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* 设置描述
* @param string $description
* @return Command
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* 获取描述
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* 设置帮助信息
* @param string $help
* @return Command
*/
public function setHelp($help)
{
$this->help = $help;
return $this;
}
/**
* 获取帮助信息
* @return string
*/
public function getHelp()
{
return $this->help;
}
/**
* 描述信息
* @return string
*/
public function getProcessedHelp()
{
$name = $this->name;
$placeholders = [
'%command.name%',
'%command.full_name%',
];
$replacements = [
$name,
$_SERVER['PHP_SELF'] . ' ' . $name,
];
return str_replace($placeholders, $replacements, $this->getHelp());
}
/**
* 设置别名
* @param string[] $aliases
* @return Command
* @throws \InvalidArgumentException
*/
public function setAliases($aliases)
{
if (!is_array($aliases) && !$aliases instanceof \Traversable) {
throw new \InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
}
foreach ($aliases as $alias) {
$this->validateName($alias);
}
$this->aliases = $aliases;
return $this;
}
/**
* 获取别名
* @return array
*/
public function getAliases()
{
return $this->aliases;
}
/**
* 获取简介
* @param bool $short 是否简单的
* @return string
*/
public function getSynopsis($short = false)
{
$key = $short ? 'short' : 'long';
if (!isset($this->synopsis[$key])) {
$this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
}
return $this->synopsis[$key];
}
/**
* 添加用法介绍
* @param string $usage
* @return $this
*/
public function addUsage($usage)
{
if (0 !== strpos($usage, $this->name)) {
$usage = sprintf('%s %s', $this->name, $usage);
}
$this->usages[] = $usage;
return $this;
}
/**
* 获取用法介绍
* @return array
*/
public function getUsages()
{
return $this->usages;
}
/**
* 验证指令名称
* @param string $name
* @throws \InvalidArgumentException
*/
private function validateName($name)
{
if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
throw new \InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
}
}
}

View File

@ -1,464 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think\console;
use think\console\input\Argument;
use think\console\input\Definition;
use think\console\input\Option;
class Input
{
/**
* @var Definition
*/
protected $definition;
/**
* @var Option[]
*/
protected $options = [];
/**
* @var Argument[]
*/
protected $arguments = [];
protected $interactive = true;
private $tokens;
private $parsed;
public function __construct($argv = null)
{
if (null === $argv) {
$argv = $_SERVER['argv'];
// 去除命令名
array_shift($argv);
}
$this->tokens = $argv;
$this->definition = new Definition();
}
protected function setTokens(array $tokens)
{
$this->tokens = $tokens;
}
/**
* 绑定实例
* @param Definition $definition A InputDefinition instance
*/
public function bind(Definition $definition)
{
$this->arguments = [];
$this->options = [];
$this->definition = $definition;
$this->parse();
}
/**
* 解析参数
*/
protected function parse()
{
$parseOptions = true;
$this->parsed = $this->tokens;
while (null !== $token = array_shift($this->parsed)) {
if ($parseOptions && '' == $token) {
$this->parseArgument($token);
} elseif ($parseOptions && '--' == $token) {
$parseOptions = false;
} elseif ($parseOptions && 0 === strpos($token, '--')) {
$this->parseLongOption($token);
} elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
$this->parseShortOption($token);
} else {
$this->parseArgument($token);
}
}
}
/**
* 解析短选项
* @param string $token 当前的指令.
*/
private function parseShortOption($token)
{
$name = substr($token, 1);
if (strlen($name) > 1) {
if ($this->definition->hasShortcut($name[0])
&& $this->definition->getOptionForShortcut($name[0])->acceptValue()
) {
$this->addShortOption($name[0], substr($name, 1));
} else {
$this->parseShortOptionSet($name);
}
} else {
$this->addShortOption($name, null);
}
}
/**
* 解析短选项
* @param string $name 当前指令
* @throws \RuntimeException
*/
private function parseShortOptionSet($name)
{
$len = strlen($name);
for ($i = 0; $i < $len; ++$i) {
if (!$this->definition->hasShortcut($name[$i])) {
throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i]));
}
$option = $this->definition->getOptionForShortcut($name[$i]);
if ($option->acceptValue()) {
$this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
break;
} else {
$this->addLongOption($option->getName(), null);
}
}
}
/**
* 解析完整选项
* @param string $token 当前指令
*/
private function parseLongOption($token)
{
$name = substr($token, 2);
if (false !== $pos = strpos($name, '=')) {
$this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1));
} else {
$this->addLongOption($name, null);
}
}
/**
* 解析参数
* @param string $token 当前指令
* @throws \RuntimeException
*/
private function parseArgument($token)
{
$c = count($this->arguments);
if ($this->definition->hasArgument($c)) {
$arg = $this->definition->getArgument($c);
$this->arguments[$arg->getName()] = $arg->isArray() ? [$token] : $token;
} elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
$arg = $this->definition->getArgument($c - 1);
$this->arguments[$arg->getName()][] = $token;
} else {
throw new \RuntimeException('Too many arguments.');
}
}
/**
* 添加一个短选项的值
* @param string $shortcut 短名称
* @param mixed $value
* @throws \RuntimeException
*/
private function addShortOption($shortcut, $value)
{
if (!$this->definition->hasShortcut($shortcut)) {
throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
}
$this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
}
/**
* 添加一个完整选项的值
* @param string $name 选项名
* @param mixed $value
* @throws \RuntimeException
*/
private function addLongOption($name, $value)
{
if (!$this->definition->hasOption($name)) {
throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name));
}
$option = $this->definition->getOption($name);
if (false === $value) {
$value = null;
}
if (null !== $value && !$option->acceptValue()) {
throw new \RuntimeException(sprintf('The "--%s" option does not accept a value.', $name, $value));
}
if (null === $value && $option->acceptValue() && count($this->parsed)) {
$next = array_shift($this->parsed);
if (isset($next[0]) && '-' !== $next[0]) {
$value = $next;
} elseif (empty($next)) {
$value = '';
} else {
array_unshift($this->parsed, $next);
}
}
if (null === $value) {
if ($option->isValueRequired()) {
throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name));
}
if (!$option->isArray()) {
$value = $option->isValueOptional() ? $option->getDefault() : true;
}
}
if ($option->isArray()) {
$this->options[$name][] = $value;
} else {
$this->options[$name] = $value;
}
}
/**
* 获取第一个参数
* @return string|null
*/
public function getFirstArgument()
{
foreach ($this->tokens as $token) {
if ($token && '-' === $token[0]) {
continue;
}
return $token;
}
return;
}
/**
* 检查原始参数是否包含某个值
* @param string|array $values 需要检查的值
* @return bool
*/
public function hasParameterOption($values)
{
$values = (array) $values;
foreach ($this->tokens as $token) {
foreach ($values as $value) {
if ($token === $value || 0 === strpos($token, $value . '=')) {
return true;
}
}
}
return false;
}
/**
* 获取原始选项的值
* @param string|array $values 需要检查的值
* @param mixed $default 默认值
* @return mixed The option value
*/
public function getParameterOption($values, $default = false)
{
$values = (array) $values;
$tokens = $this->tokens;
while (0 < count($tokens)) {
$token = array_shift($tokens);
foreach ($values as $value) {
if ($token === $value || 0 === strpos($token, $value . '=')) {
if (false !== $pos = strpos($token, '=')) {
return substr($token, $pos + 1);
}
return array_shift($tokens);
}
}
}
return $default;
}
/**
* 验证输入
* @throws \RuntimeException
*/
public function validate()
{
if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) {
throw new \RuntimeException('Not enough arguments.');
}
}
/**
* 检查输入是否是交互的
* @return bool
*/
public function isInteractive()
{
return $this->interactive;
}
/**
* 设置输入的交互
* @param bool
*/
public function setInteractive($interactive)
{
$this->interactive = (bool) $interactive;
}
/**
* 获取所有的参数
* @return Argument[]
*/
public function getArguments()
{
return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
}
/**
* 根据名称获取参数
* @param string $name 参数名
* @return mixed
* @throws \InvalidArgumentException
*/
public function getArgument($name)
{
if (!$this->definition->hasArgument($name)) {
throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
}
return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)
->getDefault();
}
/**
* 设置参数的值
* @param string $name 参数名
* @param string $value
* @throws \InvalidArgumentException
*/
public function setArgument($name, $value)
{
if (!$this->definition->hasArgument($name)) {
throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
}
$this->arguments[$name] = $value;
}
/**
* 检查是否存在某个参数
* @param string|int $name 参数名或位置
* @return bool
*/
public function hasArgument($name)
{
return $this->definition->hasArgument($name);
}
/**
* 获取所有的选项
* @return Option[]
*/
public function getOptions()
{
return array_merge($this->definition->getOptionDefaults(), $this->options);
}
/**
* 获取选项值
* @param string $name 选项名称
* @return mixed
* @throws \InvalidArgumentException
*/
public function getOption($name)
{
if (!$this->definition->hasOption($name)) {
throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
}
return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
}
/**
* 设置选项值
* @param string $name 选项名
* @param string|bool $value
* @throws \InvalidArgumentException
*/
public function setOption($name, $value)
{
if (!$this->definition->hasOption($name)) {
throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
}
$this->options[$name] = $value;
}
/**
* 是否有某个选项
* @param string $name 选项名
* @return bool
*/
public function hasOption($name)
{
return $this->definition->hasOption($name) && isset($this->options[$name]);
}
/**
* 转义指令
* @param string $token
* @return string
*/
public function escapeToken($token)
{
return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
}
/**
* 返回传递给命令的参数的字符串
* @return string
*/
public function __toString()
{
$tokens = array_map(function ($token) {
if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
return $match[1] . $this->escapeToken($match[2]);
}
if ($token && '-' !== $token[0]) {
return $this->escapeToken($token);
}
return $token;
}, $this->tokens);
return implode(' ', $tokens);
}
}

View File

@ -1,19 +0,0 @@
Copyright (c) 2004-2016 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -1,222 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think\console;
use Exception;
use think\console\output\Ask;
use think\console\output\Descriptor;
use think\console\output\driver\Buffer;
use think\console\output\driver\Console;
use think\console\output\driver\Nothing;
use think\console\output\Question;
use think\console\output\question\Choice;
use think\console\output\question\Confirmation;
/**
* Class Output
* @package think\console
*
* @see \think\console\output\driver\Console::setDecorated
* @method void setDecorated($decorated)
*
* @see \think\console\output\driver\Buffer::fetch
* @method string fetch()
*
* @method void info($message)
* @method void error($message)
* @method void comment($message)
* @method void warning($message)
* @method void highlight($message)
* @method void question($message)
*/
class Output
{
const VERBOSITY_QUIET = 0;
const VERBOSITY_NORMAL = 1;
const VERBOSITY_VERBOSE = 2;
const VERBOSITY_VERY_VERBOSE = 3;
const VERBOSITY_DEBUG = 4;
const OUTPUT_NORMAL = 0;
const OUTPUT_RAW = 1;
const OUTPUT_PLAIN = 2;
private $verbosity = self::VERBOSITY_NORMAL;
/** @var Buffer|Console|Nothing */
private $handle = null;
protected $styles = [
'info',
'error',
'comment',
'question',
'highlight',
'warning'
];
public function __construct($driver = 'console')
{
$class = '\\think\\console\\output\\driver\\' . ucwords($driver);
$this->handle = new $class($this);
}
public function ask(Input $input, $question, $default = null, $validator = null)
{
$question = new Question($question, $default);
$question->setValidator($validator);
return $this->askQuestion($input, $question);
}
public function askHidden(Input $input, $question, $validator = null)
{
$question = new Question($question);
$question->setHidden(true);
$question->setValidator($validator);
return $this->askQuestion($input, $question);
}
public function confirm(Input $input, $question, $default = true)
{
return $this->askQuestion($input, new Confirmation($question, $default));
}
/**
* {@inheritdoc}
*/
public function choice(Input $input, $question, array $choices, $default = null)
{
if (null !== $default) {
$values = array_flip($choices);
$default = $values[$default];
}
return $this->askQuestion($input, new Choice($question, $choices, $default));
}
protected function askQuestion(Input $input, Question $question)
{
$ask = new Ask($input, $this, $question);
$answer = $ask->run();
if ($input->isInteractive()) {
$this->newLine();
}
return $answer;
}
protected function block($style, $message)
{
$this->writeln("<{$style}>{$message}</$style>");
}
/**
* 输出空行
* @param int $count
*/
public function newLine($count = 1)
{
$this->write(str_repeat(PHP_EOL, $count));
}
/**
* 输出信息并换行
* @param string $messages
* @param int $type
*/
public function writeln($messages, $type = self::OUTPUT_NORMAL)
{
$this->write($messages, true, $type);
}
/**
* 输出信息
* @param string $messages
* @param bool $newline
* @param int $type
*/
public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
{
$this->handle->write($messages, $newline, $type);
}
public function renderException(\Exception $e)
{
$this->handle->renderException($e);
}
/**
* {@inheritdoc}
*/
public function setVerbosity($level)
{
$this->verbosity = (int) $level;
}
/**
* {@inheritdoc}
*/
public function getVerbosity()
{
return $this->verbosity;
}
public function isQuiet()
{
return self::VERBOSITY_QUIET === $this->verbosity;
}
public function isVerbose()
{
return self::VERBOSITY_VERBOSE <= $this->verbosity;
}
public function isVeryVerbose()
{
return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
}
public function isDebug()
{
return self::VERBOSITY_DEBUG <= $this->verbosity;
}
public function describe($object, array $options = [])
{
$descriptor = new Descriptor();
$options = array_merge([
'raw_text' => false,
], $options);
$descriptor->describe($this, $object, $options);
}
public function __call($method, $args)
{
if (in_array($method, $this->styles)) {
array_unshift($args, $method);
return call_user_func_array([$this, 'block'], $args);
}
if ($this->handle && method_exists($this->handle, $method)) {
return call_user_func_array([$this->handle, $method], $args);
} else {
throw new Exception('method not exists:' . __CLASS__ . '->' . $method);
}
}
}

View File

@ -1 +0,0 @@
console 工具使用 hiddeninput.exe 在 windows 上隐藏密码输入,该二进制文件由第三方提供,相关源码和其他细节可以在 [Hidden Input](https://github.com/Seldaek/hidden-input) 找到。

View File

@ -1,60 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think\console\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Option;
use think\console\Output;
use think\facade\App;
use think\facade\Build as AppBuild;
class Build extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
$this->setName('build')
->setDefinition([
new Option('config', null, Option::VALUE_OPTIONAL, "build.php path"),
new Option('module', null, Option::VALUE_OPTIONAL, "module name"),
])
->setDescription('Build Application Dirs');
}
protected function execute(Input $input, Output $output)
{
if ($input->hasOption('module')) {
AppBuild::module($input->getOption('module'));
$output->writeln("Successed");
return;
}
if ($input->hasOption('config')) {
$build = include $input->getOption('config');
} else {
$build = include App::getAppPath() . 'build.php';
}
if (empty($build)) {
$output->writeln("Build Config Is Empty");
return;
}
AppBuild::run($build);
$output->writeln("Successed");
}
}

View File

@ -1,45 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\console\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Option;
use think\console\Output;
use think\facade\App;
class Clear extends Command
{
protected function configure()
{
// 指令配置
$this
->setName('clear')
->addOption('path', 'd', Option::VALUE_OPTIONAL, 'path to clear', null)
->setDescription('Clear runtime file');
}
protected function execute(Input $input, Output $output)
{
$path = $input->getOption('path') ?: App::getRuntimePath();
$files = scandir($path);
if ($files) {
foreach ($files as $file) {
if ('.' != $file && '..' != $file && is_dir($path . $file)) {
array_map('unlink', glob($path . $file . '/*.*'));
} elseif ('.gitignore' != $file && is_file($path . $file)) {
unlink($path . $file);
}
}
}
$output->writeln("<info>Clear Successed</info>");
}
}

View File

@ -1,69 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think\console\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument as InputArgument;
use think\console\input\Option as InputOption;
use think\console\Output;
class Help extends Command
{
private $command;
/**
* {@inheritdoc}
*/
protected function configure()
{
$this->ignoreValidationErrors();
$this->setName('help')->setDefinition([
new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
])->setDescription('Displays help for a command')->setHelp(<<<EOF
The <info>%command.name%</info> command displays help for a given command:
<info>php %command.full_name% list</info>
To display the list of available commands, please use the <info>list</info> command.
EOF
);
}
/**
* Sets the command.
* @param Command $command The command to set
*/
public function setCommand(Command $command)
{
$this->command = $command;
}
/**
* {@inheritdoc}
*/
protected function execute(Input $input, Output $output)
{
if (null === $this->command) {
$this->command = $this->getConsole()->find($input->getArgument('command_name'));
}
$output->describe($this->command, [
'raw_text' => $input->getOption('raw'),
]);
$this->command = null;
}
}

View File

@ -1,74 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think\console\command;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\console\input\Argument as InputArgument;
use think\console\input\Option as InputOption;
use think\console\input\Definition as InputDefinition;
class Lists extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
$this->setName('list')->setDefinition($this->createDefinition())->setDescription('Lists commands')->setHelp(<<<EOF
The <info>%command.name%</info> command lists all commands:
<info>php %command.full_name%</info>
You can also display the commands for a specific namespace:
<info>php %command.full_name% test</info>
It's also possible to get raw list of commands (useful for embedding command runner):
<info>php %command.full_name% --raw</info>
EOF
);
}
/**
* {@inheritdoc}
*/
public function getNativeDefinition()
{
return $this->createDefinition();
}
/**
* {@inheritdoc}
*/
protected function execute(Input $input, Output $output)
{
$output->describe($this->getConsole(), [
'raw_text' => $input->getOption('raw'),
'namespace' => $input->getArgument('namespace'),
]);
}
/**
* {@inheritdoc}
*/
private function createDefinition()
{
return new InputDefinition([
new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list')
]);
}
}

View File

@ -1,111 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 刘志淳 <chun@engineer.com>
// +----------------------------------------------------------------------
namespace think\console\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\Output;
use think\facade\App;
use think\facade\Config;
use think\facade\Env;
abstract class Make extends Command
{
protected $type;
abstract protected function getStub();
protected function configure()
{
$this->addArgument('name', Argument::REQUIRED, "The name of the class");
}
protected function execute(Input $input, Output $output)
{
$name = trim($input->getArgument('name'));
$classname = $this->getClassName($name);
$pathname = $this->getPathName($classname);
if (is_file($pathname)) {
$output->writeln('<error>' . $this->type . ' already exists!</error>');
return false;
}
if (!is_dir(dirname($pathname))) {
mkdir(strtolower(dirname($pathname)), 0755, true);
}
file_put_contents($pathname, $this->buildClass($classname));
$output->writeln('<info>' . $this->type . ' created successfully.</info>');
}
protected function buildClass($name)
{
$stub = file_get_contents($this->getStub());
$namespace = trim(implode('\\', array_slice(explode('\\', $name), 0, -1)), '\\');
$class = str_replace($namespace . '\\', '', $name);
return str_replace(['{%className%}', '{%namespace%}', '{%app_namespace%}'], [
$class,
$namespace,
App::getNamespace(),
], $stub);
}
protected function getPathName($name)
{
$name = str_replace(App::getNamespace() . '\\', '', $name);
return Env::get('app_path') . ltrim(str_replace('\\', '/', $name), '/') . '.php';
}
protected function getClassName($name)
{
$appNamespace = App::getNamespace();
if (strpos($name, $appNamespace . '\\') !== false) {
return $name;
}
if (Config::get('app_multi_module')) {
if (strpos($name, '/')) {
list($module, $name) = explode('/', $name, 2);
} else {
$module = 'common';
}
} else {
$module = null;
}
if (strpos($name, '/') !== false) {
$name = str_replace('/', '\\', $name);
}
return $this->getNamespace($appNamespace, $module) . '\\' . $name;
}
protected function getNamespace($appNamespace, $module)
{
return $module ? ($appNamespace . '\\' . $module) : $appNamespace;
}
}

View File

@ -1,54 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: Slince <taosikai@yeah.net>
// +----------------------------------------------------------------------
namespace think\console\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Option;
use think\console\Output;
use think\facade\App;
class RunServer extends Command
{
public function configure()
{
$this->setName('run')
->addOption('host', 'H', Option::VALUE_OPTIONAL,
'The host to server the application on', '127.0.0.1')
->addOption('port', 'p', Option::VALUE_OPTIONAL,
'The port to server the application on', 8000)
->addOption('root', 'r', Option::VALUE_OPTIONAL,
'The document root of the application', App::getRootPath() . 'public')
->setDescription('PHP Built-in Server for ThinkPHP');
}
public function execute(Input $input, Output $output)
{
$host = $input->getOption('host');
$port = $input->getOption('port');
$root = $input->getOption('root');
$command = sprintf(
'php -S %s:%d -t %s %s',
$host,
$port,
escapeshellarg($root),
escapeshellarg($root . '/router.php')
);
$output->writeln(sprintf('ThinkPHP Development server is started On <http://%s:%s/>', $host, $port));
$output->writeln(sprintf('You can exit with <info>`CTRL-C`</info>'));
$output->writeln(sprintf('Document root is: %s', $root));
passthru($command);
}
}

View File

@ -1,50 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 刘志淳 <chun@engineer.com>
// +----------------------------------------------------------------------
namespace think\console\command\make;
use think\console\command\Make;
use think\console\input\Option;
use think\facade\Config;
class Controller extends Make
{
protected $type = "Controller";
protected function configure()
{
parent::configure();
$this->setName('make:controller')
->addOption('plain', null, Option::VALUE_NONE, 'Generate an empty controller class.')
->setDescription('Create a new resource controller class');
}
protected function getStub()
{
if ($this->input->getOption('plain')) {
return __DIR__ . '/stubs/controller.plain.stub';
}
return __DIR__ . '/stubs/controller.stub';
}
protected function getClassName($name)
{
return parent::getClassName($name) . (Config::get('controller_suffix') ? ucfirst(Config::get('url_controller_layer')) : '');
}
protected function getNamespace($appNamespace, $module)
{
return parent::getNamespace($appNamespace, $module) . '\controller';
}
}

View File

@ -1,36 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 刘志淳 <chun@engineer.com>
// +----------------------------------------------------------------------
namespace think\console\command\make;
use think\console\command\Make;
class Model extends Make
{
protected $type = "Model";
protected function configure()
{
parent::configure();
$this->setName('make:model')
->setDescription('Create a new model class');
}
protected function getStub()
{
return __DIR__ . '/stubs/model.stub';
}
protected function getNamespace($appNamespace, $module)
{
return parent::getNamespace($appNamespace, $module) . '\model';
}
}

View File

@ -1,10 +0,0 @@
<?php
namespace {%namespace%};
use think\Controller;
class {%className%} extends Controller
{
//
}

View File

@ -1,85 +0,0 @@
<?php
namespace {%namespace%};
use think\Controller;
use think\Request;
class {%className%} extends Controller
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
//
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function create()
{
//
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
//
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read($id)
{
//
}
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit($id)
{
//
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
{
//
}
}

View File

@ -1,10 +0,0 @@
<?php
namespace {%namespace%};
use think\Model;
class {%className%} extends Model
{
//
}

View File

@ -1,280 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think\console\command\optimize;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Container;
class Autoload extends Command
{
protected function configure()
{
$this->setName('optimize:autoload')
->setDescription('Optimizes PSR0 and PSR4 packages to be loaded with classmaps too, good for production.');
}
protected function execute(Input $input, Output $output)
{
$classmapFile = <<<EOF
<?php
/**
* 类库映射
*/
return [
EOF;
$app = Container::get('app');
$namespacesToScan = [
$app->getNamespace() . '\\' => realpath(rtrim($app->getAppPath())),
'think\\' => $app->getAppPath() . 'library/think',
'traits\\' => $app->getAppPath() . 'library/traits',
'' => realpath(rtrim($app->getRootPath() . 'extend')),
];
krsort($namespacesToScan);
$classMap = [];
foreach ($namespacesToScan as $namespace => $dir) {
if (!is_dir($dir)) {
continue;
}
$namespaceFilter = '' === $namespace ? null : $namespace;
$classMap = $this->addClassMapCode($dir, $namespaceFilter, $classMap);
}
ksort($classMap);
foreach ($classMap as $class => $code) {
$classmapFile .= ' ' . var_export($class, true) . ' => ' . $code;
}
$classmapFile .= "];\n";
$runtimePath = $app->getRuntimePath();
if (!is_dir($runtimePath)) {
@mkdir($runtimePath, 0755, true);
}
file_put_contents($runtimePath . 'classmap.php', $classmapFile);
$output->writeln('<info>Succeed!</info>');
}
protected function addClassMapCode($dir, $namespace, $classMap)
{
foreach ($this->createMap($dir, $namespace) as $class => $path) {
$pathCode = $this->getPathCode($path) . ",\n";
if (!isset($classMap[$class])) {
$classMap[$class] = $pathCode;
} elseif ($classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class] . ' ' . $path, '\\', '/'))) {
$this->output->writeln(
'<warning>Warning: Ambiguous class resolution, "' . $class . '"' .
' was found in both "' . str_replace(["',\n"], [
'',
], $classMap[$class]) . '" and "' . $path . '", the first will be used.</warning>'
);
}
}
return $classMap;
}
protected function getPathCode($path)
{
$baseDir = '';
$app = Container::get('app');
$appPath = $this->normalizePath(realpath($app->getAppPath()));
$libPath = $this->normalizePath(realpath($app->getThinkPath() . 'library'));
$extendPath = $this->normalizePath(realpath($app->getRootPath() . 'extend'));
$path = $this->normalizePath($path);
if (strpos($path, $libPath . '/') === 0) {
$path = substr($path, strlen($app->getThinkPath() . 'library'));
$baseDir = "'" . $libPath . "/'";
} elseif (strpos($path, $appPath . '/') === 0) {
$path = substr($path, strlen($appPath) + 1);
$baseDir = "'" . $appPath . "/'";
} elseif (strpos($path, $extendPath . '/') === 0) {
$path = substr($path, strlen($extendPath) + 1);
$baseDir = "'" . $extendPath . "/'";
}
if (false !== $path) {
$baseDir .= " . ";
}
return $baseDir . ((false !== $path) ? var_export($path, true) : "");
}
protected function normalizePath($path)
{
$parts = [];
$path = strtr($path, '\\', '/');
$prefix = '';
$absolute = false;
if (preg_match('{^([0-9a-z]+:(?://(?:[a-z]:)?)?)}i', $path, $match)) {
$prefix = $match[1];
$path = substr($path, strlen($prefix));
}
if (substr($path, 0, 1) === '/') {
$absolute = true;
$path = substr($path, 1);
}
$up = false;
foreach (explode('/', $path) as $chunk) {
if ('..' === $chunk && ($absolute || $up)) {
array_pop($parts);
$up = !(empty($parts) || '..' === end($parts));
} elseif ('.' !== $chunk && '' !== $chunk) {
$parts[] = $chunk;
$up = '..' !== $chunk;
}
}
return $prefix . ($absolute ? '/' : '') . implode('/', $parts);
}
protected function createMap($path, $namespace = null)
{
if (is_string($path)) {
if (is_file($path)) {
$path = [new \SplFileInfo($path)];
} elseif (is_dir($path)) {
$objects = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path), \RecursiveIteratorIterator::SELF_FIRST);
$path = [];
/** @var \SplFileInfo $object */
foreach ($objects as $object) {
if ($object->isFile() && $object->getExtension() == 'php') {
$path[] = $object;
}
}
} else {
throw new \RuntimeException(
'Could not scan for classes inside "' . $path .
'" which does not appear to be a file nor a folder'
);
}
}
$map = [];
/** @var \SplFileInfo $file */
foreach ($path as $file) {
$filePath = $file->getRealPath();
if (pathinfo($filePath, PATHINFO_EXTENSION) != 'php') {
continue;
}
$classes = $this->findClasses($filePath);
foreach ($classes as $class) {
if (null !== $namespace && 0 !== strpos($class, $namespace)) {
continue;
}
if (!isset($map[$class])) {
$map[$class] = $filePath;
} elseif ($map[$class] !== $filePath && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($map[$class] . ' ' . $filePath, '\\', '/'))) {
$this->output->writeln(
'<warning>Warning: Ambiguous class resolution, "' . $class . '"' .
' was found in both "' . $map[$class] . '" and "' . $filePath . '", the first will be used.</warning>'
);
}
}
}
return $map;
}
protected function findClasses($path)
{
$extraTypes = '|trait';
$contents = @php_strip_whitespace($path);
if (!$contents) {
if (!file_exists($path)) {
$message = 'File at "%s" does not exist, check your classmap definitions';
} elseif (!is_readable($path)) {
$message = 'File at "%s" is not readable, check its permissions';
} elseif ('' === trim(file_get_contents($path))) {
return [];
} else {
$message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted';
}
$error = error_get_last();
if (isset($error['message'])) {
$message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message'];
}
throw new \RuntimeException(sprintf($message, $path));
}
if (!preg_match('{\b(?:class|interface' . $extraTypes . ')\s}i', $contents)) {
return [];
}
// strip heredocs/nowdocs
$contents = preg_replace('{<<<\s*(\'?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\2(?=\r\n|\n|\r|;)}s', 'null', $contents);
// strip strings
$contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
// strip leading non-php code if needed
if (substr($contents, 0, 2) !== '<?') {
$contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
if (0 === $replacements) {
return [];
}
}
// strip non-php blocks in the file
$contents = preg_replace('{\?>.+<\?}s', '?><?', $contents);
// strip trailing non-php code if needed
$pos = strrpos($contents, '?>');
if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
$contents = substr($contents, 0, $pos);
}
preg_match_all('{
(?:
\b(?<![\$:>])(?P<type>class|interface' . $extraTypes . ') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
| \b(?<![\$:>])(?P<ns>namespace) (?P<nsname>\s++[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\s*+\\\\\s*+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+)? \s*+ [\{;]
)
}ix', $contents, $matches);
$classes = [];
$namespace = '';
for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
if (!empty($matches['ns'][$i])) {
$namespace = str_replace([' ', "\t", "\r", "\n"], '', $matches['nsname'][$i]) . '\\';
} else {
$name = $matches['name'][$i];
if (':' === $name[0]) {
$name = 'xhp' . substr(str_replace(['-', ':'], ['_', '__'], $name), 1);
} elseif ('enum' === $matches['type'][$i]) {
$name = rtrim($name, ':');
}
$classes[] = ltrim($namespace . $name, '\\');
}
}
return $classes;
}
}

View File

@ -1,97 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2017 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think\console\command\optimize;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\Output;
use think\Container;
use think\facade\App;
class Config extends Command
{
/** @var Output */
protected $output;
protected function configure()
{
$this->setName('optimize:config')
->addArgument('module', Argument::OPTIONAL, 'Build module config cache .')
->setDescription('Build config and common file cache.');
}
protected function execute(Input $input, Output $output)
{
if ($input->getArgument('module')) {
$module = $input->getArgument('module') . DIRECTORY_SEPARATOR;
} else {
$module = '';
}
$content = '<?php ' . PHP_EOL . $this->buildCacheContent($module);
$runtimePath = App::getRuntimePath();
if (!is_dir($runtimePath . $module)) {
@mkdir($runtimePath . $module, 0755, true);
}
file_put_contents($runtimePath . $module . 'init.php', $content);
$output->writeln('<info>Succeed!</info>');
}
protected function buildCacheContent($module)
{
$content = '// This cache file is automatically generated at:' . date('Y-m-d H:i:s') . PHP_EOL;
$path = realpath(App::getAppPath() . $module) . DIRECTORY_SEPARATOR;
if ($module) {
$configPath = is_dir($path . 'config') ? $path . 'config' : App::getConfigPath() . $module;
} else {
$configPath = App::getConfigPath();
}
$ext = App::getConfigExt();
$config = Container::get('config');
$files = is_dir($configPath) ? scandir($configPath) : [];
foreach ($files as $file) {
if ('.' . pathinfo($file, PATHINFO_EXTENSION) === $ext) {
$filename = $configPath . DIRECTORY_SEPARATOR . $file;
$config->load($filename, pathinfo($file, PATHINFO_FILENAME));
}
}
// 加载行为扩展文件
if (is_file($path . 'tags.php')) {
$content .= PHP_EOL . '\think\facade\Hook::import(' . (var_export(include $path . 'tags.php' ?: [], true)) . ');' . PHP_EOL;
}
// 加载公共文件
if (is_file($path . 'common.php')) {
$common = substr(php_strip_whitespace($path . 'common.php'), 6);
if ($common) {
$content .= PHP_EOL . $common . PHP_EOL;
}
}
if ('' == $module) {
$content .= PHP_EOL . substr(php_strip_whitespace(App::getThinkPath() . 'helper.php'), 6) . PHP_EOL;
}
if (is_file($path . 'provider.php')) {
$content .= PHP_EOL . '\think\Container::getInstance()->bind(' . var_export(include $path . 'provider.php' ?: [], true) . ');' . PHP_EOL;
}
$content .= PHP_EOL . '\think\facade\Config::set(' . var_export($config->get(), true) . ');' . PHP_EOL;
return $content;
}
}

View File

@ -1,64 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think\console\command\optimize;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Container;
class Route extends Command
{
/** @var Output */
protected $output;
protected function configure()
{
$this->setName('optimize:route')
->setDescription('Build route cache.');
}
protected function execute(Input $input, Output $output)
{
file_put_contents(Container::get('app')->getRuntimePath() . 'route.php', $this->buildRouteCache());
$output->writeln('<info>Succeed!</info>');
}
protected function buildRouteCache()
{
Container::get('route')->setName([]);
Container::get('config')->set('url_lazy_route', false);
// 路由检测
$path = Container::get('app')->getRoutePath();
$files = is_dir($path) ? scandir($path) : [];
foreach ($files as $file) {
if (strpos($file, '.php')) {
$filename = $path . DIRECTORY_SEPARATOR . $file;
// 导入路由配置
$rules = include $filename;
if (is_array($rules)) {
Container::get('route')->import($rules);
}
}
}
if (Container::get('config')->get('route_annotation')) {
include Container::get('build')->buildRoute();
}
$content = '<?php ' . PHP_EOL . 'return ';
$content .= var_export(Container::get('route')->getName(), true) . ';';
return $content;
}
}

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