内核更新

This commit is contained in:
2016-09-26 13:55:47 +08:00
parent 863f6a1cd0
commit 7608d4d0f7
17 changed files with 213 additions and 79 deletions

View File

@@ -19,8 +19,6 @@ return [
'auto_bind_module' => false,
// 注册的根命名空间
'root_namespace' => [],
// 扩展配置文件
'extra_config_list' => ['database', 'validate'],
// 扩展函数文件
'extra_file_list' => [THINK_PATH . 'helper' . EXT],
// 默认输出类型
@@ -97,6 +95,10 @@ return [
'url_controller_layer' => 'controller',
// 表单请求类型伪装变量
'var_method' => '_method',
// 表单ajax伪装变量
'var_ajax' => '_ajax',
// 表单pjax伪装变量
'var_pjax' => '_pjax',
// +----------------------------------------------------------------------
// | 模板设置

View File

@@ -214,18 +214,39 @@ class App
public static function invokeMethod($method, $vars = [])
{
if (is_array($method)) {
$class = is_object($method[0]) ? $method[0] : new $method[0];
$class = is_object($method[0]) ? $method[0] : new $method[0](Request::instance());
$reflect = new \ReflectionMethod($class, $method[1]);
} else {
// 静态方法
$reflect = new \ReflectionMethod($method);
}
$args = self::bindParams($reflect, $vars);
// 记录执行信息
self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info');
return $reflect->invokeArgs(isset($class) ? $class : null, $args);
}
/**
* 调用反射执行类的实例化 支持依赖注入
* @access public
* @param string $class 类名
* @param array $vars 变量
* @return mixed
*/
public static function invokeClass($class, $vars = [])
{
$reflect = new \ReflectionClass($class);
$constructor = $reflect->getConstructor();
if ($constructor) {
$args = self::bindParams($constructor, $vars);
} else {
$args = [];
}
self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info');
return $reflect->newInstanceArgs($args);
}
/**
* 绑定参数
* @access public
@@ -254,9 +275,9 @@ class App
$class = $param->getClass();
if ($class) {
$className = $class->getName();
if (isset($vars[$name]) && $vars[$name] instanceof $className) {
$args[] = $vars[$name];
unset($vars[$name]);
$bind = Request::instance()->$name;
if ($bind instanceof $className) {
$args[] = $bind;
} else {
$args[] = method_exists($className, 'instance') ? $className::instance() : new $className();
}
@@ -444,12 +465,18 @@ class App
$path = APP_PATH . $module;
// 加载模块配置
$config = Config::load(CONF_PATH . $module . 'config' . CONF_EXT);
// 读取数据库配置文件
$filename = CONF_PATH . $module . 'database' . CONF_EXT;
Config::load($filename, 'database');
// 读取扩展配置文件
if ($config['extra_config_list']) {
foreach ($config['extra_config_list'] as $name => $file) {
$filename = CONF_PATH . $module . $file . CONF_EXT;
Config::load($filename, is_string($name) ? $name : pathinfo($filename, PATHINFO_FILENAME));
if (is_dir(CONF_PATH . $module . 'extra')) {
$dir = CONF_PATH . $module . 'extra';
$files = scandir($dir);
foreach ($files as $file) {
if (strpos($file, CONF_EXT)) {
$filename = $dir . DS . $file;
Config::load($filename, pathinfo($file, PATHINFO_FILENAME));
}
}
}

View File

@@ -95,27 +95,15 @@ class File extends SplFileObject
}
/**
* 获取文件的md5散列值
* @return $this
* 获取文件的哈希散列值
* @return $string
*/
public function md5()
public function hash($type = 'sha1')
{
if (!isset($this->hash['md5'])) {
$this->hash['md5'] = md5_file($this->filename);
if (!isset($this->hash[$type])) {
$this->hash[$type] = hash_file($type, $this->filename);
}
return $this->hash['md5'];
}
/**
* 获取文件的sha1散列值
* @return $this
*/
public function sha1()
{
if (!isset($this->hash['sha1'])) {
$this->hash['sha1'] = sha1_file($this->filename);
}
return $this->hash['sha1'];
return $this->hash[$type];
}
/**
@@ -356,19 +344,18 @@ class File extends SplFileObject
$savename = call_user_func_array($this->rule, [$this]);
} else {
switch ($this->rule) {
case 'md5':
$md5 = md5_file($this->filename);
$savename = substr($md5, 0, 2) . DS . substr($md5, 2);
break;
case 'sha1':
$sha1 = sha1_file($this->filename);
$savename = substr($sha1, 0, 2) . DS . substr($sha1, 2);
break;
case 'date':
$savename = date('Ymd') . DS . md5(microtime(true));
break;
default:
$savename = call_user_func($this->rule);
if (in_array($this->rule, hash_algos())) {
$hash = $this->hash($this->rule);
$savename = substr($hash, 0, 2) . DS . substr($hash, 2);
} elseif (is_callable($this->rule)) {
$savename = call_user_func($this->rule);
} else {
$savename = date('Ymd') . DS . md5(microtime(true));
}
}
}
} elseif ('' === $savename) {

View File

@@ -406,7 +406,7 @@ class Loader
}
$class = self::parseClass($module, $layer, $name, $appendSuffix);
if (class_exists($class)) {
return new $class(Request::instance());
return App::invokeClass($class);
} elseif ($empty && class_exists($emptyClass = self::parseClass($module, $layer, $empty, $appendSuffix))) {
return new $emptyClass(Request::instance());
}

View File

@@ -442,12 +442,16 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
$value = (bool) $value;
break;
case 'timestamp':
$format = !empty($param) ? $param : $this->dateFormat;
$value = date($format, $value);
if (!is_null($value)) {
$format = !empty($param) ? $param : $this->dateFormat;
$value = date($format, $value);
}
break;
case 'datetime':
$format = !empty($param) ? $param : $this->dateFormat;
$value = date($format, strtotime($value));
if (!is_null($value)) {
$format = !empty($param) ? $param : $this->dateFormat;
$value = date($format, strtotime($value));
}
break;
case 'json':
$value = json_decode($value, true);
@@ -1346,11 +1350,8 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
public static function __callStatic($method, $params)
{
$query = self::getDb();
$model = get_called_class();
if (!isset(self::$links[$model])) {
self::$links[$model] = (new static())->db();
}
$query = self::$links[$model];
// 全局作用域
if (static::$useGlobalScope && method_exists($model, 'base')) {
call_user_func_array('static::base', [ & $query]);
@@ -1358,6 +1359,15 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
return call_user_func_array([$query, $method], $params);
}
protected static function getDb()
{
$model = get_called_class();
if (!isset(self::$links[$model])) {
self::$links[$model] = (new static())->db();
}
return self::$links[$model];
}
/**
* 修改器 设置数据对象的值
* @access public

View File

@@ -117,6 +117,10 @@ class Request
protected static $hook = [];
// 绑定的属性
protected $bind = [];
// php://input
protected $input;
// 请求缓存
protected $cache;
/**
* 架构函数
@@ -133,6 +137,8 @@ class Request
if (is_null($this->filter)) {
$this->filter = Config::get('default_filter');
}
// 保存 php://input
$this->input = file_get_contents('php://input');
}
public function __call($method, $args)
@@ -698,7 +704,7 @@ class Request
public function put($name = '', $default = null, $filter = null)
{
if (is_null($this->put)) {
$content = file_get_contents('php://input');
$content = $this->input;
if (strpos($content, '":')) {
$this->put = json_decode($content, true);
} else {
@@ -1180,22 +1186,34 @@ class Request
/**
* 当前是否Ajax请求
* @access public
* @param bool $ajax true 获取原始ajax请求
* @return bool
*/
public function isAjax()
public function isAjax($ajax = false)
{
$value = $this->server('HTTP_X_REQUESTED_WITH');
return (!is_null($value) && strtolower($value) == 'xmlhttprequest') ? true : false;
$value = $this->server('HTTP_X_REQUESTED_WITH', '', 'strtolower');
$result = ('xmlhttprequest' == $value) ? true : false;
if (true === $ajax) {
return $result;
} else {
return $this->param(Config::get('var_ajax')) ? true : $result;
}
}
/**
* 当前是否Pjax请求
* @access public
* @param bool $pjax true 获取原始pjax请求
* @return bool
*/
public function isPjax()
public function isPjax($pjax = false)
{
return !is_null($this->server('HTTP_X_PJAX')) ? true : false;
$result = !is_null($this->server('HTTP_X_PJAX')) ? true : false;
if (true === $pjax) {
return $result;
} else {
return $this->param(Config::get('var_pjax')) ? true : $result;
}
}
/**
@@ -1416,11 +1434,21 @@ class Request
public function getContent()
{
if (is_null($this->content)) {
$this->content = file_get_contents('php://input');
$this->content = $this->input;
}
return $this->content;
}
/**
* 获取当前请求的php://input
* @access public
* @return string
*/
public function getInput()
{
return $this->input;
}
/**
* 生成请求令牌
* @access public
@@ -1439,6 +1467,45 @@ class Request
return $token;
}
/**
* 读取或者设置缓存
* @access public
* @param string $key 缓存标识,支持变量规则 ,例如 item/:name/:id
* @param mixed $expire 缓存有效期
* @return mixed
*/
public function cache($key, $expire = null)
{
if (false !== strpos($key, ':')) {
$param = $this->param();
foreach ($param as $item => $val) {
if (is_string($val) && false !== strpos($key, ':' . $item)) {
$key = str_replace(':' . $item, $val, $key);
}
}
}
if (Cache::has($key)) {
// 读取缓存
$content = Cache::get($key);
$response = Response::create($content)
->code(304)
->header('Content-Type', Cache::get($key . '_header'));
throw new \think\exception\HttpResponseException($response);
} else {
$this->cache = [$key, $expire];
}
}
/**
* 读取缓存设置
* @access public
* @return array
*/
public function getCache()
{
return $this->cache;
}
/**
* 设置当前请求绑定的对象实例
* @access public
@@ -1464,4 +1531,9 @@ class Request
{
return isset($this->bind[$name]) ? $this->bind[$name] : null;
}
public function __isset($name)
{
return isset($this->bind[$name]);
}
}

View File

@@ -11,9 +11,11 @@
namespace think;
use think\Cache;
use think\Config;
use think\Debug;
use think\Env;
use think\Request;
use think\response\Json as JsonResponse;
use think\response\Jsonp as JsonpResponse;
use think\response\Redirect as RedirectResponse;
@@ -111,11 +113,21 @@ class Response
}
echo $data;
if (200 == $this->code) {
$cache = Request::instance()->getCache();
if ($cache) {
Cache::set($cache[0], $data, $cache[1]);
Cache::set($cache[0] . '_header', $this->header['Content-Type']);
}
}
if (function_exists('fastcgi_finish_request')) {
// 提高页面响应
fastcgi_finish_request();
}
// 监听response_end
Hook::listen('response_end', $this);
}
/**

View File

@@ -985,10 +985,6 @@ class Route
case 'namespace':
// 绑定到命名空间
return self::bindToNamespace($url, $bind, $depr);
case 'module':
// 如果有模块/控制器绑定 针对路由到 模块/控制器 有效
$url = (empty(self::$domainBind) ? $bind . '/' : '') . ltrim($url, '/');
break;
}
}
return false;
@@ -1240,17 +1236,20 @@ class Route
foreach ($matches[1] as $name) {
if (strpos($name, '?')) {
$name = substr($name, 0, -1);
$replace[] = '(' . (isset($pattern[$name]) ? $pattern[$name] : '\w+') . '?)';
$replace[] = '(' . (isset($pattern[$name]) ? $pattern[$name] : '\w+') . ')?';
} else {
$replace[] = '(' . (isset($pattern[$name]) ? $pattern[$name] : '\w+') . ')';
}
$value[] = $name;
}
$val = str_replace($matches[0], $replace, $val);
if (preg_match('/^' . $val . '$/', $m1[$key], $match)) {
if (preg_match('/^' . $val . '$/', isset($m1[$key]) ? $m1[$key] : '', $match)) {
array_shift($match);
$match = array_slice($match, 0, count($value));
$var = array_merge($var, array_combine($value, $match));
foreach ($value as $k => $name) {
if (isset($match[$k])) {
$var[$name] = $match[$k];
}
}
continue;
} else {
return false;
@@ -1296,6 +1295,7 @@ class Route
*/
private static function parseRule($rule, $route, $pathinfo, $option = [], $matches = [], $merge = false)
{
$request = Request::instance();
// 解析路由规则
if ($rule) {
$rule = explode('/', $rule);
@@ -1368,13 +1368,13 @@ class Route
$bind[$key] = $result;
}
}
Request::instance()->bind($bind);
$request->bind($bind);
}
// 解析额外参数
self::parseUrlParams(empty($paths) ? '' : implode('/', $paths), $matches);
// 记录匹配的路由信息
Request::instance()->routeInfo(['rule' => $rule, 'route' => $route, 'option' => $option, 'var' => $matches]);
$request->routeInfo(['rule' => $rule, 'route' => $route, 'option' => $option, 'var' => $matches]);
// 检测路由after行为
if (!empty($option['after_behavior'])) {
@@ -1402,8 +1402,9 @@ class Route
} elseif (0 === strpos($route, '/') || 0 === strpos($route, 'http')) {
// 路由到重定向地址
$result = ['type' => 'redirect', 'url' => $route, 'status' => isset($option['status']) ? $option['status'] : 301];
} elseif (0 === strpos($route, '\\')) {
} elseif (false !== strpos($route, '\\')) {
// 路由到方法
$route = str_replace('/', '@', $route);
$method = strpos($route, '@') ? explode('@', $route) : $route;
$result = ['type' => 'method', 'method' => $method];
} elseif (0 === strpos($route, '@')) {
@@ -1413,6 +1414,17 @@ class Route
// 路由到模块/控制器/操作
$result = self::parseModule($route);
}
// 开启请求缓存
if ($request->isGet() && !empty($option['cache'])) {
$cache = $option['cache'];
if (is_array($cache)) {
list($key, $expire) = $cache;
} else {
$key = $pathinfo;
$expire = $cache;
}
$request->cache($key, $expire);
}
return $result;
}

View File

@@ -127,6 +127,8 @@ class Template
$this->config = array_merge($this->config, $config);
} elseif (isset($this->config[$config])) {
return $this->config[$config];
} else {
return null;
}
}

View File

@@ -771,7 +771,7 @@ class Query
* @param string $type JOIN类型
* @return $this
*/
public function view($join, $field = null, $on = null, $type = 'INNER')
public function view($join, $field = true, $on = null, $type = 'INNER')
{
$this->options['view'] = true;
if (is_array($join) && is_null($field)) {

View File

@@ -59,10 +59,10 @@ class Pgsql extends Connection
$info[$val['field']] = [
'name' => $val['field'],
'type' => $val['type'],
'notnull' => (bool) ('' === $val['null']), // not null is empty, null is yes
'notnull' => (bool) ('' !== $val['null']),
'default' => $val['default'],
'primary' => (strtolower($val['key']) == 'pri'),
'autoinc' => (strtolower($val['extra']) == 'auto_increment'),
'primary' => !empty($val['key']),
'autoinc' => (0 === strpos($val['extra'], 'nextval(')),
];
}
}

View File

@@ -209,7 +209,9 @@ class Merge extends Model
// 处理关联模型数据
$data = $this->parseData($name, $this->data);
$query = clone $db;
$query->table($table)->strict(false)->where($this->fk, $this->data[$this->getPk()])->update($data);
if ($query->table($table)->strict(false)->where($this->fk, $this->data[$this->getPk()])->update($data)) {
$result = 1;
}
}
// 新增回调
$this->trigger('after_update', $this);

View File

@@ -554,7 +554,7 @@ class Relation
case self::BELONGS_TO:
case self::HAS_MANY:
if ($data instanceof Model) {
$data = $data->toArray();
$data = $data->getData();
}
// 保存关联表数据
$data[$this->foreignKey] = $this->parent->{$this->localKey};
@@ -604,7 +604,8 @@ class Relation
if (is_array($data)) {
// 保存关联表数据
$model = new $this->model;
$id = $model->save($data);
$model->save($data);
$id = $model->getLastInsID();
} elseif (is_numeric($data) || is_string($data)) {
// 根据关联表主键直接写入中间表
$id = $data;
@@ -681,11 +682,14 @@ class Relation
$pk = (new $this->model)->getPk();
$throughKey = $this->throughKey;
$modelTable = $this->parent->getTable();
$result = $this->query->field($alias . '.*')->alias($alias)
$this->query->field($alias . '.*')->alias($alias)
->join($throughTable, $throughTable . '.' . $pk . '=' . $alias . '.' . $throughKey)
->join($modelTable, $modelTable . '.' . $this->localKey . '=' . $throughTable . '.' . $this->foreignKey)
->where($throughTable . '.' . $this->foreignKey, $this->parent->{$this->localKey});
break;
case self::BELONGS_TO_MANY:
// TODO
}
$result = call_user_func_array([$this->query, $method], $args);
if ($result instanceof \think\db\Query) {

View File

@@ -67,7 +67,7 @@ class Redirect extends Response
*/
public function getTargetUrl()
{
return preg_match('/^(https?:|\/)/', $this->data) ? $this->data : Url::build($this->data, $this->params);
return (strpos($this->data, '://') || 0 === strpos($this->data, '/')) ? $this->data : Url::build($this->data, $this->params);
}
public function params($params = [])

View File

@@ -143,6 +143,8 @@ class Php
{
if (is_array($name)) {
$this->config = array_merge($this->config, $name);
} elseif (is_null($value)) {
return isset($this->config[$name]) ? $this->config[$name] : null;
} else {
$this->config[$name] = $value;
}

View File

@@ -130,17 +130,19 @@ class Think
}
/**
* 配置模板引擎
* 配置或者获取模板引擎参数
* @access private
* @param string|array $name 参数名
* @param mixed $value 参数值
* @return void
* @return mixed
*/
public function config($name, $value = null)
{
if (is_array($name)) {
$this->template->config($name);
$this->config = array_merge($this->config, $name);
} elseif (is_null($value)) {
return $this->template->config($name);
} else {
$this->template->$name = $value;
$this->config[$name] = $value;

View File

@@ -44,7 +44,7 @@ trait Jump
if (is_null($url) && isset($_SERVER["HTTP_REFERER"])) {
$url = $_SERVER["HTTP_REFERER"];
} elseif ('' !== $url) {
$url = preg_match('/^(https?:|\/)/', $url) ? $url : Url::build($url);
$url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : Url::build($url);
}
$result = [
'code' => $code,
@@ -83,7 +83,7 @@ trait Jump
if (is_null($url)) {
$url = 'javascript:history.back(-1);';
} elseif ('' !== $url) {
$url = preg_match('/^(https?:|\/)/', $url) ? $url : Url::build($url);
$url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : Url::build($url);
}
$result = [
'code' => $code,