1
0
mirror of https://gitee.com/zoujingli/ThinkAdmin.git synced 2025-04-06 03:58:04 +08:00

[更新]ComposerUpdate

This commit is contained in:
Anyon 2018-06-04 14:44:37 +08:00
parent 12f99b7933
commit f2580af374
36 changed files with 670 additions and 394 deletions

@ -186,6 +186,8 @@ return [
'level' => [],
// 是否记录trace信息到日志
'record_trace' => false,
// 是否JSON格式记录
'json' => false,
],
// +----------------------------------------------------------------------

@ -20,7 +20,7 @@ use think\route\Dispatch;
*/
class App extends Container
{
const VERSION = '5.1.14';
const VERSION = '5.1.15';
/**
* 当前模块路径
@ -382,7 +382,7 @@ class App extends Container
$this->lang->load($this->appPath . $module . DIRECTORY_SEPARATOR . 'lang' . DIRECTORY_SEPARATOR . $this->request->langset() . '.php');
// 模块请求缓存检查
$this->request->cache(
$this->checkRequestCache(
$config['app']['request_cache'],
$config['app']['request_cache_expire'],
$config['app']['request_cache_except']
@ -419,7 +419,7 @@ class App extends Container
if (empty($dispatch)) {
// 路由检测
$dispatch = $this->routeCheck();
$dispatch = $this->routeCheck()->init();
}
// 记录当前调度信息
@ -436,7 +436,7 @@ class App extends Container
$this->hook->listen('app_begin');
// 请求缓存检查
$this->request->cache(
$this->checkRequestCache(
$this->config('request_cache'),
$this->config('request_cache_expire'),
$this->config('request_cache_except')
@ -468,7 +468,9 @@ class App extends Container
$response = Response::create($data, $type);
} else {
$response = Response::create();
$data = ob_get_clean();
$status = empty($data) ? 204 : 200;
$response = Response::create($data, '', $status);
}
return $response;
});
@ -512,6 +514,34 @@ class App extends Container
]);
}
/**
* 设置当前地址的请求缓存
* @access public
* @param string $key 缓存标识,支持变量规则 ,例如 item/:name/:id
* @param mixed $expire 缓存有效期
* @param array $except 缓存排除
* @param string $tag 缓存标签
* @return void
*/
public function checkRequestCache($key, $expire = null, $except = [], $tag = null)
{
$cache = $this->request->cache($key, $expire, $except, $tag);
if ($cache) {
list($key, $expire, $tag) = $cache;
if (strtotime($this->request->server('HTTP_IF_MODIFIED_SINCE')) + $expire > $this->request->server('REQUEST_TIME')) {
// 读取缓存
$response = Response::create()->code(304);
throw new HttpResponseException($response);
} elseif ($this->cache->has($key)) {
list($content, $header) = $this->cache->get($key);
$response = Response::create($content)->header($header);
throw new HttpResponseException($response);
}
}
}
/**
* 设置当前请求的调度信息
* @access public
@ -554,15 +584,17 @@ class App extends Container
*/
public function routeCheck()
{
// 获取应用调度信息
// 检测路由缓存
if (!$this->appDebug && $this->config->get('route_check_cache')) {
$routeKey = $this->getRouteCacheKey();
$option = $this->config->get('route_cache_option') ?: $this->cache->getConfig();
if ($this->cache->has($routeKey)) {
return $this->cache->get($routeKey);
if ($this->cache->connect($option)->has($routeKey)) {
return $this->cache->connect($option)->get($routeKey);
}
}
// 获取应用调度信息
$path = $this->request->path();
// 路由检测
@ -591,10 +623,6 @@ class App extends Container
}
}
if (is_file($this->runtimePath . 'rule_regex.php')) {
$this->route->setRuleRegexs(include $this->runtimePath . 'rule_regex.php');
}
// 是否强制路由模式
$must = !is_null($this->routeMust) ? $this->routeMust : $this->route->config('url_route_must');
@ -604,6 +632,7 @@ class App extends Container
if (!empty($routeKey)) {
try {
$this->cache
->connect($option)
->tag('route_cache')
->set($routeKey, $dispatch);
} catch (\Exception $e) {

@ -239,7 +239,7 @@ class Build
$class = new \ReflectionClass($namespace . '\\' . $module . '\\' . $layer . '\\' . $controller);
if (strpos($layer, DIRECTORY_SEPARATOR)) {
if (strpos($layer, '\\')) {
// 多级控制器
$level = str_replace(DIRECTORY_SEPARATOR, '.', substr($layer, 11));
$controller = $level . '.' . $controller;

@ -100,6 +100,11 @@ class Cache
return new static($config->pull('cache'));
}
public function getConfig()
{
return $this->config;
}
public function setConfig(array $config)
{
$this->config = array_merge($this->config, $config);

@ -25,17 +25,6 @@ class Config implements \ArrayAccess
*/
private $prefix = 'app';
/**
* 应用对象
* @var App
*/
protected $app;
public function __construct(App $app)
{
$this->app = $app;
}
/**
* 设置配置参数默认前缀
* @access public
@ -90,30 +79,6 @@ class Config implements \ArrayAccess
return $this->config;
}
/**
* 自动加载配置文件PHP格式
* @access public
* @param string $name 配置名
* @return void
*/
protected function autoLoad($name)
{
// 如果尚未载入 则动态加载配置文件
$module = $this->app->request->module();
$module = $module ? $module . DIRECTORY_SEPARATOR : '';
$path = $this->app->getAppPath() . $module;
if (is_dir($path . 'config')) {
$file = $path . 'config' . DIRECTORY_SEPARATOR . $name . $this->app->getConfigExt();
} elseif (is_dir($this->app->getConfigPath() . $module)) {
$file = $this->app->getConfigPath() . $module . $name . $this->app->getConfigExt();
}
if (isset($file) && is_file($file)) {
$this->load($file, $name);
}
}
/**
* 检测配置是否存在
* @access public
@ -139,21 +104,17 @@ class Config implements \ArrayAccess
{
$name = strtolower($name);
if (!isset($this->config[$name])) {
// 如果尚未载入 则动态加载配置文件
$this->autoLoad($name);
}
return isset($this->config[$name]) ? $this->config[$name] : [];
}
/**
* 获取配置参数 为空则获取所有配置
* @access public
* @param string $name 配置参数名(支持多级配置 .号分割)
* @param string $name 配置参数名(支持多级配置 .号分割)
* @param mixed $default 默认值
* @return mixed
*/
public function get($name = null)
public function get($name = null, $default = null)
{
// 无参数时获取所有
if (empty($name)) {
@ -170,17 +131,12 @@ class Config implements \ArrayAccess
$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 $default;
}
}

@ -42,6 +42,7 @@ class Console
"think\\console\\command\\make\\Controller",
"think\\console\\command\\make\\Model",
"think\\console\\command\\make\\Middleware",
"think\\console\\command\\make\\Validate",
"think\\console\\command\\optimize\\Autoload",
"think\\console\\command\\optimize\\Config",
"think\\console\\command\\optimize\\Schema",

@ -178,6 +178,21 @@ class Container implements \ArrayAccess
return isset($this->bind[$abstract]) || isset($this->instances[$abstract]);
}
/**
* 判断容器中是否存在对象实例
* @access public
* @param string $abstract 类名或者标识
* @return bool
*/
public function exists($abstract)
{
if (isset($this->bind[$abstract])) {
$abstract = $this->bind[$abstract];
}
return isset($this->instances[$abstract]);
}
/**
* 判断容器中是否存在类及标识
* @access public
@ -420,12 +435,13 @@ class Container implements \ArrayAccess
*/
protected function getObjectParam($className, &$vars)
{
$value = array_shift($vars);
$array = $vars;
$value = array_shift($array);
if ($value instanceof $className) {
$result = $value;
array_shift($vars);
} else {
array_unshift($vars, $value);
$result = $this->make($className);
}

@ -101,11 +101,16 @@ class Db
/**
* 获取数据库配置
* @access public
* @return array
* @param string $config 配置名称
* @return mixed
*/
public static function getConfig()
public static function getConfig($name = '')
{
return self::$config;
if ('' === $name) {
return self::$config;
}
return isset(self::$config[$name]) ? self::$config[$name] : null;
}
/**
@ -121,7 +126,8 @@ class Db
{
// 解析配置参数
$options = self::parseConfig($config ?: self::$config);
$query = $query ?: self::$config['query'];
$query = $query ?: $options['query'];
// 创建数据库连接对象实例
self::$connection = Connection::instance($options, $name);
@ -142,11 +148,13 @@ class Db
$config = isset(self::$config[$config]) ? self::$config[$config] : self::$config;
}
if (is_string($config)) {
return self::parseDsnConfig($config);
} else {
return $config;
$result = is_string($config) ? self::parseDsnConfig($config) : $config;
if (empty($result['query'])) {
$result['query'] = self::$config['query'];
}
return $result;
}
/**

@ -126,11 +126,11 @@ class Log implements LoggerInterface
$msg = strtr($msg, $replace);
}
$this->log[$type][] = $msg;
if (PHP_SAPI == 'cli') {
// 命令行日志实时写入
$this->save();
$this->write($msg, $type, true);
} else {
$this->log[$type][] = $msg;
}
return $this;
@ -196,7 +196,7 @@ class Log implements LoggerInterface
*/
public function save()
{
if (empty($this->log) || !$this->allowWrite || !$this->driver) {
if (empty($this->log) || !$this->allowWrite) {
return true;
}
@ -221,7 +221,8 @@ class Log implements LoggerInterface
}
}
$result = $this->driver->save($log);
$result = $this->driver->save($log, true);
if ($result) {
$this->log = [];
}
@ -240,11 +241,11 @@ class Log implements LoggerInterface
public function write($msg, $type = 'info', $force = false)
{
// 封装日志信息
$log = $this->log;
if (empty($this->config['level'])) {
$force = true;
}
if (true === $force || empty($this->config['level'])) {
$log[$type][] = $msg;
} elseif (in_array($type, $this->config['level'])) {
if (true === $force || in_array($type, $this->config['level'])) {
$log[$type][] = $msg;
} else {
return false;
@ -254,13 +255,7 @@ class Log implements LoggerInterface
$this->app['hook']->listen('log_write', $log);
// 写入日志
$result = $this->driver->save($log);
if ($result) {
$this->log = [];
}
return $result;
return $this->driver->save($log, false);
}
/**

@ -11,6 +11,7 @@
namespace think;
use InvalidArgumentException;
use think\db\Query;
/**
@ -173,11 +174,6 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
$this->resultSetType = $config['resultset_type'];
}
if (is_null($this->query)) {
// 设置查询对象
$this->query = $config['query'];
}
if (!empty($this->connection) && is_array($this->connection)) {
// 设置模型的数据库连接
$this->connection = array_merge($config, $this->connection);
@ -542,17 +538,30 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
}
// 模型更新
$result = $this->db(false)->where($where)->strict(false)->field($allowFields)->update($data);
$db = $this->db(false);
$db->startTrans();
// 关联更新
if (!empty($this->relationWrite)) {
$this->autoRelationUpdate();
try {
$result = $db->where($where)
->strict(false)
->field($allowFields)
->update($data);
// 关联更新
if (!empty($this->relationWrite)) {
$this->autoRelationUpdate();
}
$db->commit();
// 更新回调
$this->trigger('after_update');
return $result;
} catch (\Exception $e) {
$db->rollback();
throw $e;
}
// 更新回调
$this->trigger('after_update');
return $result;
}
/**
@ -576,31 +585,43 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
// 检查允许字段
$allowFields = $this->checkAllowFields(array_merge($this->auto, $this->insert));
$result = $this->db(false)->strict(false)->field($allowFields)->insert($this->data, $this->replace, false, $sequence);
$db = $this->db(false);
$db->startTrans();
// 获取自动增长主键
if ($result && $insertId = $this->db(false)->getLastInsID($sequence)) {
$pk = $this->getPk();
try {
$result = $db->strict(false)
->field($allowFields)
->insert($this->data, $this->replace, false, $sequence);
foreach ((array) $pk as $key) {
if (!isset($this->data[$key]) || '' == $this->data[$key]) {
$this->data[$key] = $insertId;
// 获取自动增长主键
if ($result && $insertId = $db->getLastInsID($sequence)) {
$pk = $this->getPk();
foreach ((array) $pk as $key) {
if (!isset($this->data[$key]) || '' == $this->data[$key]) {
$this->data[$key] = $insertId;
}
}
}
// 关联写入
if (!empty($this->relationWrite)) {
$this->autoRelationInsert();
}
$db->commit();
// 标记为更新
$this->isUpdate = true;
// 新增回调
$this->trigger('after_insert');
return $result;
} catch (\Exception $e) {
$db->rollback();
throw $e;
}
// 关联写入
if (!empty($this->relationWrite)) {
$this->autoRelationInsert();
}
// 标记为更新
$this->isUpdate = true;
// 新增回调
$this->trigger('after_insert');
return $result;
}
/**
@ -622,7 +643,9 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
return false;
}
$result = $this->db(false)->where($where)->setInc($field, $step, $lazyTime);
$result = $this->db(false)
->where($where)
->setInc($field, $step, $lazyTime);
if (true !== $result) {
$this->data[$field] += $step;
@ -653,7 +676,9 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
return false;
}
$result = $this->db(false)->where($where)->setDec($field, $step, $lazyTime);
$result = $this->db(false)
->where($where)
->setDec($field, $step, $lazyTime);
if (true !== $result) {
$this->data[$field] -= $step;
@ -762,21 +787,31 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
// 读取更新条件
$where = $this->getWhere();
// 删除当前模型数据
$result = $this->db(false)->where($where)->delete();
$db = $this->db(false);
$db->startTrans();
// 关联删除
if (!empty($this->relationWrite)) {
$this->autoRelationDelete();
try {
// 删除当前模型数据
$result = $db->where($where)->delete();
// 关联删除
if (!empty($this->relationWrite)) {
$this->autoRelationDelete();
}
$db->commit();
$this->trigger('after_delete');
// 清空数据
$this->data = [];
$this->origin = [];
return $result;
} catch (\Exception $e) {
$db->rollback();
throw $e;
}
$this->trigger('after_delete');
// 清空数据
$this->data = [];
$this->origin = [];
return $result;
}
/**
@ -1015,11 +1050,11 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
*/
public function __isset($name)
{
if (array_key_exists($name, $this->data) || array_key_exists($name, $this->relation)) {
return true;
try {
return !is_null($this->getAttr($name));
} catch (InvalidArgumentException $e) {
return false;
}
return false;
}
/**

@ -11,8 +11,6 @@
namespace think;
use think\exception\HttpResponseException;
class Request
{
/**
@ -21,17 +19,32 @@ class Request
*/
protected $instance;
/**
* 应用对象实例
* @var App
*/
protected $app;
/**
* 配置参数
* @var array
*/
protected $config = [];
protected $config = [
// 表单请求类型伪装变量
'var_method' => '_method',
// 表单ajax伪装变量
'var_ajax' => '_ajax',
// 表单pjax伪装变量
'var_pjax' => '_pjax',
// PATHINFO变量名 用于兼容模式
'var_pathinfo' => 's',
// 兼容PATH_INFO获取
'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
// 默认全局过滤方法 用逗号分隔多个
'default_filter' => '',
// 域名根如thinkphp.cn
'url_domain_root' => '',
// HTTPS代理标识
'https_agent_name' => '',
// IP代理获取标识
'http_agent_ip' => 'X-REAL-IP',
// URL伪静态后缀
'url_html_suffix' => 'html',
];
/**
* 请求类型
@ -268,9 +281,8 @@ class Request
* @access public
* @param array $options 参数
*/
public function __construct(App $app, array $options = [])
public function __construct(array $options = [])
{
$this->app = $app;
$this->init($options);
// 保存 php://input
@ -296,7 +308,13 @@ class Request
public static function __make(App $app, Config $config)
{
return new static($app, $config->pull('app'));
$request = new static($config->pull('app'));
$request->session($app['session']->get());
$request->cookie($app['cookie']->get());
$request->server($_SERVER);
$request->env($app['env']->get());
return $request;
}
public function __call($method, $args)
@ -411,13 +429,14 @@ class Request
$options['domain'] = isset($info['scheme']) ? $info['scheme'] . '://' . $server['HTTP_HOST'] : '';
$options['content'] = $content;
$request = new static();
foreach ($options as $name => $item) {
if (property_exists($this, $name)) {
$this->$name = $item;
if (property_exists($request, $name)) {
$request->$name = $item;
}
}
return $this;
return $request;
}
/**
@ -514,13 +533,13 @@ class Request
return $this;
} elseif (!$this->url) {
if ($this->isCli()) {
$this->url = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : '';
} elseif (isset($_SERVER['HTTP_X_REWRITE_URL'])) {
$this->url = $_SERVER['HTTP_X_REWRITE_URL'];
} elseif (isset($_SERVER['REQUEST_URI'])) {
$this->url = $_SERVER['REQUEST_URI'];
} elseif (isset($_SERVER['ORIG_PATH_INFO'])) {
$this->url = $_SERVER['ORIG_PATH_INFO'] . (!empty($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : '');
$this->url = $this->server('argv')[1] ?: '';
} elseif ($this->server('HTTP_X_REWRITE_URL')) {
$this->url = $this->server('HTTP_X_REWRITE_URL');
} elseif ($this->server('REQUEST_URI')) {
$this->url = $this->server('REQUEST_URI');
} elseif ($this->server('ORIG_PATH_INFO')) {
$this->url = $this->server('ORIG_PATH_INFO') . (!empty($this->server('QUERY_STRING')) ? '?' . $this->server('QUERY_STRING') : '');
} else {
$this->url = '';
}
@ -562,17 +581,17 @@ class Request
} elseif (!$this->baseFile) {
$url = '';
if (!$this->isCli()) {
$script_name = basename($_SERVER['SCRIPT_FILENAME']);
if (basename($_SERVER['SCRIPT_NAME']) === $script_name) {
$url = $_SERVER['SCRIPT_NAME'];
} elseif (basename($_SERVER['PHP_SELF']) === $script_name) {
$url = $_SERVER['PHP_SELF'];
} elseif (isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME']) === $script_name) {
$url = $_SERVER['ORIG_SCRIPT_NAME'];
} elseif (($pos = strpos($_SERVER['PHP_SELF'], '/' . $script_name)) !== false) {
$url = substr($_SERVER['SCRIPT_NAME'], 0, $pos) . '/' . $script_name;
} elseif (isset($_SERVER['DOCUMENT_ROOT']) && strpos($_SERVER['SCRIPT_FILENAME'], $_SERVER['DOCUMENT_ROOT']) === 0) {
$url = str_replace('\\', '/', str_replace($_SERVER['DOCUMENT_ROOT'], '', $_SERVER['SCRIPT_FILENAME']));
$script_name = basename($this->server('SCRIPT_FILENAME'));
if (basename($this->server('SCRIPT_NAME')) === $script_name) {
$url = $this->server('SCRIPT_NAME');
} elseif (basename($this->server('PHP_SELF')) === $script_name) {
$url = $this->server('PHP_SELF');
} elseif (basename($this->server('ORIG_SCRIPT_NAME')) === $script_name) {
$url = $this->server('ORIG_SCRIPT_NAME');
} elseif (($pos = strpos($this->server('PHP_SELF'), '/' . $script_name)) !== false) {
$url = substr($this->server('SCRIPT_NAME'), 0, $pos) . '/' . $script_name;
} elseif ($this->server('DOCUMENT_ROOT') && strpos($this->server('SCRIPT_FILENAME'), $this->server('DOCUMENT_ROOT')) === 0) {
$url = str_replace('\\', '/', str_replace($this->server('DOCUMENT_ROOT'), '', $this->server('SCRIPT_FILENAME')));
}
}
$this->baseFile = $url;
@ -630,27 +649,29 @@ class Request
if (is_null($this->pathinfo)) {
if (isset($_GET[$this->config['var_pathinfo']])) {
// 判断URL里面是否有兼容模式参数
$_SERVER['PATH_INFO'] = $_GET[$this->config['var_pathinfo']];
$pathinfo = $_GET[$this->config['var_pathinfo']];
unset($_GET[$this->config['var_pathinfo']]);
} elseif ($this->isCli()) {
// CLI模式下 index.php module/controller/action/params/...
$_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : '';
$pathinfo = isset($this->server('argv')[1]) ? $this->server('argv')[1] : '';
} elseif ('cli-server' == PHP_SAPI) {
$_SERVER['PATH_INFO'] = strpos($_SERVER['REQUEST_URI'], '?') ? strstr($_SERVER['REQUEST_URI'], '?', true) : $_SERVER['REQUEST_URI'];
$pathinfo = strpos($this->server('REQUEST_URI'), '?') ? strstr($this->server('REQUEST_URI'), '?', true) : $this->server('REQUEST_URI');
} elseif ($this->server('PATH_INFO')) {
$pathinfo = $this->server('PATH_INFO');
}
// 分析PATHINFO信息
if (!isset($_SERVER['PATH_INFO'])) {
if (!isset($pathinfo)) {
foreach ($this->config['pathinfo_fetch'] as $type) {
if (!empty($_SERVER[$type])) {
$_SERVER['PATH_INFO'] = (0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME'])) ?
substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type];
if ($this->server($type)) {
$pathinfo = (0 === strpos($this->server($type), $this->server('SCRIPT_NAME'))) ?
substr($this->server($type), strlen($this->server('SCRIPT_NAME'))) : $this->server($type);
break;
}
}
}
$this->pathinfo = empty($_SERVER['PATH_INFO']) || '/' == $_SERVER['PATH_INFO'] ? '' : ltrim($_SERVER['PATH_INFO'], '/');
$this->pathinfo = empty($pathinfo) || '/' == $pathinfo ? '' : ltrim($pathinfo, '/');
}
return $this->pathinfo;
@ -699,7 +720,7 @@ class Request
*/
public function time($float = false)
{
return $float ? $_SERVER['REQUEST_TIME_FLOAT'] : $_SERVER['REQUEST_TIME'];
return $float ? $this->server('REQUEST_TIME_FLOAT') : $this->server('REQUEST_TIME');
}
/**
@ -753,15 +774,15 @@ class Request
{
if (true === $method) {
// 获取原始请求类型
return $this->isCli() ? 'GET' : (isset($this->server['REQUEST_METHOD']) ? $this->server['REQUEST_METHOD'] : $_SERVER['REQUEST_METHOD']);
return $this->isCli() ? 'GET' : $this->server('REQUEST_METHOD');
} elseif (!$this->method) {
if (isset($_POST[$this->config['var_method']])) {
$this->method = strtoupper($_POST[$this->config['var_method']]);
$this->{$this->method}($_POST);
} elseif (isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) {
$this->method = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']);
} elseif ($this->server('HTTP_X_HTTP_METHOD_OVERRIDE')) {
$this->method = strtoupper($this->server('HTTP_X_HTTP_METHOD_OVERRIDE'));
} else {
$this->method = $this->isCli() ? 'GET' : (isset($this->server['REQUEST_METHOD']) ? $this->server['REQUEST_METHOD'] : $_SERVER['REQUEST_METHOD']);
$this->method = $this->isCli() ? 'GET' : $this->server('REQUEST_METHOD');
}
}
@ -1051,10 +1072,6 @@ class Request
*/
public function session($name = '', $default = null, $filter = '')
{
if (empty($this->session)) {
$this->session = $this->app['session']->get();
}
if (is_array($name)) {
return $this->session = array_merge($this->session, $name);
}
@ -1072,16 +1089,10 @@ class Request
*/
public function cookie($name = '', $default = null, $filter = '')
{
$cookie = $this->app['cookie'];
if (empty($this->cookie)) {
$this->cookie = $cookie->get();
}
if (is_array($name)) {
return $this->cookie = array_merge($this->cookie, $name);
} elseif (!empty($name)) {
$data = $cookie->has($name) ? $cookie->get($name) : $default;
$data = isset($this->cookie[$name]) ? $this->cookie[$name] : $default;
} else {
$data = $this->cookie;
}
@ -1109,10 +1120,6 @@ class Request
*/
public function server($name = '', $default = null, $filter = '')
{
if (empty($this->server)) {
$this->server = $_SERVER;
}
if (is_array($name)) {
return $this->server = array_merge($this->server, $name);
}
@ -1208,10 +1215,6 @@ class Request
*/
public function env($name = '', $default = null, $filter = '')
{
if (empty($this->env)) {
$this->env = $this->app['env']->get();
}
if (is_array($name)) {
return $this->env = array_merge($this->env, $name);
}
@ -1523,17 +1526,15 @@ class Request
*/
public function isSsl()
{
$server = array_merge($_SERVER, $this->server);
if (isset($server['HTTPS']) && ('1' == $server['HTTPS'] || 'on' == strtolower($server['HTTPS']))) {
if ($this->server('HTTPS') && ('1' == $this->server('HTTPS') || 'on' == strtolower($this->server('HTTPS')))) {
return true;
} elseif (isset($server['REQUEST_SCHEME']) && 'https' == $server['REQUEST_SCHEME']) {
} elseif ('https' == $this->server('REQUEST_SCHEME')) {
return true;
} elseif (isset($server['SERVER_PORT']) && ('443' == $server['SERVER_PORT'])) {
} elseif ('443' == $this->server('SERVER_PORT')) {
return true;
} elseif (isset($server['HTTP_X_FORWARDED_PROTO']) && 'https' == $server['HTTP_X_FORWARDED_PROTO']) {
} elseif ('https' == $this->server('HTTP_X_FORWARDED_PROTO')) {
return true;
} elseif ($this->config['https_agent_name'] && isset($server[$this->config['https_agent_name']])) {
} elseif ($this->config['https_agent_name'] && $this->server($this->config['https_agent_name'])) {
return true;
}
@ -1593,23 +1594,23 @@ class Request
$httpAgentIp = $this->config['http_agent_ip'];
if ($httpAgentIp && isset($_SERVER[$httpAgentIp])) {
$ip = $_SERVER[$httpAgentIp];
if ($httpAgentIp && $this->server($httpAgentIp)) {
$ip = $this->server($httpAgentIp);
} elseif ($adv) {
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
if ($this->server('HTTP_X_FORWARDED_FOR')) {
$arr = explode(',', $this->server('HTTP_X_FORWARDED_FOR'));
$pos = array_search('unknown', $arr);
if (false !== $pos) {
unset($arr[$pos]);
}
$ip = trim(current($arr));
} elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (isset($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
} elseif ($this->server('HTTP_CLIENT_IP')) {
$ip = $this->server('HTTP_CLIENT_IP');
} elseif ($this->server('REMOTE_ADDR')) {
$ip = $this->server('REMOTE_ADDR');
}
} elseif (isset($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
} elseif ($this->server('REMOTE_ADDR')) {
$ip = $this->server('REMOTE_ADDR');
}
// IP地址类型
@ -1635,13 +1636,13 @@ class Request
*/
public function isMobile()
{
if (isset($_SERVER['HTTP_VIA']) && stristr($_SERVER['HTTP_VIA'], "wap")) {
if ($this->server('HTTP_VIA') && stristr($this->server('HTTP_VIA'), "wap")) {
return true;
} elseif (isset($_SERVER['HTTP_ACCEPT']) && strpos(strtoupper($_SERVER['HTTP_ACCEPT']), "VND.WAP.WML")) {
} elseif ($this->server('HTTP_ACCEPT') && strpos(strtoupper($this->server('HTTP_ACCEPT')), "VND.WAP.WML")) {
return true;
} elseif (isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_PROFILE'])) {
} elseif ($this->server('HTTP_X_WAP_PROFILE') || $this->server('HTTP_PROFILE')) {
return true;
} elseif (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/(blackberry|configuration\/cldc|hp |hp-|htc |htc_|htc-|iemobile|kindle|midp|mmp|motorola|mobile|nokia|opera mini|opera |Googlebot-Mobile|YahooSeeker\/M1A1-R2D2|android|iphone|ipod|mobi|palm|palmos|pocket|portalmmm|ppc;|smartphone|sonyericsson|sqh|spv|symbian|treo|up.browser|up.link|vodafone|windows ce|xda |xda_)/i', $_SERVER['HTTP_USER_AGENT'])) {
} elseif ($this->server('HTTP_USER_AGENT') && preg_match('/(blackberry|configuration\/cldc|hp |hp-|htc |htc_|htc-|iemobile|kindle|midp|mmp|motorola|mobile|nokia|opera mini|opera |Googlebot-Mobile|YahooSeeker\/M1A1-R2D2|android|iphone|ipod|mobi|palm|palmos|pocket|portalmmm|ppc;|smartphone|sonyericsson|sqh|spv|symbian|treo|up.browser|up.link|vodafone|windows ce|xda |xda_)/i', $this->server('HTTP_USER_AGENT'))) {
return true;
}
@ -1676,11 +1677,7 @@ class Request
*/
public function host($strict = false)
{
if (isset($_SERVER['HTTP_X_REAL_HOST'])) {
$host = $_SERVER['HTTP_X_REAL_HOST'];
} else {
$host = $this->server('HTTP_HOST');
}
$host = $this->server('HTTP_X_REAL_HOST') ?: $this->server('HTTP_HOST');
return true === $strict && strpos($host, ':') ? strstr($host, ':', true) : $host;
}
@ -1879,13 +1876,13 @@ class Request
public function token($name = '__token__', $type = 'md5')
{
$type = is_callable($type) ? $type : 'md5';
$token = call_user_func($type, $_SERVER['REQUEST_TIME_FLOAT']);
$token = call_user_func($type, $this->server('REQUEST_TIME_FLOAT'));
if ($this->isAjax()) {
header($name . ': ' . $token);
}
$this->app['session']->set($name, $token);
facade\Session::set($name, $token);
return $token;
}
@ -1897,7 +1894,7 @@ class Request
* @param mixed $expire 缓存有效期
* @param array $except 缓存排除
* @param string $tag 缓存标签
* @return void
* @return mixed
*/
public function cache($key, $expire = null, $except = [], $tag = null)
{
@ -1953,20 +1950,9 @@ class Request
if (isset($fun)) {
$key = $fun($key);
}
$cache = $this->app['cache'];
if (strtotime($this->server('HTTP_IF_MODIFIED_SINCE')) + $expire > $_SERVER['REQUEST_TIME']) {
// 读取缓存
$response = Response::create()->code(304);
throw new HttpResponseException($response);
} elseif ($cache->has($key)) {
list($content, $header) = $cache->get($key);
$response = Response::create($content)->header($header);
throw new HttpResponseException($response);
}
$this->cache = [$key, $expire, $tag];
return $this->cache;
}
/**

@ -818,9 +818,9 @@ class Route
}
// 默认路由解析
$ruleItem = new RuleItem($this, $this->group, '', '', $url);
return new UrlDispatch($this->request, $ruleItem, $url, ['auto_search' => $this->autoSearchController]);
return new UrlDispatch($this->request, $this->group, $url, [
'auto_search' => $this->autoSearchController,
]);
}
/**

@ -110,7 +110,7 @@ class File extends Driver
*/
public function has($name)
{
return $this->get($name) ? true : false;
return false !== $this->get($name) ? true : false;
}
/**

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

@ -0,0 +1,24 @@
<?php
namespace {%namespace%};
use think\Validate;
class {%className%} extends Validate
{
/**
* 定义验证规则
* 格式:'字段名' => ['规则1','规则2'...]
*
* @var array
*/
protected $rule = [];
/**
* 定义错误信息
* 格式:'字段名.规则名' => '错误信息'
*
* @var array
*/
protected $message = [];
}

@ -99,7 +99,7 @@ class Config extends Command
if (is_file($path . 'provider.php')) {
$provider = include $path . 'provider.php';
if (is_array($provider)) {
$content .= PHP_EOL . '\think\Container::getInstance()->bind(' . var_export($provider, true) . ');' . PHP_EOL;
$content .= PHP_EOL . '\think\Container::getInstance()->bindTo(' . var_export($provider, true) . ');' . PHP_EOL;
}
}

@ -951,7 +951,7 @@ abstract class Builder
protected function parseComment(Query $query, $comment)
{
if (false !== strpos($comment, '*/')) {
$comment = strstr($coment, '*/', true);
$comment = strstr($comment, '*/', true);
}
return !empty($comment) ? ' /* ' . $comment . ' */' : '';

@ -2450,10 +2450,19 @@ class Query
if ($relation instanceof \Closure) {
$closure = $relation;
$relation = $key;
} elseif (!is_int($key)) {
$aggregateField = $relation;
$relation = $key;
}
if (!isset($aggregateField)) {
$aggregateField = Loader::parseName($relation) . '_' . $aggregate;
}
$relation = Loader::parseName($relation, 1, false);
$count = '(' . $this->model->$relation()->getRelationCountQuery($closure, $aggregate, $field) . ')';
$this->field([$count => Loader::parseName($relation) . '_' . $aggregate]);
$this->field([$count => $aggregateField]);
}
}

@ -27,7 +27,7 @@ use think\Facade;
* @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\RuleGroup group(string|array $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 注册路由

@ -11,7 +11,7 @@
namespace think\log\driver;
use think\Container;
use think\App;
/**
* 本地化调试输出到文件
@ -25,19 +25,22 @@ class File
'path' => '',
'apart_level' => [],
'max_files' => 0,
'json' => false,
];
protected $writed = [];
protected $app;
// 实例化并传入参数
public function __construct($config = [])
public function __construct(App $app, $config = [])
{
$this->app = $app;
if (is_array($config)) {
$this->config = array_merge($this->config, $config);
}
if (empty($this->config['path'])) {
$this->config['path'] = Container::get('app')->getRuntimePath() . 'log' . DIRECTORY_SEPARATOR;
$this->config['path'] = $this->app->getRuntimePath() . 'log' . DIRECTORY_SEPARATOR;
} elseif (substr($this->config['path'], -1) != DIRECTORY_SEPARATOR) {
$this->config['path'] .= DIRECTORY_SEPARATOR;
}
@ -46,13 +49,89 @@ class File
/**
* 日志写入接口
* @access public
* @param array $log 日志信息
* @param array $log 日志信息
* @param bool $append 是否追加请求信息
* @return bool
*/
public function save(array $log = [])
public function save(array $log = [], $append = false)
{
$destination = $this->getMasterLogFile();
$path = dirname($destination);
!is_dir($path) && mkdir($path, 0755, true);
$info = [];
foreach ($log as $type => $val) {
foreach ($val as $msg) {
if (!is_string($msg)) {
$msg = var_export($msg, true);
}
$info[$type][] = $this->config['json'] ? $msg : '[ ' . $type . ' ] ' . $msg;
}
if (!$this->config['json'] && in_array($type, $this->config['apart_level'])) {
// 独立记录的日志级别
$filename = $this->getApartLevelFile($path, $type);
$this->write($info[$type], $filename, true, $append);
unset($info[$type]);
}
}
if ($info) {
return $this->write($info, $destination, false, $append);
}
return true;
}
/**
* 日志写入
* @access protected
* @param array $message 日志信息
* @param string $destination 日志文件
* @param bool $apart 是否独立文件写入
* @param bool $append 是否追加请求信息
* @return bool
*/
protected function write($message, $destination, $apart = false, $append = false)
{
// 检测日志文件大小,超过配置大小则备份日志文件重新生成
$this->checkLogSize($destination);
// 日志信息封装
$info['timestamp'] = date($this->config['time_format']);
foreach ($message as $type => $msg) {
$info[$type] = is_array($msg) ? implode("\r\n", $msg) : $msg;
}
if (PHP_SAPI == 'cli') {
$message = $this->parseCliLog($info);
} else {
// 添加调试日志
$this->getDebugLog($info, $append, $apart);
$message = $this->parseLog($info);
}
return error_log($message, 3, $destination);
}
/**
* 获取主日志文件名
* @access public
* @return string
*/
protected function getMasterLogFile()
{
if ($this->config['single']) {
$name = is_string($this->config['single']) ? $this->config['single'] : 'single';
$name = is_string($this->config['single']) ? $this->config['single'] : 'single';
$destination = $this->config['path'] . $name . '.log';
} else {
$cli = PHP_SAPI == 'cli' ? '_cli' : '';
@ -74,90 +153,128 @@ class File
$destination = $this->config['path'] . $filename;
}
$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 . DIRECTORY_SEPARATOR . $name . '_' . $type . '.log';
} elseif ($this->config['max_files']) {
$filename = $path . DIRECTORY_SEPARATOR . date('Ymd') . '_' . $type . $cli . '.log';
} else {
$filename = $path . DIRECTORY_SEPARATOR . date('d') . '_' . $type . $cli . '.log';
}
$this->write($level, $filename, true);
} else {
$info .= $level;
}
}
if ($info) {
return $this->write($info, $destination);
}
return true;
return $destination;
}
/**
* 日志写入
* @access protected
* @param array $message 日志信息
* @param string $destination 日志文件
* @param bool $apart 是否独立文件写入
* @return bool
* 获取独立日志文件名
* @access public
* @param string $path 日志目录
* @param string $type 日志类型
* @return string
*/
protected function write($message, $destination, $apart = false)
protected function getApartLevelFile($path, $type)
{
$cli = PHP_SAPI == 'cli' ? '_cli' : '';
if ($this->config['single']) {
$name = is_string($this->config['single']) ? $this->config['single'] : 'single';
$name .= '_' . $type;
} elseif ($this->config['max_files']) {
$name = date('Ymd') . '_' . $type . $cli;
} else {
$name = date('d') . '_' . $type . $cli;
}
return $path . DIRECTORY_SEPARATOR . $name . '.log';
}
/**
* 检查日志文件大小并自动生成备份文件
* @access protected
* @param string $destination 日志文件
* @return void
*/
protected function checkLogSize($destination)
{
// 检测日志文件大小,超过配置大小则备份日志文件重新生成
if (is_file($destination) && floor($this->config['file_size']) <= filesize($destination)) {
try {
rename($destination, dirname($destination) . DIRECTORY_SEPARATOR . 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);
}
/**
* CLI日志解析
* @access protected
* @param array $info 日志信息
* @return string
*/
protected function parseCliLog($info)
{
if ($this->config['json']) {
$message = json_encode($info, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\r\n";
} else {
$now = $info['timestamp'];
unset($info['timestamp']);
$message = implode("\r\n", $info);
$message = "[{$now}]" . $message . "\r\n";
}
return $message;
}
/**
* 解析日志
* @access protected
* @param array $info 日志信息
* @return string
*/
protected function parseLog($info)
{
$requestInfo = [
'ip' => $this->app['request']->ip(),
'method' => $this->app['request']->method(),
'host' => $this->app['request']->host(),
'uri' => $this->app['request']->url(),
];
if ($this->config['json']) {
$info = $requestInfo + $info;
return json_encode($info, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\r\n";
}
array_unshift($info, "---------------------------------------------------------------\r\n[{$info['timestamp']}] {$requestInfo['ip']} {$requestInfo['method']} {$requestInfo['host']}{$requestInfo['uri']}");
unset($info['timestamp']);
return implode("\r\n", $info) . "\r\n";
}
protected function getDebugLog(&$info, $append, $apart)
{
if ($this->app->isDebug() && $append) {
if ($this->config['json']) {
// 获取基本信息
$runtime = round(microtime(true) - $this->app->getBeginTime(), 10);
$reqs = $runtime > 0 ? number_format(1 / $runtime, 2) : '∞';
$memory_use = number_format((memory_get_usage() - $this->app->getBeginMem()) / 1024, 2);
$info = [
'runtime' => number_format($runtime, 6) . 's',
'reqs' => $reqs . 'req/s',
'memory' => $memory_use . 'kb',
'file' => count(get_included_files()),
] + $info;
} elseif (!$apart) {
// 增加额外的调试信息
$runtime = round(microtime(true) - $this->app->getBeginTime(), 10);
$reqs = $runtime > 0 ? number_format(1 / $runtime, 2) : '∞';
$memory_use = number_format((memory_get_usage() - $this->app->getBeginMem()) / 1024, 2);
$time_str = '[运行时间:' . number_format($runtime, 6) . 's] [吞吐率:' . $reqs . 'req/s]';
$memory_str = ' [内存消耗:' . $memory_use . 'kb]';
$file_load = ' [文件加载:' . count(get_included_files()) . ']';
array_unshift($info, $time_str . $memory_str . $file_load);
}
}
}
}

@ -11,7 +11,7 @@
namespace think\log\driver;
use think\Container;
use think\App;
/**
* github: https://github.com/luofei614/SocketLog
@ -41,14 +41,17 @@ class Socket
];
protected $allowForceClientIds = []; //配置强制推送且被授权的client_id
protected $app;
/**
* 架构函数
* @access public
* @param array $config 缓存参数
*/
public function __construct(array $config = [])
public function __construct(App $app, array $config = [])
{
$this->app = $app;
if (!empty($config)) {
$this->config = array_merge($this->config, $config);
}
@ -60,7 +63,7 @@ class Socket
* @param array $log 日志信息
* @return bool
*/
public function save(array $log = [])
public function save(array $log = [], $append = false)
{
if (!$this->check()) {
return false;
@ -68,11 +71,11 @@ class Socket
$trace = [];
if (Container::get('app')->isDebug()) {
$runtime = round(microtime(true) - Container::get('app')->getBeginTime(), 10);
if ($this->app->isDebug()) {
$runtime = round(microtime(true) - $this->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_use = number_format((memory_get_usage() - $this->app->getBeginMem()) / 1024, 2);
$memory_str = ' [内存消耗:' . $memory_use . 'kb]';
$file_load = ' [文件加载:' . count(get_included_files()) . ']';

@ -86,7 +86,9 @@ trait SoftDelete
// 软删除
$this->data($name, $this->autoWriteTimestamp($name));
$result = $this->isUpdate()->save();
$result = $this->isUpdate()->withEvent(false)->save();
$this->withEvent = true;
} else {
// 读取更新条件
$where = $this->getWhere();

@ -72,10 +72,16 @@ abstract class Dispatch
if (isset($param['convert'])) {
$this->convert = $param['convert'];
}
}
public function init()
{
// 执行路由后置操作
if ($this->rule->doAfter()) {
// 设置请求的路由信息
// 设置当前请求的参数
$this->request->route($this->rule->getVars());
$this->request->routeInfo([
'rule' => $this->rule->getRule(),
'route' => $this->rule->getRoute(),
@ -86,13 +92,9 @@ abstract class Dispatch
$this->doRouteAfter();
}
// 初始化
$this->init();
return $this;
}
protected function init()
{}
/**
* 检查路由后置操作
* @access protected
@ -316,4 +318,14 @@ abstract class Dispatch
abstract public function exec();
public function __sleep()
{
return ['rule', 'dispatch', 'convert', 'param', 'code', 'controller', 'actionName'];
}
public function __wakeup()
{
$this->app = Container::get('app');
$this->request = $this->app['request'];
}
}

@ -80,6 +80,8 @@ class Resource extends RuleGroup
$rule = implode('/', $item) . '/' . $last;
}
$prefix = substr($rule, strlen($this->name) + 1);
// 注册资源路由
foreach ($this->rest as $key => $val) {
if ((isset($option['only']) && !in_array($key, $option['only']))
@ -93,9 +95,7 @@ class Resource extends RuleGroup
$val[1] = str_replace('<id>', '<' . $option['var'][$rule] . '>', $val[1]);
}
$option['rest'] = $key;
$this->addRule(trim($val[1], '/'), $this->route . '/' . $val[2], $val[0], $option);
$this->addRule(trim($prefix . $val[1], '/'), $this->route . '/' . $val[2], $val[0]);
}
$this->router->setGroup($origin);

@ -89,7 +89,7 @@ abstract class Rule
*/
protected $doAfter;
abstract public function check($request, $url, $depr = '/');
abstract public function check($request, $url, $completeMatch = false);
/**
* 获取Name
@ -261,6 +261,19 @@ abstract class Rule
return $this;
}
/**
* 设置变量
* @access public
* @param array $vars 变量
* @return $this
*/
public function vars($vars)
{
$this->vars = $vars;
return $this;
}
/**
* 设置路由请求类型
* @access public
@ -879,9 +892,6 @@ abstract class Rule
}, $url);
}
}
// 设置当前请求的参数
$request->route($var);
}
/**
@ -1041,4 +1051,14 @@ abstract class Rule
return call_user_func_array([$this, 'option'], $args);
}
public function __sleep()
{
return ['name', 'rule', 'route', 'method', 'vars', 'option', 'pattern', 'doAfter'];
}
public function __wakeup()
{
$this->router = Container::get('route');
}
}

@ -125,7 +125,7 @@ class RuleItem extends Rule
$suffix = null;
}
$value = [$this->rule, $vars, $this->parent->getDomain(), $suffix];
$value = [$this->rule, $vars, $this->parent->getDomain(), $suffix, $this->method];
Container::get('rule_name')->set($name, $value, $first);
}
@ -226,6 +226,7 @@ class RuleItem extends Rule
}
$pattern = array_merge($this->parent->getPattern(), $this->pattern);
$depr = $this->router->config('pathinfo_depr');
// 检查完整规则定义
if (isset($pattern['__url__']) && !preg_match(0 === strpos($pattern['__url__'], '/') ? $pattern['__url__'] : '/^' . $pattern['__url__'] . '/', str_replace('|', $depr, $url))) {
@ -233,7 +234,6 @@ class RuleItem extends Rule
}
$var = [];
$depr = $this->router->config('pathinfo_depr');
$url = $depr . str_replace('|', $depr, $url);
$rule = $depr . str_replace('/', $depr, $this->rule);

@ -22,8 +22,10 @@ class Module extends Dispatch
protected $controller;
protected $actionName;
protected function init()
public function init()
{
parent::init();
$result = $this->dispatch;
if (is_string($result)) {
@ -72,6 +74,7 @@ class Module extends Dispatch
// 设置当前请求的控制器、操作
$this->request->controller(Loader::parseName($this->controller, 1))->action($this->actionName);
return $this;
}
public function exec()

@ -17,29 +17,26 @@ use think\route\Dispatch;
class Url extends Dispatch
{
protected function init()
public function init()
{
// 解析默认的URL规则
$depr = $this->rule->getConfig('pathinfo_depr');
$result = $this->parseUrl($this->dispatch, $depr);
$result = $this->parseUrl($this->dispatch);
$this->dispatch = new Module($this->request, $this->rule, $result);
return (new Module($this->request, $this->rule, $result))->init();
}
public function exec()
{
return $this->dispatch->exec();
}
{}
/**
* 解析URL地址
* @access protected
* @param string $url URL
* @param string $depr 分隔符
* @return array
*/
protected function parseUrl($url, $depr)
protected function parseUrl($url)
{
$depr = $this->rule->getConfig('pathinfo_depr');
$bind = $this->rule->getRouter()->getBind();
if (!empty($bind) && preg_match('/^[a-z]/is', $bind)) {

2
vendor/autoload.php vendored

@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit4b011dbaeb8d413f22cc4a85f342d3db::getLoader();
return ComposerAutoloaderInit3b653bd8f42dcddd1a5ffaa4b92dcf0f::getLoader();

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit4b011dbaeb8d413f22cc4a85f342d3db
class ComposerAutoloaderInit3b653bd8f42dcddd1a5ffaa4b92dcf0f
{
private static $loader;
@ -19,15 +19,15 @@ class ComposerAutoloaderInit4b011dbaeb8d413f22cc4a85f342d3db
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit4b011dbaeb8d413f22cc4a85f342d3db', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit3b653bd8f42dcddd1a5ffaa4b92dcf0f', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit4b011dbaeb8d413f22cc4a85f342d3db', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit3b653bd8f42dcddd1a5ffaa4b92dcf0f', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit4b011dbaeb8d413f22cc4a85f342d3db::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit3b653bd8f42dcddd1a5ffaa4b92dcf0f::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
@ -48,19 +48,19 @@ class ComposerAutoloaderInit4b011dbaeb8d413f22cc4a85f342d3db
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit4b011dbaeb8d413f22cc4a85f342d3db::$files;
$includeFiles = Composer\Autoload\ComposerStaticInit3b653bd8f42dcddd1a5ffaa4b92dcf0f::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire4b011dbaeb8d413f22cc4a85f342d3db($fileIdentifier, $file);
composerRequire3b653bd8f42dcddd1a5ffaa4b92dcf0f($fileIdentifier, $file);
}
return $loader;
}
}
function composerRequire4b011dbaeb8d413f22cc4a85f342d3db($fileIdentifier, $file)
function composerRequire3b653bd8f42dcddd1a5ffaa4b92dcf0f($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;

@ -4,7 +4,7 @@
namespace Composer\Autoload;
class ComposerStaticInit4b011dbaeb8d413f22cc4a85f342d3db
class ComposerStaticInit3b653bd8f42dcddd1a5ffaa4b92dcf0f
{
public static $files = array (
'1cfd2761b63b0a29ed23657ea394cb2d' => __DIR__ . '/..' . '/topthink/think-captcha/src/helper.php',
@ -302,9 +302,9 @@ class ComposerStaticInit4b011dbaeb8d413f22cc4a85f342d3db
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit4b011dbaeb8d413f22cc4a85f342d3db::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit4b011dbaeb8d413f22cc4a85f342d3db::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit4b011dbaeb8d413f22cc4a85f342d3db::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInit3b653bd8f42dcddd1a5ffaa4b92dcf0f::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit3b653bd8f42dcddd1a5ffaa4b92dcf0f::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit3b653bd8f42dcddd1a5ffaa4b92dcf0f::$classMap;
}, null, ClassLoader::class);
}

@ -49,18 +49,18 @@
"source": {
"type": "git",
"url": "https://github.com/zoujingli/ip2region.git",
"reference": "5d981fbf3b574bad7fe9652e7aecba0920f54325"
"reference": "0a55d6c1ab6b4cbaa204824557aa950aaaefda0e"
},
"dist": {
"type": "zip",
"url": "https://files.phpcomposer.com/files/zoujingli/ip2region/5d981fbf3b574bad7fe9652e7aecba0920f54325.zip",
"reference": "5d981fbf3b574bad7fe9652e7aecba0920f54325",
"url": "https://files.phpcomposer.com/files/zoujingli/ip2region/0a55d6c1ab6b4cbaa204824557aa950aaaefda0e.zip",
"reference": "0a55d6c1ab6b4cbaa204824557aa950aaaefda0e",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
"php": ">=5.3"
},
"time": "2017-11-09T03:36:17+00:00",
"time": "2018-06-01T02:21:05+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -70,9 +70,16 @@
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache 2.0"
"Apache-2.0"
],
"description": "Ip2Region",
"authors": [
{
"name": "Anyon",
"email": "zoujingli@qq.com",
"homepage": "http://ctolog.com"
}
],
"description": "Ip2Region for PHP",
"homepage": "https://github.com/zoujingli/Ip2Region",
"keywords": [
"Ip2Region"
@ -184,17 +191,17 @@
},
{
"name": "topthink/framework",
"version": "v5.1.14",
"version_normalized": "5.1.14.0",
"version": "v5.1.15",
"version_normalized": "5.1.15.0",
"source": {
"type": "git",
"url": "https://github.com/top-think/framework.git",
"reference": "6448c4b42599d58125ba1307aa6d3defa044aeb9"
"reference": "04d8180148fe11610a9601ed6a7d7320998d21f1"
},
"dist": {
"type": "zip",
"url": "https://files.phpcomposer.com/files/top-think/framework/6448c4b42599d58125ba1307aa6d3defa044aeb9.zip",
"reference": "6448c4b42599d58125ba1307aa6d3defa044aeb9",
"url": "https://files.phpcomposer.com/files/top-think/framework/04d8180148fe11610a9601ed6a7d7320998d21f1.zip",
"reference": "04d8180148fe11610a9601ed6a7d7320998d21f1",
"shasum": ""
},
"require": {
@ -210,7 +217,7 @@
"sebastian/phpcpd": "2.*",
"squizlabs/php_codesniffer": "2.*"
},
"time": "2018-05-19T13:37:11+00:00",
"time": "2018-06-01T03:56:50+00:00",
"type": "think-framework",
"installation-source": "dist",
"notification-url": "https://packagist.org/downloads/",

2
vendor/zoujingli/ip2region/.gitignore vendored Normal file

@ -0,0 +1,2 @@
# Created by .ignore support plugin (hsz.mobi)
/.idea

@ -2,13 +2,20 @@
"type": "library",
"name": "zoujingli/ip2region",
"homepage": "https://github.com/zoujingli/Ip2Region",
"description": "Ip2Region",
"license": "Apache 2.0",
"description": "Ip2Region for PHP",
"license": "Apache-2.0",
"authors": [
{
"name": "Anyon",
"email": "zoujingli@qq.com",
"homepage": "http://ctolog.com"
}
],
"keywords": [
"Ip2Region"
],
"require": {
"php": ">=5.3.3"
"php": ">=5.3"
},
"autoload": {
"classmap": [

Binary file not shown.

@ -7,7 +7,7 @@ $ip = '101.105.35.57';
$info = $ip2region->btreeSearch($ip);
var_export($info, true);
var_export($info);
// array (
// 'city_id' => 2163,