Compare commits

...

11 Commits
5.1.5 ... main

Author SHA1 Message Date
IQ 49129af248 tp6 2019-07-10 00:27:46 +08:00
IQ 779e8b1894 tp6 2019-07-09 17:21:39 +08:00
IQ fe9029032b tp6 2019-07-09 17:19:21 +08:00
IQ 4f94e5d32b tp6 2019-07-09 17:13:17 +08:00
IQ 37b7e65000 tp6 2019-07-09 17:11:27 +08:00
IQ 68626c28e2 tp6 2019-07-09 17:02:51 +08:00
IQ f2f055023f tp6 2019-07-09 16:49:31 +08:00
IQ 5c0638197f tp6.0 2019-04-13 17:00:04 +08:00
IQ eb338ff633 tp6.0 2019-04-13 16:59:45 +08:00
IQ bad0b27de7 tp6.0 2019-04-13 16:58:24 +08:00
IQ 35351c49d5 tp6.0 2019-04-13 14:06:05 +08:00
684 changed files with 71314 additions and 30877 deletions

1
.example.env Normal file
View File

@ -0,0 +1 @@
APP_DEBUG = true [APP] DEFAULT_TIMEZONE = Asia/Shanghai [DATABASE] TYPE = mysql HOSTNAME = 127.0.0.1 DATABASE = test USERNAME = username PASSWORD = password HOSTPORT = 3306 CHARSET = utf8 DEBUG = true [LANG] default_lang = zh-cn

10
.gitignore vendored
View File

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

155
README.md
View File

@ -1,144 +1,41 @@
ThinkPHP 5.1
ThinkPHP 6.0
===============
ThinkPHP5.1对底层架构做了进一步的改进,减少依赖,其主要特性包括:
> 运行环境要求PHP7.1+。
+ 采用容器统一管理对象
+ 支持Facade
+ 注解路由支持
+ 路由跨域请求支持
+ 配置和路由目录独立
+ 取消系统常量
+ 助手函数增强
+ 类库别名机制
+ 增加条件查询
+ 改进查询机制
+ 配置采用二级
+ 依赖注入完善
## 主要新特性
* 采用`PHP7`强类型(严格模式)
* 支持更多的`PSR`规范
* 原生多应用支持
* 更强大和易用的查询
* 全新的事件系统
* 模型事件和数据库事件统一纳入事件系统
* 模板引擎分离出核心
* 内部功能中间件化
* SESSION/Cookie机制改进
* 对Swoole以及协程支持改进
* 对IDE更加友好
* 统一和精简大量用法
> 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
> 上面的目录结构和名称是可以改变的,这取决于你的入口文件和配置参数。
如果需要更新框架使用
~~~
composer update topthink/framework
~~~
## 升级指导
## 文档
原有下面系统类库的命名空间需要调整:
* 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`字段,不建议使用驼峰和中文作为数据表字段命名。
[完全开发手册](https://www.kancloud.cn/manual/thinkphp6_0/content)
## 参与开发
请参阅 [ThinkPHP5 核心框架包](https://github.com/top-think/framework)。
请参阅 [ThinkPHP 核心框架包](https://github.com/top-think/framework)。
## 版权信息
@ -146,7 +43,7 @@ ThinkPHP遵循Apache2开源协议发布并提供免费使用。
本项目包含的第三方源码和二进制文件之版权信息另行标注。
版权所有Copyright © 2006-2018 by ThinkPHP (http://thinkphp.cn)
版权所有Copyright © 2006-2019 by ThinkPHP (http://thinkphp.cn)
All rights reserved。

103
app/BaseController.php Normal file
View File

@ -0,0 +1,103 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
declare (strict_types = 1);
namespace app;
use think\App;
use think\exception\ValidateException;
use think\Validate;
/**
* 控制器基础类
*/
abstract class BaseController
{
/**
* Request实例
* @var \think\Request
*/
protected $request;
/**
* 应用实例
* @var \think\App
*/
protected $app;
/**
* 是否批量验证
* @var bool
*/
protected $batchValidate = false;
/**
* 控制器中间件
* @var array
*/
protected $middleware = [];
/**
* 构造方法
* @access public
* @param App $app 应用对象
*/
public function __construct(App $app)
{
$this->app = $app;
$this->request = $this->app->request;
// 控制器初始化
$this->initialize();
}
// 初始化
protected function initialize()
{}
/**
* 验证数据
* @access protected
* @param array $data 数据
* @param string|array $validate 验证器名或者验证规则数组
* @param array $message 提示信息
* @param bool $batch 是否批量验证
* @return array|string|true
* @throws ValidateException
*/
protected function validate(array $data, $validate, array $message = [], bool $batch = false)
{
if (is_array($validate)) {
$v = new Validate();
$v->rule($validate);
} else {
if (strpos($validate, '.')) {
// 支持场景
list($validate, $scene) = explode('.', $validate);
}
$class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
$v = new $class();
if (!empty($scene)) {
$v->scene($scene);
}
}
$v->message($message);
// 是否批量验证
if ($batch || $this->batchValidate) {
$v->batch(true);
}
return $v->failException(true)->check($data);
}
}

68
app/ExceptionHandle.php Normal file
View File

@ -0,0 +1,68 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace app;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\exception\Handle;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\exception\ValidateException;
use think\Response;
use Throwable;
/**
* 应用异常处理类
*/
class ExceptionHandle extends Handle
{
/**
* 不需要记录信息(日志)的异常类列表
* @var array
*/
protected $ignoreReport = [
HttpException::class,
HttpResponseException::class,
ModelNotFoundException::class,
DataNotFoundException::class,
ValidateException::class,
];
/**
* 记录异常信息(包括日志或者其它方式记录)
*
* @access public
* @param Throwable $exception
* @return void
*/
public function report(Throwable $exception): void
{
// 使用内置的方式记录异常日志
parent::report($exception);
}
/**
* Render an exception into an HTTP response.
*
* @access public
* @param \think\Request $request
* @param Throwable $e
* @return Response
*/
public function render($request, Throwable $e): Response
{
// 添加自定义异常处理机制
// 其他错误交给系统处理
return parent::render($request, $e);
}
}

View File

@ -2,15 +2,16 @@
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
return [
'test' => [
'news/test/index',[]
]
];
namespace app;
class Request extends \think\Request
{
}

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

@ -0,0 +1,17 @@
<?php
namespace app\controller;
use app\BaseController;
class Index extends BaseController
{
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' => [],
'HttpRun' => [],
'HttpEnd' => [],
'LogLevel' => [],
'LogWrite' => [],
],
'subscribe' => [
],
];

12
app/middleware.php Normal file
View File

@ -0,0 +1,12 @@
<?php
return [
// 全局请求缓存
// \think\middleware\CheckRequestCache::class,
// 多语言加载
// \think\middleware\LoadLangPack::class,
// Session初始化
// \think\middleware\SessionInit::class,
// 页面Trace调试
// \think\middleware\TraceDebug::class,
];

19
app/provider.php Normal file
View File

@ -0,0 +1,19 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
use app\ExceptionHandle;
use app\Request;
// 容器Provider定义文件
return [
'think\Request' => Request::class,
'think\exception\Handle' => ExceptionHandle::class,
];

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' => [],
];

26
build.example.php Normal file
View File

@ -0,0 +1,26 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* php think build 自动生成应用的目录结构的定义示例
*/
return [
// 需要自动创建的文件
'__file__' => [],
// 需要自动创建的目录
'__dir__' => ['controller', 'model', 'view'],
// 需要自动创建的控制器
'controller' => ['Index'],
// 需要自动创建的模型
'model' => ['User'],
// 需要自动创建的模板
'view' => ['index/index'],
];

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>
// +----------------------------------------------------------------------
return [
// 生成应用公共文件
'__file__' => ['common.php'],
// 定义demo模块的自动生成 (按照实际定义的文件名生成)
'demo' => [
'__file__' => ['common.php'],
'__dir__' => ['behavior', 'controller', 'model', 'view'],
'controller' => ['Index', 'Test', 'UserType'],
'model' => ['User', 'UserType'],
'view' => ['index/index'],
],
// 其他更多的模块定义
];

View File

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

1001
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -13,126 +13,35 @@
// | 应用设置
// +----------------------------------------------------------------------
use think\facade\Env;
return [
// 应用名称
'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',
'app_host' => Env::get('app.host', ''),
// 应用的命名空间
'app_namespace' => '',
// 是否启用路由
'with_route' => true,
// 是否启用事件
'with_event' => true,
// 自动多应用模式
'auto_multi_app' => false,
// 应用映射(自动多应用模式有效)
'app_map' => [],
// 域名绑定(自动多应用模式有效)
'domain_bind' => [],
// 禁止URL访问的应用列表自动多应用模式有效
'deny_app_list' => [],
// 默认应用
'default_app' => 'index',
// 默认时区
'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' => 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',
'default_timezone' => 'Asia/Shanghai',
// 异常页面的模板文件
'exception_tmpl' => Env::get('think_path') . 'tpl/think_exception.tpl',
'exception_tmpl' => app()->getThinkPath() . 'tpl/think_exception.tpl',
// 错误显示信息,非调试模式有效
'error_message' => '页面错误!请稍后再试~',
'error_message' => '页面错误!请稍后再试~',
// 显示错误信息
'show_error_msg' => false,
// 异常处理handle类 留空使用 \think\exception\Handle
'exception_handle' => '',
'show_error_msg' => false,
];

View File

@ -8,18 +8,32 @@
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
use think\facade\Env;
// +----------------------------------------------------------------------
// | 缓存设置
// +----------------------------------------------------------------------
return [
// 驱动方式
'type' => 'File',
// 缓存保存目录
'path' => '',
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 0,
// 默认缓存驱动
'default' => Env::get('cache.driver', 'file'),
// 缓存连接方式配置
'stores' => [
'file' => [
// 驱动方式
'type' => 'File',
// 缓存保存目录
'path' => app()->getRuntimePath() . 'cache',
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 0,
// 缓存标签前缀
'tag_prefix' => 'tag:',
// 序列化机制 例如 ['serialize', 'unserialize']
'serialize' => [],
],
// 更多的缓存连接
],
];

View File

@ -9,16 +9,13 @@
// | 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);
}
}
}
// +----------------------------------------------------------------------
// | 控制台配置
// +----------------------------------------------------------------------
return [
// 执行用户Windows下无效
'user' => null,
// 指令定义
'commands' => [
],
];

View File

@ -13,8 +13,6 @@
// | Cookie设置
// +----------------------------------------------------------------------
return [
// cookie 名称前缀
'prefix' => '',
// cookie 保存时间
'expire' => 0,
// cookie 保存路径
@ -24,7 +22,7 @@ return [
// cookie 启用安全传输
'secure' => false,
// httponly设置
'httponly' => '',
'httponly' => false,
// 是否使用 setcookie
'setcookie' => true,
];

View File

@ -9,47 +9,62 @@
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
use think\facade\Env;
return [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => '127.0.0.1',
// 数据库名
'database' => '',
// 用户名
'username' => 'root',
// 密码
'password' => '',
// 端口
'hostport' => '',
// 连接dsn
'dsn' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => '',
// 数据库调试模式
'debug' => true,
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 数据集返回类型
'resultset_type' => 'array',
// 默认使用的数据库连接配置
'default' => Env::get('database.driver', 'mysql'),
// 自定义时间查询规则
'time_query_rule' => [],
// 自动写入时间戳字段
'auto_timestamp' => false,
// true为自动识别类型 false关闭
// 字符串则明确指定时间字段类型 支持 int timestamp datetime date
'auto_timestamp' => true,
// 时间字段取出后的默认时间格式
'datetime_format' => 'Y-m-d H:i:s',
// 是否需要进行SQL性能分析
'sql_explain' => false,
// Query类
'query' => '\\think\\db\\Query',
// 数据库连接配置信息
'connections' => [
'mysql' => [
// 数据库类型
'type' => Env::get('database.type', 'mysql'),
// 服务器地址
'hostname' => Env::get('database.hostname', '127.0.0.1'),
// 数据库名
'database' => Env::get('database.database', ''),
// 用户名
'username' => Env::get('database.username', 'root'),
// 密码
'password' => Env::get('database.password', ''),
// 端口
'hostport' => Env::get('database.hostport', '3306'),
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => Env::get('database.charset', 'utf8'),
// 数据库表前缀
'prefix' => Env::get('database.prefix', ''),
// 数据库调试模式
'debug' => Env::get('database.debug', true),
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 是否需要进行SQL性能分析
'sql_explain' => false,
// 是否需要断线重连
'break_reconnect' => false,
],
// 更多的数据库配置信息
],
];

20
config/filesystem.php Normal file
View File

@ -0,0 +1,20 @@
<?php
use think\facade\Env;
return [
'default' => Env::get('filesystem.driver', 'local'),
'disks' => [
'local' => [
'type' => 'local',
'root' => app()->getRuntimePath() . 'storage',
],
'public' => [
'type' => 'local',
'root' => app()->getRootPath() . 'public/storage',
'url' => '/storage',
'visibility' => 'public',
],
// 更多的磁盘配置信息
],
];

37
config/lang.php Normal file
View File

@ -0,0 +1,37 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | 多语言设置
// +----------------------------------------------------------------------
use think\facade\Env;
return [
// 默认语言
'default_lang' => Env::get('lang.default_lang', 'zh-cn'),
// 允许的语言列表
'allow_lang_list' => [],
// 多语言自动侦测变量名
'detect_var' => 'lang',
// 是否使用Cookie记录
'use_cookie' => true,
// 多语言cookie变量
'cookie_var' => 'think_lang',
// 扩展语言包
'extend_list' => [],
// Accept-Language转义为对应语言包名称
'accept_language' => [
'zh-hans-cn' => 'zh-cn',
],
// 是否支持语言分组
'allow_group' => false,
];

View File

@ -8,15 +8,48 @@
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
use think\facade\Env;
// +----------------------------------------------------------------------
// | 日志设置
// +----------------------------------------------------------------------
return [
// 日志记录方式,内置 file socket 支持扩展
'type' => 'File',
// 日志保存目录
'path' => '',
// 默认日志记录通道
'default' => Env::get('log.channel', 'file'),
// 日志记录级别
'level' => [],
'level' => [],
// 日志类型记录的通道 ['error'=>'email',...]
'type_channel' => [],
// 关闭全局日志写入
'close' => false,
// 全局日志处理 支持闭包
'processor' => null,
// 日志通道列表
'channels' => [
'file' => [
// 日志记录方式
'type' => 'File',
// 日志保存目录
'path' => app()->getRuntimePath() . 'log',
// 单文件日志写入
'single' => false,
// 独立日志级别
'apart_level' => [],
// 最大日志文件数量
'max_files' => 0,
// 使用JSON格式记录
'json' => false,
// 日志处理
'processor' => null,
// 关闭通道日志写入
'close' => false,
// 日志输出格式化
'format' => '[%s][%s] %s',
// 是否实时写入
'realtime_write' => false,
],
// 其它日志通道配置
],
];

63
config/route.php Normal file
View File

@ -0,0 +1,63 @@
<?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分隔符
'pathinfo_depr' => '/',
// URL伪静态后缀
'url_html_suffix' => 'html',
// URL普通方式参数 用于自动生成
'url_common_param' => true,
// 是否开启路由延迟解析
'url_lazy_route' => false,
// 是否强制使用路由
'url_route_must' => false,
// 合并路由规则
'route_rule_merge' => false,
// 路由是否完全匹配
'route_complete_match' => 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\.]+',
// 是否自动转换URL中的控制器和操作名
'url_convert' => true,
// 是否开启请求缓存 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

@ -14,13 +14,14 @@
// +----------------------------------------------------------------------
return [
'id' => '',
// session name
'name' => '',
// SESSION_ID的提交变量,解决flash上传跨域
'var_session_id' => '',
// SESSION 前缀
'prefix' => 'think',
// 驱动方式 支持redis memcache memcached
'type' => '',
// 是否自动开启 SESSION
'auto_start' => true,
// 驱动方式 支持file redis memcache memcached
'type' => 'file',
// 过期时间
'expire' => 0,
// 前缀
'prefix' => '',
];

View File

@ -1,21 +1,13 @@
<?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 支持扩展
// 模板引擎类型使用Think
'type' => 'Think',
// 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 3 保持操作方法
'auto_rule' => 1,
// 模板路径
'view_path' => '',
// 模板后缀

View File

@ -10,9 +10,11 @@
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | Trace设置 开启 app_trace 后 有效
// | Trace设置 开启调试模式后有效
// +----------------------------------------------------------------------
return [
// 内置Html Console 支持扩展
'type' => 'Html',
// 内置Html 支持扩展
'type' => 'Html',
// 读取的日志通道名
'channel' => '',
];

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('think', function () {
return 'hello,ThinkPHP6!';
});
Route::get('hello/:name', 'index/hello');
Route::get('news', 'news/test/hello');
return [
];

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,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,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,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,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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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;
}
}

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);
}
}

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,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,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,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,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,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,10 +0,0 @@
<?php
namespace {%namespace%};
use think\Controller;
class {%className%} extends Controller
{
//
}

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;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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\db\builder;
use think\db\Builder;
use think\db\Query;
/**
* mysql数据库驱动
*/
class Mysql extends Builder
{
// 查询表达式解析
protected $parser = [
'parseCompare' => ['=', '<>', '>', '>=', '<', '<='],
'parseLike' => ['LIKE', 'NOT LIKE'],
'parseBetween' => ['NOT BETWEEN', 'BETWEEN'],
'parseIn' => ['NOT IN', 'IN'],
'parseExp' => ['EXP'],
'parseRegexp' => ['REGEXP', 'NOT REGEXP'],
'parseNull' => ['NOT NULL', 'NULL'],
'parseBetweenTime' => ['BETWEEN TIME', 'NOT BETWEEN TIME'],
'parseTime' => ['< TIME', '> TIME', '<= TIME', '>= TIME'],
'parseExists' => ['NOT EXISTS', 'EXISTS'],
];
protected $insertAllSql = '%INSERT% INTO %TABLE% (%FIELD%) VALUES %DATA% %COMMENT%';
protected $updateSql = 'UPDATE %TABLE% %JOIN% SET %SET% %WHERE% %ORDER%%LIMIT% %LOCK%%COMMENT%';
/**
* 生成insertall SQL
* @access public
* @param Query $query 查询对象
* @param array $dataSet 数据集
* @param bool $replace 是否replace
* @return string
*/
public function insertAll(Query $query, $dataSet, $replace = false)
{
$options = $query->getOptions();
// 获取合法的字段
if ('*' == $options['field']) {
$allowFields = $this->connection->getTableFields($options['table']);
} else {
$allowFields = $options['field'];
}
// 获取绑定信息
$bind = $this->connection->getFieldsBind($options['table']);
foreach ($dataSet as $k => $data) {
$data = $this->parseData($query, $data, $allowFields, $bind, '_' . $k);
$values[] = '( ' . implode(',', array_values($data)) . ' )';
if (!isset($insertFields)) {
$insertFields = array_keys($data);
}
}
$fields = [];
foreach ($insertFields as $field) {
$fields[] = $this->parseKey($query, $field);
}
return str_replace(
['%INSERT%', '%TABLE%', '%FIELD%', '%DATA%', '%COMMENT%'],
[
$replace ? 'REPLACE' : 'INSERT',
$this->parseTable($query, $options['table']),
implode(' , ', $fields),
implode(' , ', $values),
$this->parseComment($query, $options['comment']),
],
$this->insertAllSql);
}
/**
* 正则查询
* @access protected
* @param Query $query 查询对象
* @param string $key
* @param string $exp
* @param mixed $value
* @param string $field
* @return string
*/
protected function parseRegexp(Query $query, $key, $exp, $value, $field)
{
return $key . ' ' . $exp . ' ' . $value;
}
/**
* 字段和表名处理
* @access public
* @param Query $query 查询对象
* @param string $key 字段名
* @return string
*/
public function parseKey(Query $query, $key)
{
if (is_int($key)) {
return $key;
}
$key = trim($key);
if (strpos($key, '->') && false === strpos($key, '(')) {
// JSON字段支持
list($field, $name) = explode('->', $key);
$key = 'json_extract(' . $this->parseKey($query, $field) . ', \'$.' . $name . '\')';
} elseif (strpos($key, '.') && !preg_match('/[,\'\"\(\)`\s]/', $key)) {
list($table, $key) = explode('.', $key, 2);
$alias = $query->getOptions('alias');
if ('__TABLE__' == $table) {
$table = $query->getOptions('table');
$table = is_array($table) ? array_shift($table) : $table;
}
if (isset($alias[$table])) {
$table = $alias[$table];
}
}
if (!preg_match('/[,\'\"\*\(\)`.\s]/', $key)) {
$key = '`' . $key . '`';
}
if (isset($table)) {
if (strpos($table, '.')) {
$table = str_replace('.', '`.`', $table);
}
$key = '`' . $table . '`.' . $key;
}
return $key;
}
/**
* field分析
* @access protected
* @param Query $query 查询对象
* @param mixed $fields 字段名
* @return string
*/
protected function parseField(Query $query, $fields)
{
$fieldsStr = parent::parseField($query, $fields);
$options = $query->getOptions();
if (!empty($options['point'])) {
$array = [];
foreach ($options['point'] as $key => $field) {
$key = !is_numeric($key) ? $key : $field;
$array[] = 'AsText(' . $this->parseKey($query, $key) . ') AS ' . $this->parseKey($query, $field);
}
$fieldsStr .= ',' . implode(',', $array);
}
return $fieldsStr;
}
/**
* 数组数据解析
* @access protected
* @param array $data
* @return mixed
*/
protected function parseArrayData($data)
{
list($type, $value) = $data;
switch (strtolower($type)) {
case 'exp':
$result = $value;
break;
case 'point':
$fun = isset($data[2]) ? $data[2] : 'GeomFromText';
$point = isset($data[3]) ? $data[3] : 'POINT';
if (is_array($value)) {
$value = implode(' ', $value);
}
$result = $fun . '(\'' . $point . '(' . $value . ')\')';
break;
default:
$result = false;
}
return $result;
}
/**
* 随机排序
* @access protected
* @param Query $query 查询对象
* @return string
*/
protected function parseRand(Query $query)
{
return 'rand()';
}
}

View File

@ -1,47 +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\exception;
class ThrowableError extends \ErrorException
{
public function __construct(\Throwable $e)
{
if ($e instanceof \ParseError) {
$message = 'Parse error: ' . $e->getMessage();
$severity = E_PARSE;
} elseif ($e instanceof \TypeError) {
$message = 'Type error: ' . $e->getMessage();
$severity = E_RECOVERABLE_ERROR;
} else {
$message = 'Fatal error: ' . $e->getMessage();
$severity = E_ERROR;
}
parent::__construct(
$message,
$e->getCode(),
$severity,
$e->getFile(),
$e->getLine()
);
$this->setTrace($e->getTrace());
}
protected function setTrace($trace)
{
$traceReflector = new \ReflectionProperty('Exception', 'trace');
$traceReflector->setAccessible(true);
$traceReflector->setValue($this, $trace);
}
}

View File

@ -1,54 +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\facade;
use think\Facade;
/**
* @see \think\App
* @mixin \think\App
* @method \think\App bind(string $bind) static 绑定模块或者控制器
* @method void initialize() static 初始化应用
* @method void init(string $module='') static 初始化模块
* @method \think\Response run() static 执行应用
* @method \think\App dispatch(\think\route\Dispatch $dispatch) static 设置当前请求的调度信息
* @method void log(mixed $log, string $type = 'info') static 记录调试信息
* @method mixed config(string $name='') static 获取配置参数
* @method \think\route\Dispatch routeCheck() static URL路由检测根据PATH_INFO)
* @method \think\App routeMust(bool $must = false) static 设置应用的路由检测机制
* @method \think\Model model(string $name = '', string $layer = 'model', bool $appendSuffix = false, string $common = 'common') static 实例化模型
* @method object controller(string $name, string $layer = 'controller', bool $appendSuffix = false, string $empty = '') static 实例化控制器
* @method \think\Validate validate(string $name = '', string $layer = 'validate', bool $appendSuffix = false, string $common = 'common') static 实例化验证器类
* @method \think\db\Query db(mixed $config = [], mixed $name = false) static 数据库初始化
* @method mixed action(string $url, $vars = [], $layer = 'controller', $appendSuffix = false) static 调用模块的操作方法
* @method string parseClass(string $module, string $layer, string $name, bool $appendSuffix = false) static 解析应用类的类名
* @method string version() static 获取框架版本
* @method bool isDebug() static 是否为调试模式
* @method string getModulePath() static 获取当前模块路径
* @method void setModulePath(string $path) static 设置当前模块路径
* @method string getRootPath() static 获取应用根目录
* @method string getAppPath() static 获取应用类库目录
* @method string getRuntimePath() static 获取应用运行时目录
* @method string getThinkPath() static 获取核心框架目录
* @method string getRoutePath() static 获取路由目录
* @method string getConfigPath() static 获取应用配置目录
* @method string getConfigExt() static 获取配置后缀
* @method string setNamespace(string $namespace) static 设置应用类库命名空间
* @method string getNamespace() static 获取应用类库命名空间
* @method string getSuffix() static 是否启用类库后缀
* @method float getBeginTime() static 获取应用开启时间
* @method integer getBeginMem() static 获取应用初始内存占用
* @method \think\Container container() static 获取容器实例
*/
class App extends Facade
{
}

View File

@ -1,36 +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\facade;
use think\Facade;
/**
* @see \think\Cache
* @mixin \think\Cache
* @method \think\cache\Driver connect(array $options = [], mixed $name = false) static 连接缓存
* @method \think\cache\Driver init(array $options = []) static 初始化缓存
* @method \think\cache\Driver store(string $name = '') static 切换缓存类型
* @method bool has(string $name) static 判断缓存是否存在
* @method mixed get(string $name, mixed $default = false) static 读取缓存
* @method mixed pull(string $name) static 读取缓存并删除
* @method mixed set(string $name, mixed $value, int $expire = null) static 设置缓存
* @method mixed remember(string $name, mixed $value, int $expire = null) static 如果不存在则写入缓存
* @method mixed inc(string $name, int $step = 1) static 自增缓存(针对数值缓存)
* @method mixed dec(string $name, int $step = 1) static 自减缓存(针对数值缓存)
* @method bool rm(string $name) static 删除缓存
* @method bool clear(string $tag = null) static 清除缓存
* @method mixed tag(string $name, mixed $keys = null, bool $overlay = false) static 缓存标签
* @method object handler() static 返回句柄对象,可执行其它高级方法
*/
class Cache extends Facade
{
}

View File

@ -1,30 +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\facade;
use think\Facade;
/**
* @see \think\Cookie
* @mixin \think\Cookie
* @method void init(array $config = []) static 初始化
* @method bool has(string $name,string $prefix = null) static 判断Cookie数据
* @method mixed prefix(string $prefix = '') static 设置或者获取cookie作用域前缀
* @method mixed get(string $name,string $prefix = null) static Cookie获取
* @method mixed set(string $name, mixed $value = null, mixed $option = null) static 设置Cookie
* @method void forever(string $name, mixed $value = null, mixed $option = null) static 永久保存Cookie数据
* @method void delete(string $name, string $prefix = null) static Cookie删除
* @method void clear($prefix = null) static Cookie清空
*/
class Cookie extends Facade
{
}

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>
// +----------------------------------------------------------------------
namespace think\facade;
use think\Facade;
/**
* @see \think\Debug
* @mixin \think\Debug
* @method void remark(string $name, mixed $value = '') static 记录时间(微秒)和内存使用情况
* @method int getRangeTime(string $start, string $end, mixed $dec = 6) static 统计某个区间的时间(微秒)使用情况
* @method int getUseTime(int $dec = 6) static 统计从开始到统计时的时间(微秒)使用情况
* @method string getThroughputRate(string $start, string $end, mixed $dec = 6) static 获取当前访问的吞吐率情况
* @method string getRangeMem(string $start, string $end, mixed $dec = 2) static 记录区间的内存使用情况
* @method int getUseMem(int $dec = 2) static 统计从开始到统计时的内存使用情况
* @method string getMemPeak(string $start, string $end, mixed $dec = 2) static 统计区间的内存峰值情况
* @method mixed getFile(bool $detail = false) static 获取文件加载信息
* @method mixed dump(mixed $var, bool $echo = true, string $label = null, int $flags = ENT_SUBSTITUTE) static 浏览器友好的变量输出
*/
class Debug extends Facade
{
}

View File

@ -1,28 +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\facade;
use think\Facade;
/**
* @see \think\Hook
* @mixin \think\Hook
* @method \think\Hook alias(mixed $name, mixed $behavior = null) static 指定行为标识
* @method void add(string $tag, mixed $behavior, bool $first = false) static 动态添加行为扩展到某个标签
* @method void import(array $tags, bool $recursive = true) static 批量导入插件
* @method array get(string $tag = '') static 获取插件信息
* @method mixed listen(string $tag, mixed $params = null, bool $once = false) static 监听标签的行为
* @method mixed exec(mixed $class, mixed $params = null) static 执行行为
*/
class Hook extends Facade
{
}

View File

@ -1,32 +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\facade;
use think\Facade;
/**
* @see \think\Lang
* @mixin \think\Lang
* @method mixed range($range = '') static 设定当前的语言
* @method mixed set(mixed $name, string $value = null, string $range = '') static 设置语言定义
* @method array load(mixed $file, string $range = '') static 加载语言定义
* @method mixed get(string $name = null, array $vars = [], string $range = '') static 获取语言定义
* @method mixed has(string $name, string $range = '') static 获取语言定义
* @method string detect() static 自动侦测设置获取语言选择
* @method void saveToCookie(string $lang = null) static 设置当前语言到Cookie
* @method void setLangDetectVar(string $var) static 设置语言自动侦测的变量
* @method void setLangCookieVar(string $var) static 设置语言的cookie保存变量
* @method void setAllowLangList(array $list) static 设置允许的语言列表
*/
class Lang extends Facade
{
}

View File

@ -1,40 +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\facade;
use think\Facade;
/**
* @see \think\Log
* @mixin \think\Log
* @method \think\Log init(array $config = []) static 日志初始化
* @method mixed getLog(string $type = '') static 获取日志信息
* @method \think\Log record(mixed $msg, string $type = 'info', array $context = []) static 记录日志信息
* @method \think\Log clear() static 清空日志信息
* @method \think\Log key(string $key) static 当前日志记录的授权key
* @method bool check(array $config) static 检查日志写入权限
* @method bool save() static 保存调试信息
* @method void write(mixed $msg, string $type = 'info', bool $force = false) static 实时写入日志信息
* @method void log(string $level,mixed $message, array $context = []) static 记录日志信息
* @method void emergency(mixed $message, array $context = []) static 记录emergency信息
* @method void alert(mixed $message, array $context = []) static 记录alert信息
* @method void critical(mixed $message, array $context = []) static 记录critical信息
* @method void error(mixed $message, array $context = []) static 记录error信息
* @method void warning(mixed $message, array $context = []) static 记录warning信息
* @method void notice(mixed $message, array $context = []) static 记录notice信息
* @method void info(mixed $message, array $context = []) static 记录info信息
* @method void debug(mixed $message, array $context = []) static 记录debug信息
* @method void sql(mixed $message, array $context = []) static 记录sql信息
*/
class Log extends Facade
{
}

View File

@ -1,88 +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\facade;
use think\Facade;
/**
* @see \think\Request
* @mixin \think\Request
* @method void hook(mixed $method, mixed $callback = null) static Hook 方法注入
* @method \think\Request create(string $uri, string $method = 'GET', array $params = [], array $cookie = [], array $files = [], array $server = [], string $content = null) static 创建一个URL请求
* @method mixed domain(string $domain = null) static 设置或获取当前包含协议的域名
* @method mixed url(mixed $url = null) static 设置或获取当前完整URL
* @method mixed baseUrl(string $url = null) static 设置或获取当前URL
* @method mixed baseFile(string $file = null) static 设置或获取当前执行的文件
* @method mixed root(string $url = null) static 设置或获取URL访问根地址
* @method string rootUrl() static 获取URL访问根目录
* @method string pathinfo() static 获取当前请求URL的pathinfo信息含URL后缀
* @method string path() static 获取当前请求URL的pathinfo信息(不含URL后缀)
* @method string ext() static 当前URL的访问后缀
* @method float time(bool $float = false) static 获取当前请求的时间
* @method mixed type() static 当前请求的资源类型
* @method void mimeType(mixed $type, string $val = '') static 设置资源类型
* @method string method(bool $method = false) static 当前的请求类型
* @method bool isGet() static 是否为GET请求
* @method bool isPost() static 是否为POST请求
* @method bool isPut() static 是否为PUT请求
* @method bool isDelete() static 是否为DELTE请求
* @method bool isHead() static 是否为HEAD请求
* @method bool isPatch() static 是否为PATCH请求
* @method bool isOptions() static 是否为OPTIONS请求
* @method bool isCli() static 是否为cli
* @method bool isCgi() static 是否为cgi
* @method mixed param(mixed $name = '', mixed $default = null, mixed $filter = '') static 获取当前请求的参数
* @method mixed route(mixed $name = '', mixed $default = null, mixed $filter = '') static 设置获取路由参数
* @method mixed get(mixed $name = '', mixed $default = null, mixed $filter = '') static 设置获取GET参数
* @method mixed post(mixed $name = '', mixed $default = null, mixed $filter = '') static 设置获取POST参数
* @method mixed put(mixed $name = '', mixed $default = null, mixed $filter = '') static 设置获取PUT参数
* @method mixed delete(mixed $name = '', mixed $default = null, mixed $filter = '') static 设置获取DELETE参数
* @method mixed patch(mixed $name = '', mixed $default = null, mixed $filter = '') static 设置获取PATCH参数
* @method mixed request(mixed $name = '', mixed $default = null, mixed $filter = '') static 获取request变量
* @method mixed session(mixed $name = '', mixed $default = null, mixed $filter = '') static 获取session数据
* @method mixed cookie(mixed $name = '', mixed $default = null, mixed $filter = '') static 获取cookie参数
* @method mixed server(mixed $name = '', mixed $default = null, mixed $filter = '') static 获取server参数
* @method mixed env(mixed $name = '', mixed $default = null, mixed $filter = '') static 获取环境变量
* @method mixed file(mixed $name = '') static 获取上传的文件信息
* @method mixed header(mixed $name = '', mixed $default = null) static 设置或者获取当前的Header
* @method mixed input(array $data,mixed $name = '', mixed $default = null, mixed $filter = '') static 获取变量 支持过滤和默认值
* @method mixed filter(mixed $filter = null) static 设置或获取当前的过滤规则
* @method mixed has(string $name, string $type = 'param', bool $checkEmpty = false) static 是否存在某个请求参数
* @method mixed only(mixed $name, string $type = 'param') static 获取指定的参数
* @method mixed except(mixed $name, string $type = 'param') static 排除指定参数获取
* @method bool isSsl() static 当前是否ssl
* @method bool isAjax(bool $ajax = false) static 当前是否Ajax请求
* @method bool isPjax(bool $pjax = false) static 当前是否Pjax请求
* @method mixed ip(int $type = 0, bool $adv = true) static 获取客户端IP地址
* @method bool isMobile() static 检测是否使用手机访问
* @method string scheme() static 当前URL地址中的scheme参数
* @method string query() static 当前请求URL地址中的query参数
* @method string host() static 当前请求的host
* @method string port() static 当前请求URL地址中的port参数
* @method string protocol() static 当前请求 SERVER_PROTOCOL
* @method string remotePort() static 当前请求 REMOTE_PORT
* @method string contentType() static 当前请求 HTTP_CONTENT_TYPE
* @method array routeInfo(array $route = []) static 获取当前请求的路由信息
* @method array dispatch(array $dispatch = null) static 设置或者获取当前请求的调度信息
* @method mixed module(string $module = null) static 设置或者获取当前的模块名
* @method mixed controller(string $controller = null) static 设置或者获取当前的控制器名
* @method mixed action(string $action = null) static 设置或者获取当前的操作名
* @method mixed langset(string $lang = null) static 设置或者获取当前的语言
* @method string getContent() static 设置或者获取当前请求的content
* @method string getInput() static 获取当前请求的php://input
* @method string token(string $name = '__token__', mixed $type = 'md5') static 生成请求令牌
* @method string cache(string $key, mixed $expire = null, array $except = [], string $tag = null) static 设置当前地址的请求缓存
* @method string getCache() static 读取请求缓存设置
*/
class Request extends Facade
{
}

View File

@ -1,38 +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\facade;
use think\Facade;
/**
* @see \think\Response
* @mixin \think\Response
* @method \think\response create(mixed $data = '', string $type = '', int $code = 200, array $header = [], array $options = []) static 创建Response对象
* @method void send() static 发送数据到客户端
* @method \think\Response options(mixed $options = []) static 输出的参数
* @method \think\Response data(mixed $data) static 输出数据设置
* @method \think\Response header(mixed $name, string $value = null) static 设置响应头
* @method \think\Response content(mixed $content) static 设置页面输出内容
* @method \think\Response code(int $code) static 发送HTTP状态
* @method \think\Response lastModified(string $time) static LastModified
* @method \think\Response expires(string $time) static expires
* @method \think\Response eTag(string $eTag) static eTag
* @method \think\Response cacheControl(string $cache) static 页面缓存控制
* @method \think\Response contentType(string $contentType, string $charset = 'utf-8') static 页面输出类型
* @method mixed getHeader(string $name) static 获取头部信息
* @method mixed getData() static 获取原始数据
* @method mixed getContent() static 获取输出数据
* @method int getCode() static 获取状态码
*/
class Response extends Facade
{
}

View File

@ -1,48 +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\facade;
use think\Facade;
/**
* @see \think\Route
* @mixin \think\Route
* @method \think\route\Domain domain(mixed $name, mixed $rule = '', array $option = [], array $pattern = []) static 注册域名路由
* @method \think\Route pattern(mixed $name, string $rule = '') static 注册变量规则
* @method \think\Route option(mixed $name, mixed $value = '') static 注册路由参数
* @method \think\Route bind(string $bind) static 设置路由绑定
* @method mixed getBind(string $bind) static 读取路由绑定
* @method \think\Route name(string $name) static 设置当前路由标识
* @method mixed getName(string $name) static 读取路由标识
* @method void setName(string $name) static 批量导入路由标识
* @method void import(array $rules, string $type = '*') static 导入配置文件的路由规则
* @method \think\route\RuleItem rule(string $rule, mixed $route, string $method = '*', array $option = [], array $pattern = []) static 注册路由规则
* @method void rules(string $rules, string $method = '*', array $option = [], array $pattern = []) static 批量注册路由规则
* @method \think\route\RuleGroup group(string $name, mixed $route, string $method = '*', array $option = [], array $pattern = []) static 注册路由分组
* @method \think\route\RuleItem any(string $rule, mixed $route, array $option = [], array $pattern = []) static 注册路由
* @method \think\route\RuleItem get(string $rule, mixed $route, array $option = [], array $pattern = []) static 注册路由
* @method \think\route\RuleItem post(string $rule, mixed $route, array $option = [], array $pattern = []) static 注册路由
* @method \think\route\RuleItem put(string $rule, mixed $route, array $option = [], array $pattern = []) static 注册路由
* @method \think\route\RuleItem delete(string $rule, mixed $route, array $option = [], array $pattern = []) static 注册路由
* @method \think\route\RuleItem patch(string $rule, mixed $route, array $option = [], array $pattern = []) static 注册路由
* @method \think\route\Resource resource(string $rule, mixed $route, array $option = [], array $pattern = []) static 注册资源路由
* @method \think\Route controller(string $rule, mixed $route, array $option = [], array $pattern = []) static 注册控制器路由
* @method \think\Route alias(string $rule, mixed $route, array $option = [], array $pattern = []) static 注册别名路由
* @method \think\Route setMethodPrefix(mixed $method, string $prefix = '') static 设置不同请求类型下面的方法前缀
* @method \think\Route rest(string $name, array $resource = []) static rest方法定义和修改
* @method \think\RuleItem miss(string $route, string $method = '*', array $option = []) static 注册未匹配路由规则后的处理
* @method \think\RuleItem auto(string $route) static 注册一个自动解析的URL路由
* @method \think\Dispatch check(string $url, string $depr = '/', bool $must = false, bool $completeMatch = false) static 检测URL路由
*/
class Route extends Facade
{
}

View File

@ -1,37 +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\facade;
use think\Facade;
/**
* @see \think\Session
* @mixin \think\Session
* @method void init(array $config = []) static session初始化
* @method bool has(string $name,string $prefix = null) static 判断session数据
* @method mixed prefix(string $prefix = '') static 设置或者获取session作用域前缀
* @method mixed get(string $name,string $prefix = null) static session获取
* @method mixed pull(string $name,string $prefix = null) static session获取并删除
* @method void push(string $key, mixed $value) static 添加数据到一个session数组
* @method void set(string $name, mixed $value , string $prefix = null) static 设置session数据
* @method void flash(string $name, mixed $value = null) static session设置 下一次请求有效
* @method void flush() static 清空当前请求的session数据
* @method void delete(string $name, string $prefix = null) static 删除session数据
* @method void clear($prefix = null) static 清空session数据
* @method void start() static 启动session
* @method void destroy() static 销毁session
* @method void pause() static 暂停session
* @method void regenerate(bool $delete = false) static 重新生成session_id
*/
class Session extends Facade
{
}

View File

@ -1,65 +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\facade;
use think\Facade;
/**
* @see \think\Validate
* @mixin \think\Validate
* @method \think\Validate make(array $rules = [], array $message = [], array $field = []) static 创建一个验证器类
* @method \think\Validate rule(mixed $name, mixed $rule = '') static 添加字段验证规则
* @method void extend(string $type, mixed $callback = null) static 注册扩展验证(类型)规则
* @method void setTypeMsg(mixed $type, string $msg = null) static 设置验证规则的默认提示信息
* @method \think\Validate message(mixed $name, string $message = '') static 设置提示信息
* @method \think\Validate scene(string $name) static 设置验证场景
* @method bool hasScene(string $name) static 判断是否存在某个验证场景
* @method \think\Validate batch(bool $batch = true) static 设置批量验证
* @method \think\Validate only(array $fields) static 指定需要验证的字段列表
* @method \think\Validate remove(mixed $field, mixed $rule = true) static 移除某个字段的验证规则
* @method \think\Validate append(mixed $field, mixed $rule = null) static 追加某个字段的验证规则
* @method bool confirm(mixed $value, mixed $rule, array $data = [], string $field = '') static 验证是否和某个字段的值一致
* @method bool different(mixed $value, mixed $rule, array $data = []) static 验证是否和某个字段的值是否不同
* @method bool egt(mixed $value, mixed $rule, array $data = []) static 验证是否大于等于某个值
* @method bool gt(mixed $value, mixed $rule, array $data = []) static 验证是否大于某个值
* @method bool elt(mixed $value, mixed $rule, array $data = []) static 验证是否小于等于某个值
* @method bool lt(mixed $value, mixed $rule, array $data = []) static 验证是否小于某个值
* @method bool eq(mixed $value, mixed $rule) static 验证是否等于某个值
* @method bool must(mixed $value, mixed $rule) static 必须验证
* @method bool is(mixed $value, mixed $rule, array $data = []) static 验证字段值是否为有效格式
* @method bool ip(mixed $value, mixed $rule) static 验证是否有效IP
* @method bool requireIf(mixed $value, mixed $rule) static 验证某个字段等于某个值的时候必须
* @method bool requireCallback(mixed $value, mixed $rule,array $data) static 通过回调方法验证某个字段是否必须
* @method bool requireWith(mixed $value, mixed $rule, array $data) static 验证某个字段有值的情况下必须
* @method bool filter(mixed $value, mixed $rule) static 使用filter_var方式验证
* @method bool in(mixed $value, mixed $rule) static 验证是否在范围内
* @method bool notIn(mixed $value, mixed $rule) static 验证是否不在范围内
* @method bool between(mixed $value, mixed $rule) static between验证数据
* @method bool notBetween(mixed $value, mixed $rule) static 使用notbetween验证数据
* @method bool length(mixed $value, mixed $rule) static 验证数据长度
* @method bool max(mixed $value, mixed $rule) static 验证数据最大长度
* @method bool min(mixed $value, mixed $rule) static 验证数据最小长度
* @method bool after(mixed $value, mixed $rule) static 验证日期
* @method bool before(mixed $value, mixed $rule) static 验证日期
* @method bool expire(mixed $value, mixed $rule) static 验证有效期
* @method bool allowIp(mixed $value, mixed $rule) static 验证IP许可
* @method bool denyIp(mixed $value, mixed $rule) static 验证IP禁用
* @method bool regex(mixed $value, mixed $rule) static 使用正则验证数据
* @method bool token(mixed $value, mixed $rule) static 验证表单令牌
* @method bool dateFormat(mixed $value, mixed $rule) static 验证时间和日期是否符合指定格式
* @method bool unique(mixed $value, mixed $rule, array $data = [], string $field = '') static 验证是否唯一
* @method bool check(array $data, mixed $rules = [], string $scene = '') static 数据自动验证
* @method mixed getError(mixed $value, mixed $rule) static 获取错误信息
*/
class Validate extends Facade
{
}

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>
// +----------------------------------------------------------------------
namespace think\facade;
use think\Facade;
/**
* @see \think\View
* @mixin \think\View
* @method \think\View init(mixed $engine = [], array $replace = []) static 初始化
* @method \think\View share(mixed $name, mixed $value = '') static 模板变量静态赋值
* @method \think\View assign(mixed $name, mixed $value = '') static 模板变量赋值
* @method \think\View config(mixed $name, mixed $value = '') static 配置模板引擎
* @method \think\View exists(mixed $name) static 检查模板是否存在
* @method \think\View filter(Callable $filter) static 视图内容过滤
* @method \think\View engine(mixed $engine = []) static 设置当前模板解析的引擎
* @method string fetch(string $template = '', array $vars = [], array $replace = [], array $config = [], bool $renderContent = false) static 解析和获取模板内容
* @method string display(string $content = '', array $vars = [], array $replace = [], array $config = []) static 渲染内容输出
*/
class View extends Facade
{
}

View File

@ -1,86 +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: Slince <taosikai@yeah.net>
// +----------------------------------------------------------------------
namespace think\http\middleware;
use think\Request;
use think\Response;
class Dispatcher implements DispatcherInterface
{
protected $queue;
public function __construct($middlewares = [])
{
$this->queue = (array) $middlewares;
}
/**
* {@inheritdoc}
*/
public function add($middleware)
{
$this->assertValid($middleware);
$this->queue[] = $middleware;
}
/**
* {@inheritdoc}
*/
public function insert($middleware)
{
$this->assertValid($middleware);
array_unshift($this->queue, $middleware);
}
/**
* {@inheritdoc}
*/
public function all()
{
return $this->queue;
}
/**
* {@inheritdoc}
*/
public function dispatch(Request $request)
{
$requestHandler = $this->resolve();
return call_user_func($requestHandler, $request);
}
protected function resolve()
{
return function (Request $request) {
$middleware = array_shift($this->queue);
if (null !== $middleware) {
$response = call_user_func($middleware, $request, $this->resolve());
if (!$response instanceof Response) {
throw new \LogicException('The middleware must return Response instance');
}
return $response;
} else {
throw new MissingResponseException('The queue was exhausted, with no response returned');
}
};
}
protected function assertValid($middleware)
{
if (!is_callable($middleware)) {
throw new \InvalidArgumentException('The middleware is invalid');
}
}
}

View File

@ -1,45 +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: Slince <taosikai@yeah.net>
// +----------------------------------------------------------------------
namespace think\http\middleware;
use think\Request;
use think\Response;
interface DispatcherInterface
{
/**
* 在队尾添加 middleware
* @param callable $middleware
* @return DispatcherInterface
*/
public function add($middleware);
/**
* 在队前插入 middleware
* @param callable $middleware
* @return DispatcherInterface
*/
public function insert($middleware);
/**
* 获取所有的middleware
* @return array
*/
public function all();
/**
* 处理 request 并返回 response
* @param Request $request
* @return Response
*/
public function dispatch(Request $request);
}

View File

@ -1,69 +0,0 @@
<?php
namespace think\http\tests\middleware;
use PHPUnit\Framework\TestCase;
use think\http\middleware\Dispatcher;
use think\http\middleware\MissingResponseException;
use think\Request;
use think\Response;
class DispatcherTest extends TestCase
{
public function testValidMiddleware()
{
$dispatcher = new Dispatcher();
$dispatcher->add(function () {
});
$this->assertCount(1, $dispatcher->all());
$this->expectException(\InvalidArgumentException::class);
$dispatcher->add('foo middleware');
}
public function testAddAndInsert()
{
$middleware1 = function () {};
$middleware2 = function () {};
$dispatcher = new Dispatcher();
$dispatcher->add($middleware1);
$dispatcher->insert($middleware2);
$this->assertSame([$middleware2, $middleware1], $dispatcher->all());
}
public function testDispatch()
{
$middleware1 = function ($request, $next) {
return $next($request);
};
$middleware2 = function ($request) {
return Response::create('hello world');
};
$dispatcher = new Dispatcher([$middleware1, $middleware2]);
$response = $dispatcher->dispatch(new Request());
$this->assertInstanceOf(Response::class, $response);
$this->assertEquals('hello world', $response->getContent());
}
public function testDispatchWithoutResponse()
{
$middleware1 = function ($request, $next) {
return $next($request);
};
$middleware2 = function ($request, $next) {
return $next($request);
};
$dispatcher = new Dispatcher([$middleware1, $middleware2]);
$this->expectException(MissingResponseException::class);
$dispatcher->dispatch(new Request());
}
public function testDispatchWithBadResponse()
{
$middleware = function ($request, $next) {
return 'invalid response';
};
$dispatcher = new Dispatcher($middleware);
$this->expectException(\LogicException::class);
$dispatcher->dispatch(new Request());
}
}

View File

@ -1,143 +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\log\driver;
use think\Container;
/**
* 本地化调试输出到文件
*/
class File
{
protected $config = [
'time_format' => ' c ',
'single' => false,
'file_size' => 2097152,
'path' => '',
'apart_level' => [],
];
protected $writed = [];
// 实例化并传入参数
public function __construct($config = [])
{
if (is_array($config)) {
$this->config = array_merge($this->config, $config);
}
if (empty($this->config['path'])) {
$this->config['path'] = Container::get('app')->getRuntimePath() . 'log/';
}
}
/**
* 日志写入接口
* @access public
* @param array $log 日志信息
* @return bool
*/
public function save(array $log = [])
{
if ($this->config['single']) {
$name = is_string($single) ? $single : 'single';
$destination = $this->config['path'] . $name . '.log';
} else {
$cli = PHP_SAPI == 'cli' ? '_cli' : '';
$destination = $this->config['path'] . date('Ym') . '/' . date('d') . $cli . '.log';
}
$path = dirname($destination);
!is_dir($path) && mkdir($path, 0755, true);
$info = '';
foreach ($log as $type => $val) {
$level = '';
foreach ($val as $msg) {
if (!is_string($msg)) {
$msg = var_export($msg, true);
}
$level .= '[ ' . $type . ' ] ' . $msg . "\r\n";
}
if (in_array($type, $this->config['apart_level'])) {
// 独立记录的日志级别
if ($this->config['single']) {
$filename = $path . '/' . $name . '_' . $type . '.log';
} else {
$filename = $path . '/' . date('d') . '_' . $type . $cli . '.log';
}
$this->write($level, $filename, true);
} else {
$info .= $level;
}
}
if ($info) {
return $this->write($info, $destination);
}
return true;
}
/**
* 日志写入
* @access protected
* @param array $message 日志信息
* @param string $destination 日志文件
* @param bool $apart 是否独立文件写入
* @return bool
*/
protected function write($message, $destination, $apart = false)
{
// 检测日志文件大小,超过配置大小则备份日志文件重新生成
if (is_file($destination) && floor($this->config['file_size']) <= filesize($destination)) {
try {
rename($destination, dirname($destination) . '/' . time() . '-' . basename($destination));
} catch (\Exception $e) {
}
$this->writed[$destination] = false;
}
if (empty($this->writed[$destination]) && PHP_SAPI != 'cli') {
if (Container::get('app')->isDebug() && !$apart) {
// 获取基本信息
$current_uri = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$runtime = round(microtime(true) - Container::get('app')->getBeginTime(), 10);
$reqs = $runtime > 0 ? number_format(1 / $runtime, 2) : '∞';
$time_str = ' [运行时间:' . number_format($runtime, 6) . 's][吞吐率:' . $reqs . 'req/s]';
$memory_use = number_format((memory_get_usage() - Container::get('app')->getBeginMem()) / 1024, 2);
$memory_str = ' [内存消耗:' . $memory_use . 'kb]';
$file_load = ' [文件加载:' . count(get_included_files()) . ']';
$message = '[ info ] ' . $current_uri . $time_str . $memory_str . $file_load . "\r\n" . $message;
}
$now = date($this->config['time_format']);
$ip = Container::get('request')->ip();
$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'CLI';
$uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
$message = "---------------------------------------------------------------\r\n[{$now}] {$ip} {$method} {$uri}\r\n" . $message;
$this->writed[$destination] = true;
}
if (PHP_SAPI == 'cli') {
$now = date($this->config['time_format']);
$message = "[{$now}]" . $message;
}
return error_log($message, 3, $destination);
}
}

View File

@ -1,96 +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\model;
use think\Collection as BaseCollection;
use think\Model;
class Collection extends BaseCollection
{
/**
* 返回数组中指定的一列
* @access public
* @param string $column_key
* @param string|null $index_key
* @return array
*/
public function column($column_key, $index_key = null)
{
return array_column($this->toArray(), $column_key, $index_key);
}
/**
* 延迟预载入关联查询
* @access public
* @param mixed $relation 关联
* @return $this
*/
public function load($relation)
{
$item = current($this->items);
$item->eagerlyResultSet($this->items, $relation);
return $this;
}
/**
* 设置需要隐藏的输出属性
* @access public
* @param array $hidden 属性列表
* @param bool $override 是否覆盖
* @return $this
*/
public function hidden($hidden = [], $override = false)
{
$this->each(function ($model) use ($hidden, $override) {
/** @var Model $model */
$model->hidden($hidden, $override);
});
return $this;
}
/**
* 设置需要输出的属性
* @access public
* @param array $visible
* @param bool $override 是否覆盖
* @return $this
*/
public function visible($visible = [], $override = false)
{
$this->each(function ($model) use ($visible, $override) {
/** @var Model $model */
$model->visible($visible, $override);
});
return $this;
}
/**
* 设置需要追加的输出属性
* @access public
* @param array $append 属性列表
* @param bool $override 是否覆盖
* @return $this
*/
public function append($append = [], $override = false)
{
$this->each(function ($model) use ($append, $override) {
/** @var Model $model */
$model && $model->append($append, $override);
});
return $this;
}
}

View File

@ -1,151 +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\model;
use think\db\Query;
use think\Exception;
use think\Model;
/**
* Class Relation
* @package think\model
*
* @mixin Query
*/
abstract class Relation
{
// 父模型对象
protected $parent;
/** @var Model 当前关联的模型类 */
protected $model;
/** @var Query 关联模型查询对象 */
protected $query;
// 关联表外键
protected $foreignKey;
// 关联表主键
protected $localKey;
// 基础查询
protected $baseQuery;
// 是否为自关联
protected $selfRelation;
/**
* 获取关联的所属模型
* @access public
* @return Model
*/
public function getParent()
{
return $this->parent;
}
/**
* 获取当前的关联模型类的实例
* @access public
* @return Model
*/
public function getModel()
{
return $this->query->getModel();
}
/**
* 设置当前关联为自关联
* @access public
* @param bool $self 是否自关联
* @return $this
*/
public function selfRelation($self = true)
{
$this->selfRelation = $self;
return $this;
}
/**
* 当前关联是否为自关联
* @access public
* @return bool
*/
public function isSelfRelation()
{
return $this->selfRelation;
}
/**
* 封装关联数据集
* @access public
* @param array $resultSet 数据集
* @return mixed
*/
protected function resultSetBuild($resultSet)
{
return (new $this->model)->toCollection($resultSet);
}
protected function getQueryFields($model)
{
$fields = $this->query->getOptions('field');
return $this->getRelationQueryFields($fields, $model);
}
protected function getRelationQueryFields($fields, $model)
{
if ($fields) {
if (is_string($fields)) {
$fields = explode(',', $fields);
}
foreach ($fields as &$field) {
if (false === strpos($field, '.')) {
$field = $model . '.' . $field;
}
}
} else {
$fields = $model . '.*';
}
return $fields;
}
protected function getQueryWhere(&$where, $relation)
{
foreach ($where as $key => $val) {
if (is_string($key)) {
$where[] = [false === strpos($key, '.') ? $relation . '.' . $key : $key, '=', $val];
unset($where[$key]);
}
}
}
/**
* 执行基础查询(仅执行一次)
* @access protected
* @return void
*/
protected function baseQuery()
{}
public function __call($method, $args)
{
if ($this->query) {
// 执行基础查询
$this->baseQuery();
$result = call_user_func_array([$this->query->getModel(), $method], $args);
return $result === $this->query ? $this : $result;
} else {
throw new Exception('method not exists:' . __CLASS__ . '->' . $method);
}
}
}

View File

@ -1,157 +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\model\concern;
use think\Container;
/**
* 模型事件处理
*/
trait ModelEvent
{
/**
* 模型回调
* @var array
*/
private static $event = [];
/**
* 注册回调方法
* @access public
* @param string $event 事件名
* @param callable $callback 回调方法
* @param bool $override 是否覆盖
* @return void
*/
public static function event($event, $callback, $override = false)
{
$class = static::class;
if ($override) {
self::$event[$class][$event] = [];
}
self::$event[$class][$event][] = $callback;
}
/**
* 触发事件
* @access protected
* @param string $event 事件名
* @return bool
*/
protected function trigger($event)
{
$class = static::class;
if (isset(self::$event[$class][$event])) {
foreach (self::$event[$class][$event] as $callback) {
$result = Container::getInstance()->invoke($callback, [$this]);
if (false === $result) {
return false;
}
}
}
return true;
}
/**
* 模型before_insert事件快捷方法
* @access protected
* @param callable $callback
* @param bool $override
*/
protected static function beforeInsert($callback, $override = false)
{
self::event('before_insert', $callback, $override);
}
/**
* 模型after_insert事件快捷方法
* @access protected
* @param callable $callback
* @param bool $override
*/
protected static function afterInsert($callback, $override = false)
{
self::event('after_insert', $callback, $override);
}
/**
* 模型before_update事件快捷方法
* @access protected
* @param callable $callback
* @param bool $override
*/
protected static function beforeUpdate($callback, $override = false)
{
self::event('before_update', $callback, $override);
}
/**
* 模型after_update事件快捷方法
* @access protected
* @param callable $callback
* @param bool $override
*/
protected static function afterUpdate($callback, $override = false)
{
self::event('after_update', $callback, $override);
}
/**
* 模型before_write事件快捷方法
* @access protected
* @param callable $callback
* @param bool $override
*/
protected static function beforeWrite($callback, $override = false)
{
self::event('before_write', $callback, $override);
}
/**
* 模型after_write事件快捷方法
* @access protected
* @param callable $callback
* @param bool $override
*/
protected static function afterWrite($callback, $override = false)
{
self::event('after_write', $callback, $override);
}
/**
* 模型before_delete事件快捷方法
* @access protected
* @param callable $callback
* @param bool $override
*/
protected static function beforeDelete($callback, $override = false)
{
self::event('before_delete', $callback, $override);
}
/**
* 模型after_delete事件快捷方法
* @access protected
* @param callable $callback
* @param bool $override
*/
protected static function afterDelete($callback, $override = false)
{
self::event('after_delete', $callback, $override);
}
}

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