[更新]ComposerUpdate

This commit is contained in:
Anyon 2018-08-10 14:33:02 +08:00
parent 525d582477
commit 340a0b144c
42 changed files with 628 additions and 186 deletions

View File

@ -37,8 +37,8 @@ class ToolsService
Session::init(config('session.'));
}
$token = request()->header('token', '');
empty($token) && $token = request()->post('token', '');
empty($token) && $token = request()->get('token', '');
empty($token) && $token = request()->post('token', '');
list($name, $value) = explode('=', decode($token) . '=');
if (!empty($value) && session_name() === $name) {
session_id($value);
@ -48,7 +48,7 @@ class ToolsService
header('Access-Control-Allow-Credentials:true');
header('Access-Control-Allow-Methods:GET,POST,OPTIONS');
header("Access-Control-Allow-Headers:Accept,Referer,Host,Keep-Alive,User-Agent,X-Requested-With,Cache-Control,Cookie,token");
header('Content-Type:text/plain charset=UTF-8');
header('Content-Type:text/plain charset=utf-8');
header('Access-Control-Max-Age:1728000');
header('HTTP/1.0 204 No Content');
header('Content-Length:0');

View File

@ -3,9 +3,11 @@
ThinkPHP 5.1 —— 12载初心你值得信赖的PHP框架
===============
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/top-think/framework/badges/quality-score.png?b=5.1)](https://scrutinizer-ci.com/g/top-think/framework/?branch=5.1)
[![Build Status](https://travis-ci.org/top-think/framework.svg?branch=master)](https://travis-ci.org/top-think/framework)
[![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)
[![PHP Version](https://img.shields.io/badge/php-%3E%3D5.6-8892BF.svg)](http://www.php.net/)
[![License](https://poser.pugx.org/topthink/framework/license)](https://packagist.org/packages/topthink/framework)
ThinkPHP5.1对底层架构做了进一步的改进,减少依赖,其主要特性包括:
@ -25,6 +27,7 @@ ThinkPHP5.1对底层架构做了进一步的改进,减少依赖,其主要特
+ 中间件支持(`V5.1.6+`
+ 支持`Swoole`/`Workerman`运行(`V5.1.18+`
### 废除的功能:
+ 聚合模型
@ -67,7 +70,7 @@ composer update topthink/framework
## 命名规范
`ThinkPHP5`遵循PSR-2命名规范和PSR-4自动加载规范。
`ThinkPHP5.1`遵循PSR-2命名规范和PSR-4自动加载规范。
## 参与开发

View File

@ -28,28 +28,6 @@ if (interface_exists('Psr\Log\LoggerInterface')) {
{}
}
// 注册核心类的静态代理
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\Middleware::class => Middleware::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,

View File

@ -20,7 +20,7 @@ use think\route\Dispatch;
*/
class App extends Container
{
const VERSION = '5.1.21';
const VERSION = '5.1.22';
/**
* 当前模块路径
@ -178,6 +178,8 @@ class App extends Container
$this->instance('app', $this);
$this->configExt = $this->env->get('config_ext', '.php');
// 加载惯例配置文件
$this->config->set(include $this->thinkPath . 'convention.php');
@ -204,8 +206,6 @@ class App extends Container
// 注册应用命名空间
Loader::addNamespace($this->namespace, $this->appPath);
$this->configExt = $this->env->get('config_ext', '.php');
// 初始化应用
$this->init();
@ -312,7 +312,7 @@ class App extends Container
// 自动读取配置文件
if (is_dir($path . 'config')) {
$dir = $path . 'config';
$dir = $path . 'config'.DIRECTORY_SEPARATOR;
} elseif (is_dir($this->configPath . $module)) {
$dir = $this->configPath . $module;
}
@ -321,8 +321,7 @@ class App extends Container
foreach ($files as $file) {
if ('.' . pathinfo($file, PATHINFO_EXTENSION) === $this->configExt) {
$filename = $dir . DIRECTORY_SEPARATOR . $file;
$this->config->load($filename, pathinfo($file, PATHINFO_FILENAME));
$this->config->load($dir . $file, pathinfo($file, PATHINFO_FILENAME));
}
}
}

View File

@ -249,6 +249,68 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
return new static(array_filter($this->items));
}
/**
* 根据字段条件过滤数组中的元素
* @access public
* @param string $field 字段名
* @param mixed $operator 操作符
* @param mixed $value 数据
* @return static
*/
public function where($field, $operator, $value = null)
{
if (is_null($value)) {
$value = $operator;
$operator = '=';
}
return $this->filter(function ($data) use ($field, $operator, $value) {
if (strpos($field, '.')) {
list($field, $relation) = explode('.', $field);
$result = isset($data[$field][$relation]) ? $data[$field][$relation] : null;
} else {
$result = isset($data[$field]) ? $data[$field] : null;
}
switch ($operator) {
case '===':
return $result === $value;
case '!==':
return $result !== $value;
case '!=':
case '<>':
return $result != $value;
case '>':
return $result > $value;
case '>=':
return $result >= $value;
case '<':
return $result < $value;
case '<=':
return $result <= $value;
case 'like':
return is_string($result) && false !== strpos($result, $value);
case 'not like':
return is_string($result) && false === strpos($result, $value);
case 'in':
return is_scalar($result) && in_array($result, $value, true);
case 'not in':
return is_scalar($result) && !in_array($result, $value, true);
case 'between':
list($min, $max) = is_string($value) ? explode(',', $value) : $value;
return is_scalar($result) && $result >= $min && $result <= $max;
case 'not between':
list($min, $max) = is_string($value) ? explode(',', $value) : $value;
return is_scalar($result) && $result > $max || $result < $min;
case '==':
case '=':
default:
return $result == $value;
}
});
}
/**
* 返回数据中指定的一列
* @access public

View File

@ -11,19 +11,68 @@
namespace think;
use Yaconf;
class Config implements \ArrayAccess
{
/**
* 配置参数
* @var array
*/
private $config = [];
protected $config = [];
/**
* 配置前缀
* @var string
*/
private $prefix = 'app';
protected $prefix = 'app';
/**
* 配置文件目录
* @var string
*/
protected $path;
/**
* 配置文件后缀
* @var string
*/
protected $ext;
/**
* 是否支持Yaconf
* @var bool
*/
protected $yaconf;
/**
* 构造方法
* @access public
*/
public function __construct($path = '', $ext = '.php')
{
$this->path = $path;
$this->ext = $ext;
$this->yaconf = class_exists('Yaconf');
}
public static function __make(App $app)
{
$path = $app->getConfigPath();
$ext = $app->getConfigExt();
return new static($path, $ext);
}
/**
* 设置开启Yaconf
* @access public
* @param bool $yaconf 是否使用Yaconf
* @return void
*/
public function useYaconf($yaconf)
{
$this->yaconf = $yaconf;
}
/**
* 设置配置参数默认前缀
@ -65,20 +114,34 @@ class Config implements \ArrayAccess
public function load($file, $name = '')
{
if (is_file($file)) {
$name = strtolower($name);
$type = pathinfo($file, PATHINFO_EXTENSION);
$filename = $file;
} elseif (is_file($this->path . $file . $this->ext)) {
$filename = $this->path . $file . $this->ext;
}
if ('php' == $type) {
return $this->set(include $file, $name);
} elseif ('yaml' == $type && function_exists('yaml_parse_file')) {
return $this->set(yaml_parse_file($file), $name);
}
return $this->parse($file, $type, $name);
if (isset($filename)) {
return $this->loadFile($filename, $name);
} elseif ($this->yaconf && Yaconf::has($file)) {
return $this->set(Yaconf::get($file), $name);
}
return $this->config;
}
protected function loadFile($file, $name)
{
$name = strtolower($name);
$type = pathinfo($file, PATHINFO_EXTENSION);
if ('php' == $type) {
return $this->set(include $file, $name);
} elseif ('yaml' == $type && function_exists('yaml_parse_file')) {
return $this->set(yaml_parse_file($file), $name);
}
return $this->parse($file, $type, $name);
}
/**
* 检测配置是否存在
* @access public
@ -91,10 +154,6 @@ class Config implements \ArrayAccess
$name = $this->prefix . '.' . $name;
}
if (class_exists('Yaconf')) {
return Yaconf::has($name);
}
return !is_null($this->get($name));
}
@ -108,6 +167,11 @@ class Config implements \ArrayAccess
{
$name = strtolower($name);
if ($this->yaconf && Yaconf::has($name)) {
$config = Yaconf::get($name);
return isset($this->config[$name]) ? array_merge($this->config[$name], $config) : $config;
}
return isset($this->config[$name]) ? $this->config[$name] : [];
}
@ -120,12 +184,8 @@ class Config implements \ArrayAccess
*/
public function get($name = null, $default = null)
{
if (class_exists('Yaconf')) {
if ($name && !strpos($name, '.')) {
$name = $this->prefix . '.' . $name;
}
return Yaconf::get($name, $default);
if ($name && !strpos($name, '.')) {
$name = $this->prefix . '.' . $name;
}
// 无参数时获取所有
@ -133,12 +193,14 @@ class Config implements \ArrayAccess
return $this->config;
}
if (!strpos($name, '.')) {
$name = $this->prefix . '.' . $name;
} elseif ('.' == substr($name, -1)) {
if ('.' == substr($name, -1)) {
return $this->pull(substr($name, 0, -1));
}
if ($this->yaconf && Yaconf::has($name)) {
return Yaconf::get($name);
}
$name = explode('.', $name);
$name[0] = strtolower($name[0]);
$config = $this->config;

View File

@ -57,6 +57,7 @@ class Container implements ArrayAccess, IteratorAggregate, Countable
'response' => Response::class,
'route' => Route::class,
'session' => Session::class,
'template' => Template::class,
'url' => Url::class,
'validate' => Validate::class,
'view' => View::class,

View File

@ -75,7 +75,7 @@ class Facade
}
/**
* 获取当前Facade对应类名
* 获取当前Facade对应类名(或者已经绑定的容器对象标识)
* @access protected
* @return string
*/

View File

@ -18,6 +18,7 @@ use think\db\Query;
* Class Model
* @package think
* @mixin Query
* @method \think\Model withAttr(array $name,\Closure $closure) 动态定义获取器
*/
abstract class Model implements \JsonSerializable, \ArrayAccess
{
@ -1041,6 +1042,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
public function __call($method, $args)
{
if ('withattr' == strtolower($method)) {
return call_user_func_array([$this, 'withAttribute'], $args);
}
return call_user_func_array([$this->db(), $method], $args);
}

View File

@ -70,7 +70,7 @@ class Memcache extends Driver
{
$key = $this->getCacheKey($name);
return $this->handler->get($key) ? true : false;
return false !== $this->handler->get($key);
}
/**

View File

@ -584,20 +584,13 @@ abstract class Connection
$this->bind = $bind;
// 释放前次的查询结果
if (!empty($this->PDOStatement)) {
$this->free();
}
Db::$queryTimes++;
// 调试开始
$this->debug(true);
// 预处理
if (empty($this->PDOStatement)) {
$this->PDOStatement = $this->linkID->prepare($sql);
}
$this->PDOStatement = $this->linkID->prepare($sql);
// 是否为存储过程调用
$procedure = in_array(strtolower(substr(trim($sql), 0, 4)), ['call', 'exec']);
@ -663,15 +656,8 @@ abstract class Connection
// 调试开始
$this->debug(true);
// 释放前次的查询结果
if (!empty($this->PDOStatement)) {
$this->free();
}
// 预处理
if (empty($this->PDOStatement)) {
$this->PDOStatement = $this->linkID->prepare($sql);
}
$this->PDOStatement = $this->linkID->prepare($sql);
// 是否为存储过程调用
$procedure = in_array(strtolower(substr(trim($sql), 0, 4)), ['call', 'exec']);
@ -742,15 +728,8 @@ abstract class Connection
// 调试开始
$this->debug(true);
//释放前次的查询结果
if (!empty($this->PDOStatement) && $this->PDOStatement->queryString != $sql) {
$this->free();
}
// 预处理
if (empty($this->PDOStatement)) {
$this->PDOStatement = $this->linkID->prepare($sql);
}
$this->PDOStatement = $this->linkID->prepare($sql);
// 是否为存储过程调用
$procedure = in_array(strtolower(substr(trim($sql), 0, 4)), ['call', 'exec']);
@ -1680,13 +1659,9 @@ abstract class Connection
$this->parseSavepoint('trans' . $this->transTimes)
);
}
} catch (\PDOException $e) {
if ($this->isBreak($e)) {
return $this->close()->startTrans();
}
throw $e;
} catch (\Exception $e) {
if ($this->isBreak($e)) {
--$this->transTimes;
return $this->close()->startTrans();
}
throw $e;
@ -1826,6 +1801,9 @@ abstract class Connection
$this->linkRead = null;
$this->links = [];
// 释放查询
$this->free();
return $this;
}
@ -2074,9 +2052,6 @@ abstract class Connection
*/
public function __destruct()
{
// 释放查询
$this->free();
// 关闭连接
$this->close();
}

View File

@ -1033,17 +1033,6 @@ class Query
return $this;
}
/**
* 设置数据排除字段
* @access public
* @param mixed $field 字段名或者数据
* @return $this
*/
public function hidden($field)
{
return $this->field($field, true);
}
/**
* 设置数据
* @access public
@ -2123,6 +2112,46 @@ class Query
return $this;
}
/**
* 设置需要隐藏的输出属性
* @access public
* @param mixed $hidden 需要隐藏的字段名
* @return $this
*/
public function hidden($hidden)
{
if ($this->model) {
$this->options['hidden'] = $hidden;
return $this;
}
return $this->field($hidden, true);
}
/**
* 设置需要输出的属性
* @access public
* @param array $visible 需要输出的属性
* @return $this
*/
public function visible(array $visible)
{
$this->options['visible'] = $visible;
return $this;
}
/**
* 设置需要追加输出的属性
* @access public
* @param array $append 需要追加的属性
* @return $this
*/
public function append(array $append)
{
$this->options['append'] = $append;
return $this;
}
/**
* 设置数据字段获取器
* @access public
@ -2133,14 +2162,8 @@ class Query
public function withAttr($name, $callback = null)
{
if (is_array($name)) {
foreach ($name as $key => $val) {
$key = Loader::parseName($key);
$this->options['with_attr'][$key] = $val;
}
$this->options['with_attr'] = $name;
} else {
$name = Loader::parseName($name);
$this->options['with_attr'][$name] = $callback;
}
@ -2219,6 +2242,31 @@ class Query
return $this;
}
/**
* 使用搜索器条件搜索字段
* @access public
* @param array $fields 搜索字段
* @param array $data 搜索数据
* @return $this
*/
public function withSearch(array $fields, array $data = [])
{
foreach ($fields as $key => $field) {
if ($field instanceof \Closure) {
$field($this, isset($data[$key]) ? $data[$key] : null, $data);
} elseif ($this->model) {
// 检测搜索器
$method = 'search' . Loader::parseName($field, 1) . 'Attr';
if (method_exists($this->model, $method)) {
$this->model->$method($this, isset($data[$field]) ? $data[$field] : null, $data);
}
}
}
return $this;
}
/**
* 指定数据表主键
* @access public
@ -2441,20 +2489,15 @@ class Query
/** @var Model $class */
$class = $this->model;
foreach ($with as $key => $relation) {
$subRelation = '';
$closure = false;
$closure = null;
if ($relation instanceof \Closure) {
// 支持闭包查询过滤关联条件
$closure = $relation;
$relation = $key;
$with[$key] = $key;
$closure = $relation;
$relation = $key;
} elseif (is_array($relation)) {
$subRelation = $relation;
$relation = $key;
$relation = $key;
} elseif (is_string($relation) && strpos($relation, '.')) {
$with[$key] = $relation;
list($relation, $subRelation) = explode('.', $relation, 2);
}
@ -2463,20 +2506,74 @@ class Query
$model = $class->$relation();
if ($model instanceof OneToOne && 0 == $model->getEagerlyType()) {
$model->removeOption()->eagerly($this, $relation, $subRelation, $closure, $first);
$table = $model->getTable();
$model->removeOption()
->table($table)
->eagerly($this, $relation, true, '', $closure, $first);
$first = false;
} elseif ($closure) {
$with[$key] = $closure;
}
}
$this->via();
if (isset($this->options['with'])) {
$this->options['with'] = array_merge($this->options['with'], $with);
} else {
$this->options['with'] = $with;
$this->options['with'] = $with;
return $this;
}
/**
* 关联预载入 JOIN方式不支持嵌套
* @access protected
* @param string|array $with 关联方法名
* @param string $joinType JOIN方式
* @return $this
*/
public function withJoin($with, $joinType = '')
{
if (empty($with)) {
return $this;
}
if (is_string($with)) {
$with = explode(',', $with);
}
$first = true;
/** @var Model $class */
$class = $this->model;
foreach ($with as $key => $relation) {
$closure = null;
$field = true;
if ($relation instanceof \Closure) {
// 支持闭包查询过滤关联条件
$closure = $relation;
$relation = $key;
} elseif (is_array($relation)) {
$field = $relation;
$relation = $key;
} elseif (is_string($relation) && strpos($relation, '.')) {
list($relation, $subRelation) = explode('.', $relation, 2);
}
/** @var Relation $model */
$relation = Loader::parseName($relation, 1, false);
$model = $class->$relation();
if ($model instanceof OneToOne) {
$model->eagerly($this, $relation, $field, $joinType, $closure, $first);
$first = false;
} else {
// 不支持其它关联
unset($with[$key]);
}
}
$this->via();
$this->options['with_join'] = $with;
return $this;
}
@ -2501,7 +2598,7 @@ class Query
}
foreach ($relations as $key => $relation) {
$closure = false;
$closure = null;
if ($relation instanceof \Closure) {
$closure = $relation;
$relation = $key;
@ -2866,6 +2963,11 @@ class Query
$result->eagerlyResultSet($resultSet, $this->options['with'], $withRelationAttr);
}
if (!empty($this->options['with_join'])) {
// JOIN预载入
$result->eagerlyResultSet($resultSet, $this->options['with_join'], $withRelationAttr, true);
}
// 模型数据集转换
$resultSet = $result->toCollection($resultSet);
} else {
@ -3069,6 +3171,8 @@ class Query
protected function getResultAttr(&$result, $withAttr = [])
{
foreach ($withAttr as $name => $closure) {
$name = Loader::parseName($name);
if (strpos($name, '.')) {
// 支持JSON字段 获取器定义
list($key, $field) = explode('.', $name);
@ -3139,7 +3243,18 @@ class Query
// 动态获取器
if (!empty($options['with_attr'])) {
$result->setModelAttrs($options['with_attr']);
$result->withAttribute($options['with_attr']);
}
// 输出属性控制
if (!empty($options['visible'])) {
$result->visible($options['visible']);
} elseif (!empty($options['hidden'])) {
$result->hidden($options['hidden']);
}
if (!empty($options['append'])) {
$result->append($options['append']);
}
// 关联查询
@ -3152,6 +3267,11 @@ class Query
$result->eagerlyResult($result, $options['with'], $withRelationAttr);
}
// JOIN预载入查询
if (!$resultSet && !empty($options['with_join'])) {
$result->eagerlyResult($result, $options['with_join'], $withRelationAttr, true);
}
// 关联统计
if (!empty($options['with_count'])) {
foreach ($options['with_count'] as $val) {

View File

@ -51,4 +51,13 @@ use think\Facade;
*/
class App extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'app';
}
}

View File

@ -21,4 +21,13 @@ use think\Facade;
*/
class Build extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'build';
}
}

View File

@ -33,4 +33,13 @@ use think\Facade;
*/
class Cache extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'cache';
}
}

View File

@ -18,10 +18,19 @@ use think\Facade;
* @mixin \think\Config
* @method bool has(string $name) static 检测配置是否存在
* @method array pull(string $name) static 获取一级配置
* @method mixed get(string $name) static 获取配置参数
* @method mixed get(string $name,mixed $default = null) static 获取配置参数
* @method mixed set(string $name, mixed $value = null) static 设置配置参数
* @method array reset(string $prefix ='') static 重置配置参数
*/
class Config extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'config';
}
}

View File

@ -27,4 +27,13 @@ use think\Facade;
*/
class Cookie extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'cookie';
}
}

View File

@ -28,4 +28,13 @@ use think\Facade;
*/
class Debug extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'debug';
}
}

View File

@ -22,4 +22,13 @@ use think\Facade;
*/
class Env extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'env';
}
}

View File

@ -25,4 +25,13 @@ use think\Facade;
*/
class Hook extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'hook';
}
}

View File

@ -29,4 +29,13 @@ use think\Facade;
*/
class Lang extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'lang';
}
}

View File

@ -37,4 +37,13 @@ use think\Facade;
*/
class Log extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'log';
}
}

View File

@ -24,4 +24,13 @@ use think\Facade;
*/
class Middleware extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'middleware';
}
}

View File

@ -85,4 +85,13 @@ use think\Facade;
*/
class Request extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'request';
}
}

View File

@ -35,4 +35,13 @@ use think\Facade;
*/
class Response extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'response';
}
}

View File

@ -45,4 +45,13 @@ use think\Facade;
*/
class Route extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'route';
}
}

View File

@ -34,4 +34,13 @@ use think\Facade;
*/
class Session extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'session';
}
}

View File

@ -0,0 +1,36 @@
<?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\Template
* @mixin \think\Template
* @method void assign(mixed $name, mixed $value = '') static 模板变量赋值
* @method mixed get(string $name = '') static 获取模板变量
* @method void fetch(string $template, array $vars = [], array $config = []) static 渲染模板文件
* @method void display(string $content, array $vars = [], array $config = []) static 渲染模板内容
* @method mixed layout(string $name, string $replace = '') static 设置模板布局
*/
class Template extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'template';
}
}

View File

@ -21,4 +21,13 @@ use think\Facade;
*/
class Url extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'url';
}
}

View File

@ -62,4 +62,14 @@ use think\Facade;
*/
class Validate extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'validate';
}
}

View File

@ -28,4 +28,13 @@ use think\Facade;
*/
class View extends Facade
{
/**
* 获取当前Facade对应类名或者已经绑定的容器对象标识
* @access protected
* @return string
*/
protected static function getFacadeClass()
{
return 'view';
}
}

View File

@ -93,4 +93,20 @@ class Collection extends BaseCollection
return $this;
}
/**
* 设置数据字段获取器
* @access public
* @param string|array $name 字段名
* @param callable $callback 闭包获取器
* @return $this
*/
public function withAttr($name, $callback = null)
{
$this->each(function ($model) use ($name, $callback) {
/** @var Model $model */
$model && $model->withAttribute($name, $callback);
});
return $this;
}
}

View File

@ -599,14 +599,25 @@ trait Attribute
}
/**
* 动态设置获取器
* @access protected
* @param array $attrs
* 设置数据字段获取器
* @access public
* @param string|array $name 字段名
* @param callable $callback 闭包获取器
* @return $this
*/
public function setModelAttrs(array $attrs = [])
public function withAttribute($name, $callback = null)
{
$this->withAttr = $attrs;
if (is_array($name)) {
foreach ($name as $key => $val) {
$key = Loader::parseName($key);
$this->withAttr[$key] = $val;
}
} else {
$name = Loader::parseName($name);
$this->withAttr[$name] = $callback;
}
return $this;
}

View File

@ -219,15 +219,16 @@ trait RelationShip
* @param array $resultSet 数据集
* @param string $relation 关联名
* @param array $withRelationAttr 关联获取器
* @param bool $join 是否为JOIN方式
* @return array
*/
public function eagerlyResultSet(&$resultSet, $relation, $withRelationAttr = [])
public function eagerlyResultSet(&$resultSet, $relation, $withRelationAttr = [], $join = false)
{
$relations = is_string($relation) ? explode(',', $relation) : $relation;
foreach ($relations as $key => $relation) {
$subRelation = '';
$closure = false;
$closure = null;
if ($relation instanceof \Closure) {
$closure = $relation;
@ -250,7 +251,7 @@ trait RelationShip
$relationResult->withAttr($withRelationAttr[$relationName]);
}
$relationResult->eagerlyResultSet($resultSet, $relation, $subRelation, $closure);
$relationResult->eagerlyResultSet($resultSet, $relation, $subRelation, $closure, $join);
}
}
@ -260,15 +261,16 @@ trait RelationShip
* @param Model $result 数据对象
* @param string $relation 关联名
* @param array $withRelationAttr 关联获取器
* @param bool $join 是否为JOIN方式
* @return Model
*/
public function eagerlyResult(&$result, $relation, $withRelationAttr = [])
public function eagerlyResult(&$result, $relation, $withRelationAttr = [], $join = false)
{
$relations = is_string($relation) ? explode(',', $relation) : $relation;
foreach ($relations as $key => $relation) {
$subRelation = '';
$closure = false;
$closure = null;
if ($relation instanceof \Closure) {
$closure = $relation;
@ -291,7 +293,7 @@ trait RelationShip
$relationResult->withAttr($withRelationAttr[$relationName]);
}
$relationResult->eagerlyResult($result, $relation, $subRelation, $closure);
$relationResult->eagerlyResult($result, $relation, $subRelation, $closure, $join);
}
}
@ -307,7 +309,7 @@ trait RelationShip
public function relationCount(&$result, $relations, $aggregate = 'sum', $field = '*')
{
foreach ($relations as $key => $relation) {
$closure = false;
$closure = null;
if ($relation instanceof \Closure) {
$closure = $relation;

View File

@ -50,6 +50,10 @@ trait TimeStamp
*/
protected function formatDateTime($time, $format, $timestamp = false)
{
if (empty($time)) {
return;
}
if (false !== strpos($format, '\\')) {
$time = new $format($time);
} elseif (!$timestamp && false !== $format) {

View File

@ -509,8 +509,7 @@ class BelongsToMany extends Relation
} else {
// 保存关联表数据
$model = new $this->model;
$model->save($data);
$id = $model->getLastInsID();
$id = $model->insertGetId($data);
}
} elseif (is_numeric($data) || is_string($data)) {
// 根据关联表主键直接写入中间表

View File

@ -50,12 +50,13 @@ abstract class OneToOne extends Relation
* @access public
* @param Query $query 查询对象
* @param string $relation 关联名
* @param string $subRelation 子关联
* @param mixed $field 关联字段
* @param string $joinType JOIN方式
* @param \Closure $closure 闭包条件
* @param bool $first
* @return void
*/
public function eagerly(Query $query, $relation, $subRelation, $closure, $first)
public function eagerly(Query $query, $relation, $field, $joinType, $closure, $first)
{
$name = Loader::parseName(basename(str_replace('\\', '/', get_class($this->parent))));
@ -64,24 +65,26 @@ abstract class OneToOne extends Relation
$query->table([$table => $name]);
if ($query->getOptions('field')) {
$field = $query->getOptions('field');
$masterField = $query->getOptions('field');
$query->removeOption('field');
} else {
$field = true;
$masterField = true;
}
$query->field($field, false, $table, $name);
$query->field($masterField, false, $table, $name);
}
// 预载入封装
$joinTable = $this->query->getTable();
$joinAlias = $relation;
$joinType = $joinType ?: $this->joinType;
$query->via($joinAlias);
if ($this instanceof BelongsTo) {
$query->join([$joinTable => $joinAlias], $name . '.' . $this->foreignKey . '=' . $joinAlias . '.' . $this->localKey, $this->joinType);
$joinOn = $name . '.' . $this->foreignKey . '=' . $joinAlias . '.' . $this->localKey;
} else {
$query->join([$joinTable => $joinAlias], $name . '.' . $this->localKey . '=' . $joinAlias . '.' . $this->foreignKey, $this->joinType);
$joinOn = $name . '.' . $this->localKey . '=' . $joinAlias . '.' . $this->foreignKey;
}
if ($closure) {
@ -92,16 +95,11 @@ abstract class OneToOne extends Relation
if ($query->getOptions('with_field')) {
$field = $query->getOptions('with_field');
$query->removeOption('with_field');
} else {
$field = true;
}
} elseif (isset($this->option['field'])) {
$field = $this->option['field'];
} else {
$field = true;
}
$query->field($field, false, $joinTable, $joinAlias, $relation . '__');
$query->join([$joinTable => $joinAlias], $joinOn, $joinType)
->field($field, false, $joinTable, $joinAlias, $relation . '__');
}
/**
@ -133,18 +131,19 @@ abstract class OneToOne extends Relation
* @param string $relation 当前关联名
* @param string $subRelation 子关联名
* @param \Closure $closure 闭包
* @param bool $join 是否为JOIN方式
* @return void
*/
public function eagerlyResultSet(&$resultSet, $relation, $subRelation, $closure)
public function eagerlyResultSet(&$resultSet, $relation, $subRelation, $closure, $join = false)
{
if (1 == $this->eagerlyType) {
// IN查询
$this->eagerlySet($resultSet, $relation, $subRelation, $closure);
} else {
// 模型关联组装
if ($join || 0 == $this->eagerlyType) {
// 模型JOIN关联组装
foreach ($resultSet as $result) {
$this->match($this->model, $relation, $result);
}
} else {
// IN查询
$this->eagerlySet($resultSet, $relation, $subRelation, $closure);
}
}
@ -155,16 +154,17 @@ abstract class OneToOne extends Relation
* @param string $relation 当前关联名
* @param string $subRelation 子关联名
* @param \Closure $closure 闭包
* @param bool $join 是否为JOIN方式
* @return void
*/
public function eagerlyResult(&$result, $relation, $subRelation, $closure)
public function eagerlyResult(&$result, $relation, $subRelation, $closure, $join = false)
{
if (1 == $this->eagerlyType) {
if (0 == $this->eagerlyType || $join) {
// 模型JOIN关联组装
$this->match($this->model, $relation, $result);
} else {
// IN查询
$this->eagerlyOne($result, $relation, $subRelation, $closure);
} else {
// 模型关联组装
$this->match($this->model, $relation, $result);
}
}
@ -272,9 +272,15 @@ abstract class OneToOne extends Relation
}
if (isset($list[$relation])) {
$relationModel = new $model($list[$relation]);
$relationModel->setParent(clone $result);
$relationModel->isUpdate(true);
$array = array_unique($list[$relation]);
if (count($array) == 1 && null === current($array)) {
$relationModel = null;
} else {
$relationModel = new $model($list[$relation]);
$relationModel->setParent(clone $result);
$relationModel->isUpdate(true);
}
if (!empty($this->bindAttr)) {
$this->bindAttr($relationModel, $result, $this->bindAttr);

View File

@ -182,7 +182,7 @@ abstract class Dispatch
} else {
$data = ob_get_clean();
$content = false === $data ? '' : $data;
$status = false === $data ? 204 : 200;
$status = '' === $content && $this->request->isAjax() ? 204 : 200;
$response = Response::create($content, '', $status);
}

2
vendor/autoload.php vendored
View File

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

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit5d00137d1db4a58cf3bb528ee40ba5ec
class ComposerAutoloaderInit8153982cf21eec76f214c39086ebcf52
{
private static $loader;
@ -19,15 +19,15 @@ class ComposerAutoloaderInit5d00137d1db4a58cf3bb528ee40ba5ec
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit5d00137d1db4a58cf3bb528ee40ba5ec', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit8153982cf21eec76f214c39086ebcf52', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit5d00137d1db4a58cf3bb528ee40ba5ec', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit8153982cf21eec76f214c39086ebcf52', '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\ComposerStaticInit5d00137d1db4a58cf3bb528ee40ba5ec::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit8153982cf21eec76f214c39086ebcf52::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
@ -48,19 +48,19 @@ class ComposerAutoloaderInit5d00137d1db4a58cf3bb528ee40ba5ec
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit5d00137d1db4a58cf3bb528ee40ba5ec::$files;
$includeFiles = Composer\Autoload\ComposerStaticInit8153982cf21eec76f214c39086ebcf52::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire5d00137d1db4a58cf3bb528ee40ba5ec($fileIdentifier, $file);
composerRequire8153982cf21eec76f214c39086ebcf52($fileIdentifier, $file);
}
return $loader;
}
}
function composerRequire5d00137d1db4a58cf3bb528ee40ba5ec($fileIdentifier, $file)
function composerRequire8153982cf21eec76f214c39086ebcf52($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;

View File

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

View File

@ -50,17 +50,17 @@
},
{
"name": "topthink/framework",
"version": "v5.1.21",
"version_normalized": "5.1.21.0",
"version": "v5.1.22",
"version_normalized": "5.1.22.0",
"source": {
"type": "git",
"url": "https://github.com/top-think/framework.git",
"reference": "e670467e24399c98581db1b1d39191848f3e6b4d"
"reference": "35e9878a6ba06257502c5ba664d8e3407012ad00"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/framework/zipball/e670467e24399c98581db1b1d39191848f3e6b4d",
"reference": "e670467e24399c98581db1b1d39191848f3e6b4d",
"url": "https://api.github.com/repos/top-think/framework/zipball/35e9878a6ba06257502c5ba664d8e3407012ad00",
"reference": "35e9878a6ba06257502c5ba664d8e3407012ad00",
"shasum": "",
"mirrors": [
{
@ -82,7 +82,7 @@
"sebastian/phpcpd": "2.*",
"squizlabs/php_codesniffer": "2.*"
},
"time": "2018-08-02T09:17:04+00:00",
"time": "2018-08-09T06:04:18+00:00",
"type": "think-framework",
"installation-source": "dist",
"notification-url": "https://packagist.org/downloads/",