1、tp内核更新
2、时间格式bug更新
This commit is contained in:
@@ -22,6 +22,8 @@ class Content extends Base{
|
|||||||
protected $type = array(
|
protected $type = array(
|
||||||
'id' => 'integer',
|
'id' => 'integer',
|
||||||
'cover_id' => 'integer',
|
'cover_id' => 'integer',
|
||||||
|
'create_time' => 'integer',
|
||||||
|
'update_time' => 'integer',
|
||||||
);
|
);
|
||||||
|
|
||||||
protected function setUidAttr(){
|
protected function setUidAttr(){
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ class Document extends Base{
|
|||||||
'level' => 'integer',
|
'level' => 'integer',
|
||||||
'comment' => 'integer',
|
'comment' => 'integer',
|
||||||
'view' => 'integer',
|
'view' => 'integer',
|
||||||
|
'create_time' => 'integer',
|
||||||
|
'update_time' => 'integer',
|
||||||
);
|
);
|
||||||
|
|
||||||
protected function setUidAttr(){
|
protected function setUidAttr(){
|
||||||
|
|||||||
@@ -97,10 +97,11 @@ return array(
|
|||||||
// 日志保存目录
|
// 日志保存目录
|
||||||
'path' => LOG_PATH,
|
'path' => LOG_PATH,
|
||||||
),
|
),
|
||||||
|
'app_trace' => true,
|
||||||
// 页面Trace信息
|
// 页面Trace信息
|
||||||
'trace' => array(
|
'trace' => array(
|
||||||
//支持Html,Console 设为false则不显示
|
//支持Html,Console 设为false则不显示
|
||||||
'type' => 'Html',
|
'type' => 'Console',
|
||||||
),
|
),
|
||||||
|
|
||||||
'view_replace_str' => array(
|
'view_replace_str' => array(
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
// | Author: liu21st <liu21st@gmail.com>
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
define('THINK_VERSION', '5.0.5beta');
|
define('THINK_VERSION', '5.0.5');
|
||||||
define('THINK_START_TIME', microtime(true));
|
define('THINK_START_TIME', microtime(true));
|
||||||
define('THINK_START_MEM', memory_get_usage());
|
define('THINK_START_MEM', memory_get_usage());
|
||||||
define('EXT', '.php');
|
define('EXT', '.php');
|
||||||
|
|||||||
@@ -107,6 +107,8 @@ return [
|
|||||||
'request_cache' => false,
|
'request_cache' => false,
|
||||||
// 请求缓存有效期
|
// 请求缓存有效期
|
||||||
'request_cache_expire' => null,
|
'request_cache_expire' => null,
|
||||||
|
// 全局请求缓存排除规则
|
||||||
|
'request_cache_except' => [],
|
||||||
|
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
// | 模板设置
|
// | 模板设置
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ use think\exception\HttpResponseException;
|
|||||||
use think\Lang;
|
use think\Lang;
|
||||||
use think\Loader;
|
use think\Loader;
|
||||||
use think\Log;
|
use think\Log;
|
||||||
|
use think\Model;
|
||||||
use think\Request;
|
use think\Request;
|
||||||
use think\Response;
|
use think\Response;
|
||||||
use think\Session;
|
use think\Session;
|
||||||
@@ -329,7 +330,7 @@ if (!function_exists('cookie')) {
|
|||||||
Cookie::clear($value);
|
Cookie::clear($value);
|
||||||
} elseif ('' === $value) {
|
} elseif ('' === $value) {
|
||||||
// 获取
|
// 获取
|
||||||
return 0 === strpos($name, '?') ? Cookie::has(substr($name, 1), $option) : Cookie::get($name);
|
return 0 === strpos($name, '?') ? Cookie::has(substr($name, 1), $option) : Cookie::get($name, $option);
|
||||||
} elseif (is_null($value)) {
|
} elseif (is_null($value)) {
|
||||||
// 删除
|
// 删除
|
||||||
return Cookie::delete($name);
|
return Cookie::delete($name);
|
||||||
@@ -548,3 +549,37 @@ if (!function_exists('token')) {
|
|||||||
return '<input type="hidden" name="' . $name . '" value="' . $token . '" />';
|
return '<input type="hidden" name="' . $name . '" value="' . $token . '" />';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!function_exists('load_relation')) {
|
||||||
|
/**
|
||||||
|
* 延迟预载入关联查询
|
||||||
|
* @param mixed $resultSet 数据集
|
||||||
|
* @param mixed $relation 关联
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function load_relation($resultSet, $relation)
|
||||||
|
{
|
||||||
|
$item = current($resultSet);
|
||||||
|
if ($item instanceof Model) {
|
||||||
|
$item->eagerlyResultSet($resultSet, $relation);
|
||||||
|
}
|
||||||
|
return $resultSet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('collection')) {
|
||||||
|
/**
|
||||||
|
* 数组转换为数据集对象
|
||||||
|
* @param array $resultSet 数据集数组
|
||||||
|
* @return \think\model\Collection|\think\Collection
|
||||||
|
*/
|
||||||
|
function collection($resultSet)
|
||||||
|
{
|
||||||
|
$item = current($resultSet);
|
||||||
|
if ($item instanceof Model) {
|
||||||
|
return \think\model\Collection::make($resultSet);
|
||||||
|
} else {
|
||||||
|
return \think\Collection::make($resultSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -63,4 +63,5 @@ return [
|
|||||||
'route name not exists' => '路由标识不存在(或参数不够)',
|
'route name not exists' => '路由标识不存在(或参数不够)',
|
||||||
'invalid request' => '非法请求',
|
'invalid request' => '非法请求',
|
||||||
'bind attr has exists' => '模型的属性已经存在',
|
'bind attr has exists' => '模型的属性已经存在',
|
||||||
|
'relation data not exists' => '关联数据不存在',
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ class App
|
|||||||
// 监听app_begin
|
// 监听app_begin
|
||||||
Hook::listen('app_begin', $dispatch);
|
Hook::listen('app_begin', $dispatch);
|
||||||
// 请求缓存检查
|
// 请求缓存检查
|
||||||
$request->cache($config['request_cache'], $config['request_cache_expire']);
|
$request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']);
|
||||||
|
|
||||||
switch ($dispatch['type']) {
|
switch ($dispatch['type']) {
|
||||||
case 'redirect':
|
case 'redirect':
|
||||||
@@ -336,7 +336,7 @@ class App
|
|||||||
$request->module($module);
|
$request->module($module);
|
||||||
$config = self::init($module);
|
$config = self::init($module);
|
||||||
// 模块请求缓存检查
|
// 模块请求缓存检查
|
||||||
$request->cache($config['request_cache'], $config['request_cache_expire']);
|
$request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']);
|
||||||
} else {
|
} else {
|
||||||
throw new HttpException(404, 'module not exists:' . $module);
|
throw new HttpException(404, 'module not exists:' . $module);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,9 +81,9 @@ class Cache
|
|||||||
* @param string $name 缓存标识
|
* @param string $name 缓存标识
|
||||||
* @return Driver
|
* @return Driver
|
||||||
*/
|
*/
|
||||||
public static function store($name)
|
public static function store($name = '')
|
||||||
{
|
{
|
||||||
if ('complex' == Config::get('cache.type')) {
|
if ('' !== $name && 'complex' == Config::get('cache.type')) {
|
||||||
self::connect(Config::get('cache.' . $name), strtolower($name));
|
self::connect(Config::get('cache.' . $name), strtolower($name));
|
||||||
}
|
}
|
||||||
return self::$handler;
|
return self::$handler;
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ namespace think;
|
|||||||
|
|
||||||
use think\db\Connection;
|
use think\db\Connection;
|
||||||
use think\db\Query;
|
use think\db\Query;
|
||||||
use think\paginator\Collection as PaginatorCollection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Db
|
* Class Db
|
||||||
@@ -25,21 +24,21 @@ use think\paginator\Collection as PaginatorCollection;
|
|||||||
* @method Query union(mixed $union, boolean $all = false) static UNION查询
|
* @method Query union(mixed $union, boolean $all = false) static UNION查询
|
||||||
* @method Query limit(mixed $offset, integer $length = null) static 查询LIMIT
|
* @method Query limit(mixed $offset, integer $length = null) static 查询LIMIT
|
||||||
* @method Query order(mixed $field, string $order = null) static 查询ORDER
|
* @method Query order(mixed $field, string $order = null) static 查询ORDER
|
||||||
* @method Query cache(mixed $key = true , integer $expire = null) static 设置查询缓存
|
* @method Query cache(mixed $key = null , integer $expire = null) static 设置查询缓存
|
||||||
* @method mixed value(string $field) static 获取某个字段的值
|
* @method mixed value(string $field) static 获取某个字段的值
|
||||||
* @method array column(string $field, string $key = '') static 获取某个列的值
|
* @method array column(string $field, string $key = '') static 获取某个列的值
|
||||||
* @method Query view(mixed $join, mixed $field = null, mixed $on = null, string $type = 'INNER') static 视图查询
|
* @method Query view(mixed $join, mixed $field = null, mixed $on = null, string $type = 'INNER') static 视图查询
|
||||||
* @method mixed find(mixed $data = []) static 查询单个记录
|
* @method mixed find(mixed $data = null) static 查询单个记录
|
||||||
* @method mixed select(mixed $data = []) static 查询多个记录
|
* @method mixed select(mixed $data = null) static 查询多个记录
|
||||||
* @method integer insert(array $data, boolean $replace = false, boolean $getLastInsID = false, string $sequence = null) static 插入一条记录
|
* @method integer insert(array $data, boolean $replace = false, boolean $getLastInsID = false, string $sequence = null) static 插入一条记录
|
||||||
* @method integer insertGetId(array $data, boolean $replace = false, string $sequence = null) static 插入一条记录并返回自增ID
|
* @method integer insertGetId(array $data, boolean $replace = false, string $sequence = null) static 插入一条记录并返回自增ID
|
||||||
* @method integer insertAll(array $dataSet) static 插入多条记录
|
* @method integer insertAll(array $dataSet) static 插入多条记录
|
||||||
* @method integer update(array $data) static 更新记录
|
* @method integer update(array $data) static 更新记录
|
||||||
* @method integer delete(mixed $data = []) static 删除记录
|
* @method integer delete(mixed $data = null) static 删除记录
|
||||||
* @method boolean chunk(integer $count, callable $callback, string $column = null) static 分块获取数据
|
* @method boolean chunk(integer $count, callable $callback, string $column = null) static 分块获取数据
|
||||||
* @method mixed query(string $sql, array $bind = [], boolean $fetch = false, boolean $master = false, mixed $class = false) static SQL查询
|
* @method mixed query(string $sql, array $bind = [], boolean $fetch = false, boolean $master = false, mixed $class = null) static SQL查询
|
||||||
* @method integer execute(string $sql, array $bind = [], boolean $fetch = false, boolean $getLastInsID = false, string $sequence = null) static SQL执行
|
* @method integer execute(string $sql, array $bind = [], boolean $fetch = false, boolean $getLastInsID = false, string $sequence = null) static SQL执行
|
||||||
* @method PaginatorCollection paginate(integer $listRows = 15, mixed $simple = false, array $config = []) static 分页查询
|
* @method Paginator paginate(integer $listRows = 15, mixed $simple = null, array $config = []) static 分页查询
|
||||||
* @method mixed transaction(callable $callback) static 执行数据库事务
|
* @method mixed transaction(callable $callback) static 执行数据库事务
|
||||||
* @method void startTrans() static 启动事务
|
* @method void startTrans() static 启动事务
|
||||||
* @method void commit() static 用于非自动提交状态下面的查询提交
|
* @method void commit() static 用于非自动提交状态下面的查询提交
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ namespace think;
|
|||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use think\db\Query;
|
use think\db\Query;
|
||||||
use think\Exception\ValidateException;
|
use think\Exception\ValidateException;
|
||||||
|
use think\model\Collection;
|
||||||
use think\model\Relation;
|
use think\model\Relation;
|
||||||
use think\model\relation\BelongsTo;
|
use think\model\relation\BelongsTo;
|
||||||
use think\model\relation\BelongsToMany;
|
use think\model\relation\BelongsToMany;
|
||||||
@@ -22,23 +23,11 @@ use think\model\relation\HasManyThrough;
|
|||||||
use think\model\relation\HasOne;
|
use think\model\relation\HasOne;
|
||||||
use think\model\relation\MorphMany;
|
use think\model\relation\MorphMany;
|
||||||
use think\model\relation\MorphTo;
|
use think\model\relation\MorphTo;
|
||||||
use think\paginator\Collection as PaginatorCollection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Model
|
* Class Model
|
||||||
* @package think
|
* @package think
|
||||||
* @method static PaginatorCollection paginate(integer $listRows = 15, boolean $simple = false, array $config = []) 分页查询
|
* @mixin Query
|
||||||
* @method static mixed value($field, $default = null) 得到某个字段的值
|
|
||||||
* @method static array column($field, $key = '') 得到某个列的数组
|
|
||||||
* @method static integer count($field = '*') COUNT查询
|
|
||||||
* @method static integer sum($field = '*') SUM查询
|
|
||||||
* @method static integer min($field = '*') MIN查询
|
|
||||||
* @method static integer max($field = '*') MAX查询
|
|
||||||
* @method static integer avg($field = '*') AVG查询
|
|
||||||
* @method static setField($field, $value = '')
|
|
||||||
* @method static Query where($field, $op = null, $condition = null) 指定AND查询条件
|
|
||||||
* @method static static findOrFail($data = null) 查找单条记录 如果不存在则抛出异常
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
abstract class Model implements \JsonSerializable, \ArrayAccess
|
abstract class Model implements \JsonSerializable, \ArrayAccess
|
||||||
{
|
{
|
||||||
@@ -107,6 +96,8 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
protected $batchValidate = false;
|
protected $batchValidate = false;
|
||||||
// 查询数据集对象
|
// 查询数据集对象
|
||||||
protected $resultSetType;
|
protected $resultSetType;
|
||||||
|
// 关联自动写入
|
||||||
|
protected $relationWrite;
|
||||||
//
|
//
|
||||||
protected static $db;
|
protected static $db;
|
||||||
|
|
||||||
@@ -153,6 +144,9 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
$this->dateFormat = $this->db(false)->getConfig('datetime_format');
|
$this->dateFormat = $this->db(false)->getConfig('datetime_format');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_null($this->resultSetType)) {
|
||||||
|
$this->resultSetType = $this->db(false)->getConfig('resultset_type');
|
||||||
|
}
|
||||||
// 执行初始化操作
|
// 执行初始化操作
|
||||||
$this->initialize();
|
$this->initialize();
|
||||||
}
|
}
|
||||||
@@ -221,7 +215,8 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected static function init()
|
protected static function init()
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置数据对象值
|
* 设置数据对象值
|
||||||
@@ -330,7 +325,12 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
$value = $_SERVER['REQUEST_TIME'];
|
$value = $_SERVER['REQUEST_TIME'];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} elseif (is_string($this->autoWriteTimestamp) && in_array(strtolower($this->autoWriteTimestamp), ['datetime', 'date', 'timestamp'])) {
|
} elseif (is_string($this->autoWriteTimestamp) && in_array(strtolower($this->autoWriteTimestamp), [
|
||||||
|
'datetime',
|
||||||
|
'date',
|
||||||
|
'timestamp'
|
||||||
|
])
|
||||||
|
) {
|
||||||
$value = $this->formatDateTime($_SERVER['REQUEST_TIME'], $this->dateFormat);
|
$value = $this->formatDateTime($_SERVER['REQUEST_TIME'], $this->dateFormat);
|
||||||
} else {
|
} else {
|
||||||
$value = $this->formatDateTime($_SERVER['REQUEST_TIME'], $this->dateFormat, true);
|
$value = $this->formatDateTime($_SERVER['REQUEST_TIME'], $this->dateFormat, true);
|
||||||
@@ -438,7 +438,12 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
// 类型转换
|
// 类型转换
|
||||||
$value = $this->readTransform($value, $this->type[$name]);
|
$value = $this->readTransform($value, $this->type[$name]);
|
||||||
} elseif (in_array($name, [$this->createTime, $this->updateTime])) {
|
} elseif (in_array($name, [$this->createTime, $this->updateTime])) {
|
||||||
if (is_string($this->autoWriteTimestamp) && in_array(strtolower($this->autoWriteTimestamp), ['datetime', 'date', 'timestamp'])) {
|
if (is_string($this->autoWriteTimestamp) && in_array(strtolower($this->autoWriteTimestamp), [
|
||||||
|
'datetime',
|
||||||
|
'date',
|
||||||
|
'timestamp'
|
||||||
|
])
|
||||||
|
) {
|
||||||
$value = $this->formatDateTime(strtotime($value), $this->dateFormat);
|
$value = $this->formatDateTime(strtotime($value), $this->dateFormat);
|
||||||
} else {
|
} else {
|
||||||
$value = $this->formatDateTime($value, $this->dateFormat);
|
$value = $this->formatDateTime($value, $this->dateFormat);
|
||||||
@@ -539,6 +544,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
* @param string $relation 关联方法
|
* @param string $relation 关联方法
|
||||||
* @param string|array $append 追加属性名
|
* @param string|array $append 追加属性名
|
||||||
* @return $this
|
* @return $this
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function appendRelationAttr($relation, $append)
|
public function appendRelationAttr($relation, $append)
|
||||||
{
|
{
|
||||||
@@ -574,6 +580,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置需要输出的属性
|
* 设置需要输出的属性
|
||||||
|
* @access public
|
||||||
* @param array $visible
|
* @param array $visible
|
||||||
* @param bool $override 是否覆盖
|
* @param bool $override 是否覆盖
|
||||||
* @return $this
|
* @return $this
|
||||||
@@ -584,6 +591,56 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析隐藏及显示属性
|
||||||
|
* @access protected
|
||||||
|
* @param array $attrs 属性
|
||||||
|
* @param array $result 结果集
|
||||||
|
* @param bool $visible
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function parseAttr($attrs, &$result, $visible = true)
|
||||||
|
{
|
||||||
|
$array = [];
|
||||||
|
foreach ($attrs as $key => $val) {
|
||||||
|
if (is_array($val)) {
|
||||||
|
if ($visible) {
|
||||||
|
$array[] = $key;
|
||||||
|
}
|
||||||
|
$result[$key] = $val;
|
||||||
|
} elseif (strpos($val, '.')) {
|
||||||
|
list($key, $name) = explode('.', $val);
|
||||||
|
if ($visible) {
|
||||||
|
$array[] = $key;
|
||||||
|
}
|
||||||
|
$result[$key][] = $name;
|
||||||
|
} else {
|
||||||
|
$array[] = $val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换子模型对象
|
||||||
|
* @access protected
|
||||||
|
* @param Model|Collection $model
|
||||||
|
* @param $visible
|
||||||
|
* @param $hidden
|
||||||
|
* @param $key
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function subToArray($model, $visible, $hidden, $key)
|
||||||
|
{
|
||||||
|
// 关联模型对象
|
||||||
|
if (isset($visible[$key])) {
|
||||||
|
$model->visible($visible[$key]);
|
||||||
|
} elseif (isset($hidden[$key])) {
|
||||||
|
$model->hidden($hidden[$key]);
|
||||||
|
}
|
||||||
|
return $model->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 转换当前模型对象为数组
|
* 转换当前模型对象为数组
|
||||||
* @access public
|
* @access public
|
||||||
@@ -592,12 +649,15 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
public function toArray()
|
public function toArray()
|
||||||
{
|
{
|
||||||
$item = [];
|
$item = [];
|
||||||
|
$visible = [];
|
||||||
|
$hidden = [];
|
||||||
// 过滤属性
|
// 过滤属性
|
||||||
if (!empty($this->visible)) {
|
if (!empty($this->visible)) {
|
||||||
$data = array_intersect_key($this->data, array_flip($this->visible));
|
$array = $this->parseAttr($this->visible, $visible);
|
||||||
|
$data = array_intersect_key($this->data, array_flip($array));
|
||||||
} elseif (!empty($this->hidden)) {
|
} elseif (!empty($this->hidden)) {
|
||||||
$data = array_diff_key($this->data, array_flip($this->hidden));
|
$array = $this->parseAttr($this->hidden, $hidden, false);
|
||||||
|
$data = array_diff_key($this->data, array_flip($array));
|
||||||
} else {
|
} else {
|
||||||
$data = $this->data;
|
$data = $this->data;
|
||||||
}
|
}
|
||||||
@@ -605,12 +665,12 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
foreach ($data as $key => $val) {
|
foreach ($data as $key => $val) {
|
||||||
if ($val instanceof Model || $val instanceof Collection) {
|
if ($val instanceof Model || $val instanceof Collection) {
|
||||||
// 关联模型对象
|
// 关联模型对象
|
||||||
$item[$key] = $val->toArray();
|
$item[$key] = $this->subToArray($val, $visible, $hidden, $key);
|
||||||
} elseif (is_array($val) && reset($val) instanceof Model) {
|
} elseif (is_array($val) && reset($val) instanceof Model) {
|
||||||
// 关联模型数据集
|
// 关联模型数据集
|
||||||
$arr = [];
|
$arr = [];
|
||||||
foreach ($val as $k => $value) {
|
foreach ($val as $k => $value) {
|
||||||
$arr[$k] = $value->toArray();
|
$arr[$k] = $this->subToArray($value, $visible, $hidden, $k);
|
||||||
}
|
}
|
||||||
$item[$key] = $arr;
|
$item[$key] = $arr;
|
||||||
} else {
|
} else {
|
||||||
@@ -620,10 +680,21 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
}
|
}
|
||||||
// 追加属性(必须定义获取器)
|
// 追加属性(必须定义获取器)
|
||||||
if (!empty($this->append)) {
|
if (!empty($this->append)) {
|
||||||
foreach ($this->append as $name) {
|
foreach ($this->append as $key => $name) {
|
||||||
|
if (is_array($name)) {
|
||||||
|
// 追加关联对象属性
|
||||||
|
$relation = $this->getAttr($key);
|
||||||
|
$item[$key] = $relation->append($name)->toArray();
|
||||||
|
} elseif (strpos($name, '.')) {
|
||||||
|
list($key, $attr) = explode('.', $name);
|
||||||
|
// 追加关联对象属性
|
||||||
|
$relation = $this->getAttr($key);
|
||||||
|
$item[$key] = $relation->append([$attr])->toArray();
|
||||||
|
} else {
|
||||||
$item[$name] = $this->getAttr($name);
|
$item[$name] = $this->getAttr($name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return !empty($item) ? $item : [];
|
return !empty($item) ? $item : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -649,7 +720,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
if ($this->resultSetType) {
|
if ($this->resultSetType) {
|
||||||
if ('collection' == $this->resultSetType) {
|
if ('collection' == $this->resultSetType) {
|
||||||
$collection = new Collection($collection);
|
$collection = new Collection($collection);
|
||||||
} else {
|
} elseif (false !== strpos($this->resultSetType, '\\')) {
|
||||||
$class = $this->resultSetType;
|
$class = $this->resultSetType;
|
||||||
$collection = new $class($collection);
|
$collection = new $class($collection);
|
||||||
}
|
}
|
||||||
@@ -657,6 +728,21 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
return $collection;
|
return $collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关联数据一起更新
|
||||||
|
* @access public
|
||||||
|
* @param mixed $relation 关联
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function together($relation)
|
||||||
|
{
|
||||||
|
if (is_string($relation)) {
|
||||||
|
$relation = explode(',', $relation);
|
||||||
|
}
|
||||||
|
$this->relationWrite = $relation;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取模型对象的主键
|
* 获取模型对象的主键
|
||||||
* @access public
|
* @access public
|
||||||
@@ -715,8 +801,32 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 自动关联写入
|
||||||
|
if (!empty($this->relationWrite)) {
|
||||||
|
$relation = [];
|
||||||
|
foreach ($this->relationWrite as $key => $name) {
|
||||||
|
if (!is_numeric($key)) {
|
||||||
|
$relation[$key] = [];
|
||||||
|
foreach ($name as $val) {
|
||||||
|
if (isset($this->data[$val])) {
|
||||||
|
$relation[$key][$val] = $this->data[$val];
|
||||||
|
unset($this->data[$val]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elseif (isset($this->data[$name])) {
|
||||||
|
$relation[$name] = $this->data[$name];
|
||||||
|
if (!$this->isUpdate) {
|
||||||
|
unset($this->data[$name]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 检测字段
|
// 检测字段
|
||||||
if (!empty($this->field)) {
|
if (!empty($this->field)) {
|
||||||
|
if (true === $this->field) {
|
||||||
|
$this->field = $this->db(false)->getTableInfo('', 'fields');
|
||||||
|
}
|
||||||
foreach ($this->data as $key => $val) {
|
foreach ($this->data as $key => $val) {
|
||||||
if (!in_array($key, $this->field)) {
|
if (!in_array($key, $this->field)) {
|
||||||
unset($this->data[$key]);
|
unset($this->data[$key]);
|
||||||
@@ -775,7 +885,33 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
unset($data[$pk]);
|
unset($data[$pk]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 关联更新
|
||||||
|
if (isset($relation)) {
|
||||||
|
foreach ($relation as $name => $val) {
|
||||||
|
if (isset($data[$name])) {
|
||||||
|
unset($data[$name]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模型更新
|
||||||
$result = $this->db()->where($where)->update($data);
|
$result = $this->db()->where($where)->update($data);
|
||||||
|
|
||||||
|
// 关联更新
|
||||||
|
if (isset($relation)) {
|
||||||
|
foreach ($relation as $name => $val) {
|
||||||
|
if ($val instanceof Model) {
|
||||||
|
$val->save();
|
||||||
|
} else {
|
||||||
|
unset($this->data[$name]);
|
||||||
|
$model = $this->getAttr($name);
|
||||||
|
if ($model instanceof Model) {
|
||||||
|
$model->save($val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 清空change
|
// 清空change
|
||||||
$this->change = [];
|
$this->change = [];
|
||||||
// 更新回调
|
// 更新回调
|
||||||
@@ -802,6 +938,15 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
$this->data[$pk] = $insertId;
|
$this->data[$pk] = $insertId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 关联写入
|
||||||
|
if (isset($relation)) {
|
||||||
|
foreach ($relation as $name => $val) {
|
||||||
|
$method = Loader::parseName($name, 1, false);
|
||||||
|
$this->$method()->save($val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 标记为更新
|
// 标记为更新
|
||||||
$this->isUpdate = true;
|
$this->isUpdate = true;
|
||||||
// 清空change
|
// 清空change
|
||||||
@@ -821,6 +966,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
* @param array $dataSet 数据
|
* @param array $dataSet 数据
|
||||||
* @param boolean $replace 是否自动识别更新和写入
|
* @param boolean $replace 是否自动识别更新和写入
|
||||||
* @return array|false
|
* @return array|false
|
||||||
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function saveAll($dataSet, $replace = true)
|
public function saveAll($dataSet, $replace = true)
|
||||||
{
|
{
|
||||||
@@ -860,13 +1006,13 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
/**
|
/**
|
||||||
* 设置允许写入的字段
|
* 设置允许写入的字段
|
||||||
* @access public
|
* @access public
|
||||||
* @param bool|array $field 允许写入的字段 如果为true只允许写入数据表字段
|
* @param mixed $field 允许写入的字段 如果为true只允许写入数据表字段
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function allowField($field)
|
public function allowField($field)
|
||||||
{
|
{
|
||||||
if (true === $field) {
|
if (is_string($field)) {
|
||||||
$field = $this->db(false)->getTableInfo('', 'fields');
|
$field = explode(',', $field);
|
||||||
}
|
}
|
||||||
$this->field = $field;
|
$this->field = $field;
|
||||||
return $this;
|
return $this;
|
||||||
@@ -918,7 +1064,29 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $this->db()->delete($this->data);
|
// 删除条件
|
||||||
|
$pk = $this->getPk();
|
||||||
|
if (isset($this->data[$pk])) {
|
||||||
|
$where = [$pk => $this->data[$pk]];
|
||||||
|
} elseif (!empty($this->updateWhere)) {
|
||||||
|
$where = $this->updateWhere;
|
||||||
|
} else {
|
||||||
|
$where = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除当前模型数据
|
||||||
|
$result = $this->db()->where($where)->delete();
|
||||||
|
|
||||||
|
// 关联删除
|
||||||
|
if (!empty($this->relationWrite)) {
|
||||||
|
foreach ($this->relationWrite as $key => $name) {
|
||||||
|
$name = is_numeric($key) ? $name : $key;
|
||||||
|
$model = $this->getAttr($name);
|
||||||
|
if ($model instanceof Model) {
|
||||||
|
$model->delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->trigger('after_delete', $this);
|
$this->trigger('after_delete', $this);
|
||||||
return $result;
|
return $result;
|
||||||
@@ -1183,9 +1351,9 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
/**
|
/**
|
||||||
* 命名范围
|
* 命名范围
|
||||||
* @access public
|
* @access public
|
||||||
* @param string|array|Closure $name 命名范围名称 逗号分隔
|
* @param string|array|\Closure $name 命名范围名称 逗号分隔
|
||||||
* @param mixed ...$params 参数调用
|
* @internal mixed ...$params 参数调用
|
||||||
* @return Model
|
* @return Model|Query
|
||||||
*/
|
*/
|
||||||
public static function scope($name)
|
public static function scope($name)
|
||||||
{
|
{
|
||||||
@@ -1228,7 +1396,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
* 根据关联条件查询当前模型
|
* 根据关联条件查询当前模型
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $relation 关联方法名
|
* @param string $relation 关联方法名
|
||||||
* @param string $operator 比较操作符
|
* @param mixed $operator 比较操作符
|
||||||
* @param integer $count 个数
|
* @param integer $count 个数
|
||||||
* @param string $id 关联表的统计字段
|
* @param string $id 关联表的统计字段
|
||||||
* @return Model
|
* @return Model
|
||||||
@@ -1236,7 +1404,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
public static function has($relation, $operator = '>=', $count = 1, $id = '*')
|
public static function has($relation, $operator = '>=', $count = 1, $id = '*')
|
||||||
{
|
{
|
||||||
$model = new static();
|
$model = new static();
|
||||||
return $model->$relation()->has($model, $operator, $count, $id);
|
if (is_array($operator) || $operator instanceof \Closure) {
|
||||||
|
return $model->$relation()->hasWhere($operator);
|
||||||
|
}
|
||||||
|
return $model->$relation()->has($operator, $count, $id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1249,7 +1420,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
public static function hasWhere($relation, $where = [])
|
public static function hasWhere($relation, $where = [])
|
||||||
{
|
{
|
||||||
$model = new static();
|
$model = new static();
|
||||||
return $model->$relation()->hasWhere($model, $where);
|
return $model->$relation()->hasWhere($where);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1281,8 +1452,19 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
$relations = explode(',', $relations);
|
$relations = explode(',', $relations);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($relations as $relation) {
|
foreach ($relations as $key => $relation) {
|
||||||
$this->data[$relation] = $this->$relation()->getRelation();
|
$subRelation = '';
|
||||||
|
$closure = null;
|
||||||
|
if ($relation instanceof \Closure) {
|
||||||
|
// 支持闭包查询过滤关联条件
|
||||||
|
$closure = $relation;
|
||||||
|
$relation = $key;
|
||||||
|
}
|
||||||
|
if (strpos($relation, '.')) {
|
||||||
|
list($relation, $subRelation) = explode('.', $relation, 2);
|
||||||
|
}
|
||||||
|
$method = Loader::parseName($relation, 1, false);
|
||||||
|
$this->data[$relation] = $this->$method()->getRelation($subRelation, $closure);
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@@ -1292,10 +1474,9 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
* @access public
|
* @access public
|
||||||
* @param array $resultSet 数据集
|
* @param array $resultSet 数据集
|
||||||
* @param string $relation 关联名
|
* @param string $relation 关联名
|
||||||
* @param string $class 数据集对象名 为空表示数组
|
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function eagerlyResultSet(&$resultSet, $relation, $class = '')
|
public function eagerlyResultSet(&$resultSet, $relation)
|
||||||
{
|
{
|
||||||
$relations = is_string($relation) ? explode(',', $relation) : $relation;
|
$relations = is_string($relation) ? explode(',', $relation) : $relation;
|
||||||
foreach ($relations as $key => $relation) {
|
foreach ($relations as $key => $relation) {
|
||||||
@@ -1306,10 +1487,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
$relation = $key;
|
$relation = $key;
|
||||||
}
|
}
|
||||||
if (strpos($relation, '.')) {
|
if (strpos($relation, '.')) {
|
||||||
list($relation, $subRelation) = explode('.', $relation);
|
list($relation, $subRelation) = explode('.', $relation, 2);
|
||||||
}
|
}
|
||||||
$relation = Loader::parseName($relation, 1, false);
|
$relation = Loader::parseName($relation, 1, false);
|
||||||
$this->$relation()->eagerlyResultSet($resultSet, $relation, $subRelation, $closure, $class);
|
$this->$relation()->eagerlyResultSet($resultSet, $relation, $subRelation, $closure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1318,10 +1499,9 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
* @access public
|
* @access public
|
||||||
* @param Model $result 数据对象
|
* @param Model $result 数据对象
|
||||||
* @param string $relation 关联名
|
* @param string $relation 关联名
|
||||||
* @param string $class 数据集对象名 为空表示数组
|
|
||||||
* @return Model
|
* @return Model
|
||||||
*/
|
*/
|
||||||
public function eagerlyResult(&$result, $relation, $class = '')
|
public function eagerlyResult(&$result, $relation)
|
||||||
{
|
{
|
||||||
$relations = is_string($relation) ? explode(',', $relation) : $relation;
|
$relations = is_string($relation) ? explode(',', $relation) : $relation;
|
||||||
|
|
||||||
@@ -1333,10 +1513,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
$relation = $key;
|
$relation = $key;
|
||||||
}
|
}
|
||||||
if (strpos($relation, '.')) {
|
if (strpos($relation, '.')) {
|
||||||
list($relation, $subRelation) = explode('.', $relation);
|
list($relation, $subRelation) = explode('.', $relation, 2);
|
||||||
}
|
}
|
||||||
$relation = Loader::parseName($relation, 1, false);
|
$relation = Loader::parseName($relation, 1, false);
|
||||||
$this->$relation()->eagerlyResult($result, $relation, $subRelation, $closure, $class);
|
$this->$relation()->eagerlyResult($result, $relation, $subRelation, $closure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1363,13 +1543,27 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取模型的默认外键名
|
||||||
|
* @access public
|
||||||
|
* @param string $name 模型名
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getForeignKey($name)
|
||||||
|
{
|
||||||
|
if (strpos($name, '\\')) {
|
||||||
|
$name = basename(str_replace('\\', '/', $name));
|
||||||
|
}
|
||||||
|
return Loader::parseName($name) . '_id';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HAS ONE 关联定义
|
* HAS ONE 关联定义
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $model 模型名
|
* @param string $model 模型名
|
||||||
* @param string $foreignKey 关联外键
|
* @param string $foreignKey 关联外键
|
||||||
* @param string $localKey 关联主键
|
* @param string $localKey 关联主键
|
||||||
* @param array $alias 别名定义
|
* @param array $alias 别名定义(已经废弃)
|
||||||
* @param string $joinType JOIN类型
|
* @param string $joinType JOIN类型
|
||||||
* @return HasOne
|
* @return HasOne
|
||||||
*/
|
*/
|
||||||
@@ -1378,8 +1572,8 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
// 记录当前关联信息
|
// 记录当前关联信息
|
||||||
$model = $this->parseModel($model);
|
$model = $this->parseModel($model);
|
||||||
$localKey = $localKey ?: $this->getPk();
|
$localKey = $localKey ?: $this->getPk();
|
||||||
$foreignKey = $foreignKey ?: Loader::parseName($this->name) . '_id';
|
$foreignKey = $foreignKey ?: $this->getForeignKey($this->name);
|
||||||
return new HasOne($this, $model, $foreignKey, $localKey, $alias, $joinType);
|
return new HasOne($this, $model, $foreignKey, $localKey, $joinType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1387,18 +1581,18 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
* @access public
|
* @access public
|
||||||
* @param string $model 模型名
|
* @param string $model 模型名
|
||||||
* @param string $foreignKey 关联外键
|
* @param string $foreignKey 关联外键
|
||||||
* @param string $otherKey 关联主键
|
* @param string $localKey 关联主键
|
||||||
* @param array $alias 别名定义
|
* @param array $alias 别名定义(已经废弃)
|
||||||
* @param string $joinType JOIN类型
|
* @param string $joinType JOIN类型
|
||||||
* @return BelongsTo
|
* @return BelongsTo
|
||||||
*/
|
*/
|
||||||
public function belongsTo($model, $foreignKey = '', $otherKey = '', $alias = [], $joinType = 'INNER')
|
public function belongsTo($model, $foreignKey = '', $localKey = '', $alias = [], $joinType = 'INNER')
|
||||||
{
|
{
|
||||||
// 记录当前关联信息
|
// 记录当前关联信息
|
||||||
$model = $this->parseModel($model);
|
$model = $this->parseModel($model);
|
||||||
$foreignKey = $foreignKey ?: Loader::parseName(basename(str_replace('\\', '/', $model))) . '_id';
|
$foreignKey = $foreignKey ?: $this->getForeignKey($model);
|
||||||
$otherKey = $otherKey ?: (new $model)->getPk();
|
$localKey = $localKey ?: (new $model)->getPk();
|
||||||
return new BelongsTo($this, $model, $foreignKey, $otherKey, $alias, $joinType);
|
return new BelongsTo($this, $model, $foreignKey, $localKey, $joinType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1407,16 +1601,15 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
* @param string $model 模型名
|
* @param string $model 模型名
|
||||||
* @param string $foreignKey 关联外键
|
* @param string $foreignKey 关联外键
|
||||||
* @param string $localKey 关联主键
|
* @param string $localKey 关联主键
|
||||||
* @param array $alias 别名定义
|
|
||||||
* @return HasMany
|
* @return HasMany
|
||||||
*/
|
*/
|
||||||
public function hasMany($model, $foreignKey = '', $localKey = '', $alias = [])
|
public function hasMany($model, $foreignKey = '', $localKey = '')
|
||||||
{
|
{
|
||||||
// 记录当前关联信息
|
// 记录当前关联信息
|
||||||
$model = $this->parseModel($model);
|
$model = $this->parseModel($model);
|
||||||
$localKey = $localKey ?: $this->getPk();
|
$localKey = $localKey ?: $this->getPk();
|
||||||
$foreignKey = $foreignKey ?: Loader::parseName($this->name) . '_id';
|
$foreignKey = $foreignKey ?: $this->getForeignKey($this->name);
|
||||||
return new HasMany($this, $model, $foreignKey, $localKey, $alias);
|
return new HasMany($this, $model, $foreignKey, $localKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1427,19 +1620,17 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
* @param string $foreignKey 关联外键
|
* @param string $foreignKey 关联外键
|
||||||
* @param string $throughKey 关联外键
|
* @param string $throughKey 关联外键
|
||||||
* @param string $localKey 关联主键
|
* @param string $localKey 关联主键
|
||||||
* @param array $alias 别名定义
|
|
||||||
* @return HasManyThrough
|
* @return HasManyThrough
|
||||||
*/
|
*/
|
||||||
public function hasManyThrough($model, $through, $foreignKey = '', $throughKey = '', $localKey = '', $alias = [])
|
public function hasManyThrough($model, $through, $foreignKey = '', $throughKey = '', $localKey = '')
|
||||||
{
|
{
|
||||||
// 记录当前关联信息
|
// 记录当前关联信息
|
||||||
$model = $this->parseModel($model);
|
$model = $this->parseModel($model);
|
||||||
$through = $this->parseModel($through);
|
$through = $this->parseModel($through);
|
||||||
$localKey = $localKey ?: $this->getPk();
|
$localKey = $localKey ?: $this->getPk();
|
||||||
$foreignKey = $foreignKey ?: Loader::parseName($this->name) . '_id';
|
$foreignKey = $foreignKey ?: $this->getForeignKey($this->name);
|
||||||
$name = Loader::parseName(basename(str_replace('\\', '/', $through)));
|
$throughKey = $throughKey ?: $this->getForeignKey($through);
|
||||||
$throughKey = $throughKey ?: $name . '_id';
|
return new HasManyThrough($this, $model, $through, $foreignKey, $throughKey, $localKey);
|
||||||
return new HasManyThrough($this, $model, $through, $foreignKey, $throughKey, $localKey, $alias);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1449,18 +1640,17 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
* @param string $table 中间表名
|
* @param string $table 中间表名
|
||||||
* @param string $foreignKey 关联外键
|
* @param string $foreignKey 关联外键
|
||||||
* @param string $localKey 当前模型关联键
|
* @param string $localKey 当前模型关联键
|
||||||
* @param array $alias 别名定义
|
|
||||||
* @return BelongsToMany
|
* @return BelongsToMany
|
||||||
*/
|
*/
|
||||||
public function belongsToMany($model, $table = '', $foreignKey = '', $localKey = '', $alias = [])
|
public function belongsToMany($model, $table = '', $foreignKey = '', $localKey = '')
|
||||||
{
|
{
|
||||||
// 记录当前关联信息
|
// 记录当前关联信息
|
||||||
$model = $this->parseModel($model);
|
$model = $this->parseModel($model);
|
||||||
$name = Loader::parseName(basename(str_replace('\\', '/', $model)));
|
$name = Loader::parseName(basename(str_replace('\\', '/', $model)));
|
||||||
$table = $table ?: $this->db(false)->getTable(Loader::parseName($this->name) . '_' . $name);
|
$table = $table ?: $this->db(false)->getTable(Loader::parseName($this->name) . '_' . $name);
|
||||||
$foreignKey = $foreignKey ?: $name . '_id';
|
$foreignKey = $foreignKey ?: $name . '_id';
|
||||||
$localKey = $localKey ?: Loader::parseName($this->name) . '_id';
|
$localKey = $localKey ?: $this->getForeignKey($this->name);
|
||||||
return new BelongsToMany($this, $model, $table, $foreignKey, $localKey, $alias);
|
return new BelongsToMany($this, $model, $table, $foreignKey, $localKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1641,6 +1831,8 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 模型事件快捷方法
|
* 模型事件快捷方法
|
||||||
|
* @param $callback
|
||||||
|
* @param bool $override
|
||||||
*/
|
*/
|
||||||
protected static function beforeInsert($callback, $override = false)
|
protected static function beforeInsert($callback, $override = false)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,14 +11,19 @@
|
|||||||
|
|
||||||
namespace think;
|
namespace think;
|
||||||
|
|
||||||
use think\paginator\Collection as PaginatorCollection;
|
use ArrayAccess;
|
||||||
|
use ArrayIterator;
|
||||||
|
use Countable;
|
||||||
|
use IteratorAggregate;
|
||||||
|
use JsonSerializable;
|
||||||
|
use Traversable;
|
||||||
|
|
||||||
abstract class Paginator
|
abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable
|
||||||
{
|
{
|
||||||
/** @var bool 是否为简洁模式 */
|
/** @var bool 是否为简洁模式 */
|
||||||
protected $simple = false;
|
protected $simple = false;
|
||||||
|
|
||||||
/** @var PaginatorCollection 数据集 */
|
/** @var Collection 数据集 */
|
||||||
protected $items;
|
protected $items;
|
||||||
|
|
||||||
/** @var integer 当前页 */
|
/** @var integer 当前页 */
|
||||||
@@ -44,7 +49,7 @@ abstract class Paginator
|
|||||||
'fragment' => '',
|
'fragment' => '',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected function __construct($items, $listRows, $currentPage = null, $total = null, $simple = false, $options = [])
|
public function __construct($items, $listRows, $currentPage = null, $total = null, $simple = false, $options = [])
|
||||||
{
|
{
|
||||||
$this->options = array_merge($this->options, $options);
|
$this->options = array_merge($this->options, $options);
|
||||||
|
|
||||||
@@ -53,10 +58,11 @@ abstract class Paginator
|
|||||||
$this->simple = $simple;
|
$this->simple = $simple;
|
||||||
$this->listRows = $listRows;
|
$this->listRows = $listRows;
|
||||||
|
|
||||||
if ($simple) {
|
|
||||||
if (!$items instanceof Collection) {
|
if (!$items instanceof Collection) {
|
||||||
$items = Collection::make($items);
|
$items = Collection::make($items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($simple) {
|
||||||
$this->currentPage = $this->setCurrentPage($currentPage);
|
$this->currentPage = $this->setCurrentPage($currentPage);
|
||||||
$this->hasMore = count($items) > ($this->listRows);
|
$this->hasMore = count($items) > ($this->listRows);
|
||||||
$items = $items->slice(0, $this->listRows);
|
$items = $items->slice(0, $this->listRows);
|
||||||
@@ -66,8 +72,7 @@ abstract class Paginator
|
|||||||
$this->currentPage = $this->setCurrentPage($currentPage);
|
$this->currentPage = $this->setCurrentPage($currentPage);
|
||||||
$this->hasMore = $this->currentPage < $this->lastPage;
|
$this->hasMore = $this->currentPage < $this->lastPage;
|
||||||
}
|
}
|
||||||
|
$this->items = $items;
|
||||||
$this->items = PaginatorCollection::make($items, $this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,12 +82,11 @@ abstract class Paginator
|
|||||||
* @param bool $simple
|
* @param bool $simple
|
||||||
* @param null $total
|
* @param null $total
|
||||||
* @param array $options
|
* @param array $options
|
||||||
* @return PaginatorCollection
|
* @return Paginator
|
||||||
*/
|
*/
|
||||||
public static function make($items, $listRows, $currentPage = null, $total = null, $simple = false, $options = [])
|
public static function make($items, $listRows, $currentPage = null, $total = null, $simple = false, $options = [])
|
||||||
{
|
{
|
||||||
$paginator = new static($items, $listRows, $currentPage, $total, $simple, $options);
|
return new static($items, $listRows, $currentPage, $total, $simple, $options);
|
||||||
return $paginator->items;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function setCurrentPage($currentPage)
|
protected function setCurrentPage($currentPage)
|
||||||
@@ -253,4 +257,113 @@ abstract class Paginator
|
|||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
abstract public function render();
|
abstract public function render();
|
||||||
|
|
||||||
|
public function items()
|
||||||
|
{
|
||||||
|
return $this->items->all();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCollection()
|
||||||
|
{
|
||||||
|
return $this->items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isEmpty()
|
||||||
|
{
|
||||||
|
return $this->items->isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve an external iterator
|
||||||
|
* @return Traversable An instance of an object implementing <b>Iterator</b> or
|
||||||
|
* <b>Traversable</b>
|
||||||
|
*/
|
||||||
|
public function getIterator()
|
||||||
|
{
|
||||||
|
return new ArrayIterator($this->items->all());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether a offset exists
|
||||||
|
* @param mixed $offset
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function offsetExists($offset)
|
||||||
|
{
|
||||||
|
return $this->items->offsetExists($offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offset to retrieve
|
||||||
|
* @param mixed $offset
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function offsetGet($offset)
|
||||||
|
{
|
||||||
|
return $this->items->offsetGet($offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offset to set
|
||||||
|
* @param mixed $offset
|
||||||
|
* @param mixed $value
|
||||||
|
*/
|
||||||
|
public function offsetSet($offset, $value)
|
||||||
|
{
|
||||||
|
$this->items->offsetSet($offset, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offset to unset
|
||||||
|
* @param mixed $offset
|
||||||
|
* @return void
|
||||||
|
* @since 5.0.0
|
||||||
|
*/
|
||||||
|
public function offsetUnset($offset)
|
||||||
|
{
|
||||||
|
$this->items->offsetUnset($offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count elements of an object
|
||||||
|
*/
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
|
return $this->items->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return (string) $this->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toArray()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$total = $this->total();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$total = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'total' => $total,
|
||||||
|
'per_page' => $this->listRows(),
|
||||||
|
'current_page' => $this->currentPage(),
|
||||||
|
'data' => $this->items->toArray()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify data which should be serialized to JSON
|
||||||
|
*/
|
||||||
|
public function jsonSerialize()
|
||||||
|
{
|
||||||
|
return $this->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __call($name, $arguments)
|
||||||
|
{
|
||||||
|
return call_user_func_array([$this->getCollection(), $name], $arguments);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1502,9 +1502,10 @@ class Request
|
|||||||
* @access public
|
* @access public
|
||||||
* @param string $key 缓存标识,支持变量规则 ,例如 item/:name/:id
|
* @param string $key 缓存标识,支持变量规则 ,例如 item/:name/:id
|
||||||
* @param mixed $expire 缓存有效期
|
* @param mixed $expire 缓存有效期
|
||||||
|
* @param array $except 缓存排除
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function cache($key, $expire = null)
|
public function cache($key, $expire = null, $except = [])
|
||||||
{
|
{
|
||||||
if (false !== $key && $this->isGet() && !$this->isCheckCache) {
|
if (false !== $key && $this->isGet() && !$this->isCheckCache) {
|
||||||
// 标记请求缓存检查
|
// 标记请求缓存检查
|
||||||
@@ -1516,6 +1517,11 @@ class Request
|
|||||||
if ($key instanceof \Closure) {
|
if ($key instanceof \Closure) {
|
||||||
$key = call_user_func_array($key, [$this]);
|
$key = call_user_func_array($key, [$this]);
|
||||||
} elseif (true === $key) {
|
} elseif (true === $key) {
|
||||||
|
foreach ($except as $rule) {
|
||||||
|
if (0 === strpos($this->url(), $rule)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
// 自动缓存功能
|
// 自动缓存功能
|
||||||
$key = '__URL__';
|
$key = '__URL__';
|
||||||
} elseif (strpos($key, '|')) {
|
} elseif (strpos($key, '|')) {
|
||||||
|
|||||||
@@ -568,7 +568,7 @@ class Validate
|
|||||||
break;
|
break;
|
||||||
case 'ip':
|
case 'ip':
|
||||||
// 是否为IP地址
|
// 是否为IP地址
|
||||||
$result = $this->filter($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6);
|
$result = $this->filter($value, [FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6]);
|
||||||
break;
|
break;
|
||||||
case 'url':
|
case 'url':
|
||||||
// 是否为一个URL地址
|
// 是否为一个URL地址
|
||||||
@@ -591,7 +591,7 @@ class Validate
|
|||||||
break;
|
break;
|
||||||
case 'boolean':
|
case 'boolean':
|
||||||
// 是否为布尔值
|
// 是否为布尔值
|
||||||
$result = in_array($value, [0, 1, true, false]);
|
$result = in_array($value, [true, false, 0, 1, '0', '1'], true);
|
||||||
break;
|
break;
|
||||||
case 'array':
|
case 'array':
|
||||||
// 是否为数组
|
// 是否为数组
|
||||||
|
|||||||
@@ -112,8 +112,8 @@ abstract class Builder
|
|||||||
$result[$item] = $val;
|
$result[$item] = $val;
|
||||||
} else {
|
} else {
|
||||||
$key = str_replace('.', '_', $key);
|
$key = str_replace('.', '_', $key);
|
||||||
$this->query->bind($key, $val, isset($bind[$key]) ? $bind[$key] : PDO::PARAM_STR);
|
$this->query->bind('__data__' . $key, $val, isset($bind[$key]) ? $bind[$key] : PDO::PARAM_STR);
|
||||||
$result[$item] = ':' . $key;
|
$result[$item] = ':__data__' . $key;
|
||||||
}
|
}
|
||||||
} elseif (is_object($val) && method_exists($val, '__toString')) {
|
} elseif (is_object($val) && method_exists($val, '__toString')) {
|
||||||
// 对象数据写入
|
// 对象数据写入
|
||||||
@@ -523,10 +523,12 @@ abstract class Builder
|
|||||||
$array = [];
|
$array = [];
|
||||||
foreach ($order as $key => $val) {
|
foreach ($order as $key => $val) {
|
||||||
if (is_numeric($key)) {
|
if (is_numeric($key)) {
|
||||||
if (false === strpos($val, '(')) {
|
if ('[rand]' == $val) {
|
||||||
$array[] = $this->parseKey($val, $options);
|
|
||||||
} elseif ('[rand]' == $val) {
|
|
||||||
$array[] = $this->parseRand();
|
$array[] = $this->parseRand();
|
||||||
|
} elseif (false === strpos($val, '(')) {
|
||||||
|
$array[] = $this->parseKey($val, $options);
|
||||||
|
} else {
|
||||||
|
$array[] = $val;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$sort = in_array(strtolower(trim($val)), ['asc', 'desc']) ? ' ' . $val : '';
|
$sort = in_array(strtolower(trim($val)), ['asc', 'desc']) ? ' ' . $val : '';
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ namespace think\db;
|
|||||||
|
|
||||||
use PDO;
|
use PDO;
|
||||||
use PDOStatement;
|
use PDOStatement;
|
||||||
use think\Collection;
|
|
||||||
use think\Db;
|
use think\Db;
|
||||||
use think\db\exception\BindParamException;
|
use think\db\exception\BindParamException;
|
||||||
use think\Debug;
|
use think\Debug;
|
||||||
@@ -51,8 +50,6 @@ abstract class Connection
|
|||||||
protected $linkRead;
|
protected $linkRead;
|
||||||
protected $linkWrite;
|
protected $linkWrite;
|
||||||
|
|
||||||
// 查询结果类型
|
|
||||||
protected $resultSetType = 'array';
|
|
||||||
// 查询结果类型
|
// 查询结果类型
|
||||||
protected $fetchType = PDO::FETCH_ASSOC;
|
protected $fetchType = PDO::FETCH_ASSOC;
|
||||||
// 字段属性大小写
|
// 字段属性大小写
|
||||||
@@ -61,6 +58,8 @@ abstract class Connection
|
|||||||
protected static $event = [];
|
protected static $event = [];
|
||||||
// 查询对象
|
// 查询对象
|
||||||
protected $query = [];
|
protected $query = [];
|
||||||
|
// 使用Builder类
|
||||||
|
protected $builder;
|
||||||
// 数据库连接参数配置
|
// 数据库连接参数配置
|
||||||
protected $config = [
|
protected $config = [
|
||||||
// 数据库类型
|
// 数据库类型
|
||||||
@@ -151,6 +150,20 @@ abstract class Connection
|
|||||||
return $this->query[$model];
|
return $this->query[$model];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前连接器类对应的Builder类
|
||||||
|
* @access public
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getBuilder()
|
||||||
|
{
|
||||||
|
if (!empty($this->builder)) {
|
||||||
|
return $this->builder;
|
||||||
|
} else {
|
||||||
|
return $this->getConfig('builder') ?: '\\think\\db\\builder\\' . ucfirst($this->getConfig('type'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 调用Query类的查询方法
|
* 调用Query类的查询方法
|
||||||
* @access public
|
* @access public
|
||||||
@@ -270,10 +283,7 @@ abstract class Connection
|
|||||||
}
|
}
|
||||||
// 记录当前字段属性大小写设置
|
// 记录当前字段属性大小写设置
|
||||||
$this->attrCase = $params[PDO::ATTR_CASE];
|
$this->attrCase = $params[PDO::ATTR_CASE];
|
||||||
// 记录数据集返回类型
|
|
||||||
if (isset($config['resultset_type'])) {
|
|
||||||
$this->resultSetType = $config['resultset_type'];
|
|
||||||
}
|
|
||||||
// 数据返回类型
|
// 数据返回类型
|
||||||
if (isset($config['result_type'])) {
|
if (isset($config['result_type'])) {
|
||||||
$this->fetchType = $config['result_type'];
|
$this->fetchType = $config['result_type'];
|
||||||
@@ -511,11 +521,13 @@ abstract class Connection
|
|||||||
protected function bindParam($bind)
|
protected function bindParam($bind)
|
||||||
{
|
{
|
||||||
foreach ($bind as $key => $val) {
|
foreach ($bind as $key => $val) {
|
||||||
if (is_numeric($key)) {
|
$param = is_numeric($key) ? $key + 1 : ':' . $key;
|
||||||
$key = $key + 1;
|
if (is_array($val)) {
|
||||||
}
|
array_unshift($val, $param);
|
||||||
array_unshift($val, $key);
|
|
||||||
$result = call_user_func_array([$this->PDOStatement, 'bindParam'], $val);
|
$result = call_user_func_array([$this->PDOStatement, 'bindParam'], $val);
|
||||||
|
} else {
|
||||||
|
$result = $this->PDOStatement->bindValue($param, $val);
|
||||||
|
}
|
||||||
if (!$result) {
|
if (!$result) {
|
||||||
$param = array_shift($val);
|
$param = array_shift($val);
|
||||||
throw new BindParamException(
|
throw new BindParamException(
|
||||||
@@ -529,11 +541,11 @@ abstract class Connection
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得数据集
|
* 获得数据集数组
|
||||||
* @access protected
|
* @access protected
|
||||||
* @param bool $pdo 是否返回PDOStatement
|
* @param bool $pdo 是否返回PDOStatement
|
||||||
* @param bool $procedure 是否存储过程
|
* @param bool $procedure 是否存储过程
|
||||||
* @return mixed
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function getResult($pdo = false, $procedure = false)
|
protected function getResult($pdo = false, $procedure = false)
|
||||||
{
|
{
|
||||||
@@ -547,11 +559,6 @@ abstract class Connection
|
|||||||
}
|
}
|
||||||
$result = $this->PDOStatement->fetchAll($this->fetchType);
|
$result = $this->PDOStatement->fetchAll($this->fetchType);
|
||||||
$this->numRows = count($result);
|
$this->numRows = count($result);
|
||||||
|
|
||||||
if ('collection' == $this->resultSetType) {
|
|
||||||
// 返回数据集Collection对象
|
|
||||||
$result = new Collection($result);
|
|
||||||
}
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -746,6 +753,9 @@ abstract class Connection
|
|||||||
public function close()
|
public function close()
|
||||||
{
|
{
|
||||||
$this->linkID = null;
|
$this->linkID = null;
|
||||||
|
$this->linkWrite = null;
|
||||||
|
$this->linkRead = null;
|
||||||
|
$this->links = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -124,8 +124,7 @@ class Query
|
|||||||
*/
|
*/
|
||||||
protected function setBuilder()
|
protected function setBuilder()
|
||||||
{
|
{
|
||||||
$builder = $this->connection->getConfig('builder') ?: $this->connection->getConfig('type');
|
$class = $this->connection->getBuilder();
|
||||||
$class = false !== strpos($builder, '\\') ? $builder : '\\think\\db\\builder\\' . ucfirst($builder);
|
|
||||||
$this->builder = new $class($this->connection, $this);
|
$this->builder = new $class($this->connection, $this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,10 +508,17 @@ class Query
|
|||||||
* COUNT查询
|
* COUNT查询
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $field 字段名
|
* @param string $field 字段名
|
||||||
* @return integer
|
* @return integer|string
|
||||||
*/
|
*/
|
||||||
public function count($field = '*')
|
public function count($field = '*')
|
||||||
{
|
{
|
||||||
|
if (isset($this->options['group'])) {
|
||||||
|
// 支持GROUP
|
||||||
|
$options = $this->getOptions();
|
||||||
|
$subSql = $this->options($options)->field('count(' . $field . ')')->bind($this->bind)->buildSql();
|
||||||
|
return $this->table([$subSql => '_group_count_'])->value('COUNT(*) AS tp_count', 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->value('COUNT(' . $field . ') AS tp_count', 0, true);
|
return $this->value('COUNT(' . $field . ') AS tp_count', 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1170,7 +1176,9 @@ class Query
|
|||||||
} elseif (is_null($condition)) {
|
} elseif (is_null($condition)) {
|
||||||
// 字段相等查询
|
// 字段相等查询
|
||||||
$where[$field] = ['eq', $op];
|
$where[$field] = ['eq', $op];
|
||||||
|
if ('AND' != $logic) {
|
||||||
$this->options['multi'][$logic][$field][] = $where[$field];
|
$this->options['multi'][$logic][$field][] = $where[$field];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$where[$field] = [$op, $condition, isset($param[2]) ? $param[2] : null];
|
$where[$field] = [$op, $condition, isset($param[2]) ? $param[2] : null];
|
||||||
if ('exp' == strtolower($op) && isset($param[2]) && is_array($param[2])) {
|
if ('exp' == strtolower($op) && isset($param[2]) && is_array($param[2])) {
|
||||||
@@ -1285,7 +1293,7 @@ class Query
|
|||||||
* var_page:分页变量,
|
* var_page:分页变量,
|
||||||
* list_rows:每页数量
|
* list_rows:每页数量
|
||||||
* type:分页类名
|
* type:分页类名
|
||||||
* @return \think\paginator\Collection
|
* @return \think\Paginator
|
||||||
* @throws DbException
|
* @throws DbException
|
||||||
*/
|
*/
|
||||||
public function paginate($listRows = null, $simple = false, $config = [])
|
public function paginate($listRows = null, $simple = false, $config = [])
|
||||||
@@ -1315,9 +1323,9 @@ class Query
|
|||||||
|
|
||||||
if (!isset($total) && !$simple) {
|
if (!isset($total) && !$simple) {
|
||||||
$options = $this->getOptions();
|
$options = $this->getOptions();
|
||||||
if (isset($options['order'])) {
|
|
||||||
unset($this->options['order']);
|
unset($this->options['order'], $this->options['limit'], $this->options['page'], $this->options['field']);
|
||||||
}
|
|
||||||
$bind = $this->bind;
|
$bind = $this->bind;
|
||||||
$total = $this->count();
|
$total = $this->count();
|
||||||
$results = $this->options($options)->bind($bind)->page($page, $listRows)->select();
|
$results = $this->options($options)->bind($bind)->page($page, $listRows)->select();
|
||||||
@@ -1902,7 +1910,11 @@ class Query
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->via();
|
$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;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1967,12 +1979,22 @@ class Query
|
|||||||
/**
|
/**
|
||||||
* 设置关联查询
|
* 设置关联查询
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $relation 关联名称
|
* @param string|array $relation 关联名称
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function relation($relation)
|
public function relation($relation)
|
||||||
{
|
{
|
||||||
|
if (empty($relation)) {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
if (is_string($relation)) {
|
||||||
|
$relation = explode(',', $relation);
|
||||||
|
}
|
||||||
|
if (isset($this->options['relation'])) {
|
||||||
|
$this->options['relation'] = array_mrege($this->options['relation'], $relation);
|
||||||
|
} else {
|
||||||
$this->options['relation'] = $relation;
|
$this->options['relation'] = $relation;
|
||||||
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2280,29 +2302,35 @@ class Query
|
|||||||
// 数据列表读取后的处理
|
// 数据列表读取后的处理
|
||||||
if (!empty($this->model)) {
|
if (!empty($this->model)) {
|
||||||
// 生成模型对象
|
// 生成模型对象
|
||||||
$model = $this->model;
|
$modelName = $this->model;
|
||||||
if (count($resultSet) > 0) {
|
if (count($resultSet) > 0) {
|
||||||
foreach ($resultSet as $key => $result) {
|
foreach ($resultSet as $key => $result) {
|
||||||
/** @var Model $result */
|
/** @var Model $result */
|
||||||
$result = new $model($result);
|
$model = new $modelName($result);
|
||||||
$result->isUpdate(true);
|
$model->isUpdate(true);
|
||||||
|
|
||||||
// 关联查询
|
// 关联查询
|
||||||
if (!empty($options['relation'])) {
|
if (!empty($options['relation'])) {
|
||||||
$result->relationQuery($options['relation']);
|
$model->relationQuery($options['relation']);
|
||||||
}
|
}
|
||||||
// 关联统计
|
// 关联统计
|
||||||
if (!empty($options['with_count'])) {
|
if (!empty($options['with_count'])) {
|
||||||
$result->relationCount($result, $options['with_count']);
|
$model->relationCount($model, $options['with_count']);
|
||||||
}
|
}
|
||||||
$resultSet[$key] = $result;
|
$resultSet[$key] = $model;
|
||||||
}
|
}
|
||||||
if (!empty($options['with'])) {
|
if (!empty($options['with'])) {
|
||||||
// 预载入
|
// 预载入
|
||||||
$result->eagerlyResultSet($resultSet, $options['with'], is_object($resultSet) ? get_class($resultSet) : '');
|
$model->eagerlyResultSet($resultSet, $options['with']);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// 模型数据集转换
|
// 模型数据集转换
|
||||||
$resultSet = (new $model)->toCollection($resultSet);
|
$resultSet = $model->toCollection($resultSet);
|
||||||
|
} else {
|
||||||
|
$resultSet = (new $modelName)->toCollection($resultSet);
|
||||||
|
}
|
||||||
|
} elseif ('collection' == $this->connection->getConfig('resultset_type')) {
|
||||||
|
// 返回Collection对象
|
||||||
|
$resultSet = new Collection($resultSet);
|
||||||
}
|
}
|
||||||
// 返回结果处理
|
// 返回结果处理
|
||||||
if (!empty($options['fail']) && count($resultSet) == 0) {
|
if (!empty($options['fail']) && count($resultSet) == 0) {
|
||||||
@@ -2394,7 +2422,7 @@ class Query
|
|||||||
}
|
}
|
||||||
// 预载入查询
|
// 预载入查询
|
||||||
if (!empty($options['with'])) {
|
if (!empty($options['with'])) {
|
||||||
$data->eagerlyResult($data, $options['with'], is_object($result) ? get_class($result) : '');
|
$data->eagerlyResult($data, $options['with']);
|
||||||
}
|
}
|
||||||
// 关联统计
|
// 关联统计
|
||||||
if (!empty($options['with_count'])) {
|
if (!empty($options['with_count'])) {
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ use think\Log;
|
|||||||
class Mysql extends Connection
|
class Mysql extends Connection
|
||||||
{
|
{
|
||||||
|
|
||||||
|
protected $builder = '\\think\\db\\builder\\Mysql';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析pdo连接的dsn信息
|
* 解析pdo连接的dsn信息
|
||||||
* @access protected
|
* @access protected
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ use think\db\Connection;
|
|||||||
*/
|
*/
|
||||||
class Pgsql extends Connection
|
class Pgsql extends Connection
|
||||||
{
|
{
|
||||||
|
protected $builder = '\\think\\db\\builder\\Pgsql';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析pdo连接的dsn信息
|
* 解析pdo连接的dsn信息
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ use think\db\Connection;
|
|||||||
class Sqlite extends Connection
|
class Sqlite extends Connection
|
||||||
{
|
{
|
||||||
|
|
||||||
|
protected $builder = '\\think\\db\\builder\\Sqlite';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析pdo连接的dsn信息
|
* 解析pdo连接的dsn信息
|
||||||
* @access protected
|
* @access protected
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class Sqlsrv extends Connection
|
|||||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||||
PDO::ATTR_STRINGIFY_FETCHES => false,
|
PDO::ATTR_STRINGIFY_FETCHES => false,
|
||||||
];
|
];
|
||||||
|
protected $builder = '\\think\\db\\builder\\Sqlsrv';
|
||||||
/**
|
/**
|
||||||
* 解析pdo连接的dsn信息
|
* 解析pdo连接的dsn信息
|
||||||
* @access protected
|
* @access protected
|
||||||
|
|||||||
79
core/library/think/model/Collection.php
Normal file
79
core/library/think/model/Collection.php
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: zhangyajun <448901948@qq.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace think\model;
|
||||||
|
|
||||||
|
use think\Collection as BaseCollection;
|
||||||
|
use think\Model;
|
||||||
|
|
||||||
|
class Collection extends BaseCollection
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 延迟预载入关联查询
|
||||||
|
* @access public
|
||||||
|
* @param mixed $relation 关联
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function load($relation)
|
||||||
|
{
|
||||||
|
$item = current($this->items);
|
||||||
|
$item->eagerlyResultSet($this->items, $relation);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置需要隐藏的输出属性
|
||||||
|
* @access public
|
||||||
|
* @param array $hidden 属性列表
|
||||||
|
* @param bool $override 是否覆盖
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function hidden($hidden = [], $override = false)
|
||||||
|
{
|
||||||
|
$this->each(function ($model) use ($hidden, $override) {
|
||||||
|
/** @var Model $model */
|
||||||
|
$model->hidden($hidden, $override);
|
||||||
|
});
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置需要输出的属性
|
||||||
|
* @param array $visible
|
||||||
|
* @param bool $override 是否覆盖
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function visible($visible = [], $override = false)
|
||||||
|
{
|
||||||
|
$this->each(function ($model) use ($visible, $override) {
|
||||||
|
/** @var Model $model */
|
||||||
|
$model->visible($visible, $override);
|
||||||
|
});
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置需要追加的输出属性
|
||||||
|
* @access public
|
||||||
|
* @param array $append 属性列表
|
||||||
|
* @param bool $override 是否覆盖
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function append($append = [], $override = false)
|
||||||
|
{
|
||||||
|
$this->each(function ($model) use ($append, $override) {
|
||||||
|
/** @var Model $model */
|
||||||
|
$model->append($append, $override);
|
||||||
|
});
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
namespace think\model;
|
namespace think\model;
|
||||||
|
|
||||||
use think\Db;
|
|
||||||
use think\db\Query;
|
use think\db\Query;
|
||||||
use think\Model;
|
use think\Model;
|
||||||
|
|
||||||
@@ -41,7 +40,7 @@ class Merge extends Model
|
|||||||
* 查找单条记录
|
* 查找单条记录
|
||||||
* @access public
|
* @access public
|
||||||
* @param mixed $data 主键值或者查询条件(闭包)
|
* @param mixed $data 主键值或者查询条件(闭包)
|
||||||
* @param string $with 关联预查询
|
* @param string|array $with 关联预查询
|
||||||
* @param bool $cache 是否缓存
|
* @param bool $cache 是否缓存
|
||||||
* @return \think\Model
|
* @return \think\Model
|
||||||
*/
|
*/
|
||||||
@@ -105,7 +104,8 @@ class Merge extends Model
|
|||||||
* 查找所有记录
|
* 查找所有记录
|
||||||
* @access public
|
* @access public
|
||||||
* @param mixed $data 主键列表或者查询条件(闭包)
|
* @param mixed $data 主键列表或者查询条件(闭包)
|
||||||
* @param string $with 关联预查询
|
* @param array|string $with 关联预查询
|
||||||
|
* @param bool $cache
|
||||||
* @return array|false|string
|
* @return array|false|string
|
||||||
*/
|
*/
|
||||||
public static function all($data = null, $with = [], $cache = false)
|
public static function all($data = null, $with = [], $cache = false)
|
||||||
@@ -121,7 +121,7 @@ class Merge extends Model
|
|||||||
* @param string $model 模型名称
|
* @param string $model 模型名称
|
||||||
* @param array $data 数据
|
* @param array $data 数据
|
||||||
* @param bool $insert 是否新增
|
* @param bool $insert 是否新增
|
||||||
* @return void
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function parseData($model, $data, $insert = false)
|
protected function parseData($model, $data, $insert = false)
|
||||||
{
|
{
|
||||||
@@ -147,7 +147,8 @@ class Merge extends Model
|
|||||||
* @param mixed $data 数据
|
* @param mixed $data 数据
|
||||||
* @param array $where 更新条件
|
* @param array $where 更新条件
|
||||||
* @param string $sequence 自增序列名
|
* @param string $sequence 自增序列名
|
||||||
* @return integer|false
|
* @return false|int
|
||||||
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function save($data = [], $where = [], $sequence = null)
|
public function save($data = [], $where = [], $sequence = null)
|
||||||
{
|
{
|
||||||
@@ -158,7 +159,7 @@ class Merge extends Model
|
|||||||
}
|
}
|
||||||
// 数据对象赋值
|
// 数据对象赋值
|
||||||
foreach ($data as $key => $value) {
|
foreach ($data as $key => $value) {
|
||||||
$this->setAttr($key, $value);
|
$this->setAttr($key, $value, $data);
|
||||||
}
|
}
|
||||||
if (!empty($where)) {
|
if (!empty($where)) {
|
||||||
$this->isUpdate = true;
|
$this->isUpdate = true;
|
||||||
@@ -278,7 +279,8 @@ class Merge extends Model
|
|||||||
/**
|
/**
|
||||||
* 删除当前的记录 并删除关联数据
|
* 删除当前的记录 并删除关联数据
|
||||||
* @access public
|
* @access public
|
||||||
* @return integer
|
* @return int
|
||||||
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function delete()
|
public function delete()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,24 +15,24 @@ use think\db\Query;
|
|||||||
use think\Exception;
|
use think\Exception;
|
||||||
use think\Model;
|
use think\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Relation
|
||||||
|
* @package think\model
|
||||||
|
*
|
||||||
|
* @mixin Query
|
||||||
|
*/
|
||||||
abstract class Relation
|
abstract class Relation
|
||||||
{
|
{
|
||||||
// 父模型对象
|
// 父模型对象
|
||||||
protected $parent;
|
protected $parent;
|
||||||
/** @var Model 当前关联的模型类 */
|
/** @var Model 当前关联的模型类 */
|
||||||
protected $model;
|
protected $model;
|
||||||
|
/** @var Query 关联模型查询对象 */
|
||||||
|
protected $query;
|
||||||
// 关联表外键
|
// 关联表外键
|
||||||
protected $foreignKey;
|
protected $foreignKey;
|
||||||
// 关联表主键
|
// 关联表主键
|
||||||
protected $localKey;
|
protected $localKey;
|
||||||
// 数据表别名
|
|
||||||
protected $alias;
|
|
||||||
// 当前关联的JOIN类型
|
|
||||||
protected $joinType;
|
|
||||||
// 关联模型查询对象
|
|
||||||
protected $query;
|
|
||||||
// 关联查询条件
|
|
||||||
protected $where;
|
|
||||||
// 关联查询参数
|
// 关联查询参数
|
||||||
protected $option;
|
protected $option;
|
||||||
// 基础查询
|
// 基础查询
|
||||||
@@ -72,24 +72,11 @@ abstract class Relation
|
|||||||
* 封装关联数据集
|
* 封装关联数据集
|
||||||
* @access public
|
* @access public
|
||||||
* @param array $resultSet 数据集
|
* @param array $resultSet 数据集
|
||||||
* @param string $class 数据集类名
|
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
protected function resultSetBuild($resultSet, $class = '')
|
protected function resultSetBuild($resultSet)
|
||||||
{
|
{
|
||||||
return $class ? new $class($resultSet) : $resultSet;
|
return (new $this->model)->toCollection($resultSet);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置当前关联定义的数据表别名
|
|
||||||
* @access public
|
|
||||||
* @param array $alias 别名定义
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setAlias($alias)
|
|
||||||
{
|
|
||||||
$this->alias = $alias;
|
|
||||||
return $this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,6 +90,13 @@ abstract class Relation
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行基础查询(进执行一次)
|
||||||
|
* @access protected
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
abstract protected function baseQuery();
|
||||||
|
|
||||||
public function __call($method, $args)
|
public function __call($method, $args)
|
||||||
{
|
{
|
||||||
if ($this->query) {
|
if ($this->query) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace think\model\relation;
|
namespace think\model\relation;
|
||||||
|
|
||||||
|
use think\Loader;
|
||||||
use think\Model;
|
use think\Model;
|
||||||
|
|
||||||
class BelongsTo extends OneToOne
|
class BelongsTo extends OneToOne
|
||||||
@@ -22,29 +23,32 @@ class BelongsTo extends OneToOne
|
|||||||
* @param string $model 模型名
|
* @param string $model 模型名
|
||||||
* @param string $foreignKey 关联外键
|
* @param string $foreignKey 关联外键
|
||||||
* @param string $localKey 关联主键
|
* @param string $localKey 关联主键
|
||||||
* @param array $alias 别名定义
|
|
||||||
* @param string $joinType JOIN类型
|
* @param string $joinType JOIN类型
|
||||||
*/
|
*/
|
||||||
public function __construct(Model $parent, $model, $foreignKey, $localKey, $alias = [], $joinType = 'INNER')
|
public function __construct(Model $parent, $model, $foreignKey, $localKey, $joinType = 'INNER')
|
||||||
{
|
{
|
||||||
$this->parent = $parent;
|
$this->parent = $parent;
|
||||||
$this->model = $model;
|
$this->model = $model;
|
||||||
$this->foreignKey = $foreignKey;
|
$this->foreignKey = $foreignKey;
|
||||||
$this->localKey = $localKey;
|
$this->localKey = $localKey;
|
||||||
$this->alias = $alias;
|
|
||||||
$this->joinType = $joinType;
|
$this->joinType = $joinType;
|
||||||
$this->query = (new $model)->db();
|
$this->query = (new $model)->db();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 延迟获取关联数据
|
* 延迟获取关联数据
|
||||||
|
* @param string $subRelation 子关联名
|
||||||
|
* @param \Closure $closure 闭包查询条件
|
||||||
* @access public
|
* @access public
|
||||||
|
* @return array|false|\PDOStatement|string|Model
|
||||||
*/
|
*/
|
||||||
public function getRelation()
|
public function getRelation($subRelation = '', $closure = null)
|
||||||
{
|
{
|
||||||
$foreignKey = $this->foreignKey;
|
$foreignKey = $this->foreignKey;
|
||||||
$localKey = $this->localKey;
|
if ($closure) {
|
||||||
return $this->query->where($localKey, $this->parent->$foreignKey)->find();
|
call_user_func_array($closure, [ & $this->query]);
|
||||||
|
}
|
||||||
|
return $this->query->where($this->localKey, $this->parent->$foreignKey)->relation($subRelation)->find();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,10 +58,9 @@ class BelongsTo extends OneToOne
|
|||||||
* @param string $relation 当前关联名
|
* @param string $relation 当前关联名
|
||||||
* @param string $subRelation 子关联名
|
* @param string $subRelation 子关联名
|
||||||
* @param \Closure $closure 闭包
|
* @param \Closure $closure 闭包
|
||||||
* @param string $class 数据集对象名 为空表示数组
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function eagerlySet(&$resultSet, $relation, $subRelation, $closure, $class)
|
protected function eagerlySet(&$resultSet, $relation, $subRelation, $closure)
|
||||||
{
|
{
|
||||||
$localKey = $this->localKey;
|
$localKey = $this->localKey;
|
||||||
$foreignKey = $this->foreignKey;
|
$foreignKey = $this->foreignKey;
|
||||||
@@ -71,26 +74,29 @@ class BelongsTo extends OneToOne
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($range)) {
|
if (!empty($range)) {
|
||||||
$this->where[$localKey] = ['in', $range];
|
|
||||||
$data = $this->eagerlyWhere($this, [
|
$data = $this->eagerlyWhere($this, [
|
||||||
$localKey => [
|
$localKey => [
|
||||||
'in',
|
'in',
|
||||||
$range,
|
$range,
|
||||||
],
|
],
|
||||||
], $localKey, $relation, $subRelation, $closure);
|
], $localKey, $relation, $subRelation, $closure);
|
||||||
|
// 关联属性名
|
||||||
|
$attr = Loader::parseName($relation);
|
||||||
// 关联数据封装
|
// 关联数据封装
|
||||||
foreach ($resultSet as $result) {
|
foreach ($resultSet as $result) {
|
||||||
if (!isset($data[$result->$foreignKey])) {
|
// 关联模型
|
||||||
$data[$result->$foreignKey] = [];
|
if (!isset($data[$result->$localKey])) {
|
||||||
|
$relationModel = null;
|
||||||
|
} else {
|
||||||
|
$relationModel = $data[$result->$localKey];
|
||||||
}
|
}
|
||||||
$relationModel = $this->resultSetBuild($data[$result->$foreignKey], $class);
|
|
||||||
if (!empty($this->bindAttr)) {
|
if ($relationModel && !empty($this->bindAttr)) {
|
||||||
// 绑定关联属性
|
// 绑定关联属性
|
||||||
$this->bindAttr($relationModel, $result, $this->bindAttr);
|
$this->bindAttr($relationModel, $result, $this->bindAttr);
|
||||||
}
|
}
|
||||||
// 设置关联属性
|
// 设置关联属性
|
||||||
$result->setAttr($relation, $relationModel);
|
$result->setAttr($attr, $relationModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,25 +108,25 @@ class BelongsTo extends OneToOne
|
|||||||
* @param string $relation 当前关联名
|
* @param string $relation 当前关联名
|
||||||
* @param string $subRelation 子关联名
|
* @param string $subRelation 子关联名
|
||||||
* @param \Closure $closure 闭包
|
* @param \Closure $closure 闭包
|
||||||
* @param string $class 数据集对象名 为空表示数组
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function eagerlyOne(&$result, $relation, $subRelation, $closure, $class)
|
protected function eagerlyOne(&$result, $relation, $subRelation, $closure)
|
||||||
{
|
{
|
||||||
$localKey = $this->localKey;
|
$localKey = $this->localKey;
|
||||||
$foreignKey = $this->foreignKey;
|
$foreignKey = $this->foreignKey;
|
||||||
$data = $this->eagerlyWhere($this, [$localKey => $result->$foreignKey], $localKey, $relation, $subRelation, $closure);
|
$data = $this->eagerlyWhere($this, [$localKey => $result->$foreignKey], $localKey, $relation, $subRelation, $closure);
|
||||||
// 关联数据封装
|
// 关联模型
|
||||||
if (!isset($data[$result->$foreignKey])) {
|
if (!isset($data[$result->$localKey])) {
|
||||||
$data[$result->$foreignKey] = [];
|
$relationModel = null;
|
||||||
|
} else {
|
||||||
|
$relationModel = $data[$result->$localKey];
|
||||||
}
|
}
|
||||||
$relationModel = $this->resultSetBuild($data[$result->$foreignKey], $class);
|
if ($relationModel && !empty($this->bindAttr)) {
|
||||||
if (!empty($this->bindAttr)) {
|
|
||||||
// 绑定关联属性
|
// 绑定关联属性
|
||||||
$this->bindAttr($relationModel, $result, $this->bindAttr);
|
$this->bindAttr($relationModel, $result, $this->bindAttr);
|
||||||
}
|
}
|
||||||
// 设置关联属性
|
// 设置关联属性
|
||||||
$result->setAttr($relation, $relationModel);
|
$result->setAttr(Loader::parseName($relation), $relationModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,9 @@
|
|||||||
|
|
||||||
namespace think\model\relation;
|
namespace think\model\relation;
|
||||||
|
|
||||||
use think\Db;
|
|
||||||
use think\db\Query;
|
use think\db\Query;
|
||||||
use think\Exception;
|
use think\Exception;
|
||||||
|
use think\Loader;
|
||||||
use think\Model;
|
use think\Model;
|
||||||
use think\model\Pivot;
|
use think\model\Pivot;
|
||||||
use think\model\Relation;
|
use think\model\Relation;
|
||||||
@@ -31,32 +31,35 @@ class BelongsToMany extends Relation
|
|||||||
* @param string $table 中间表名
|
* @param string $table 中间表名
|
||||||
* @param string $foreignKey 关联模型外键
|
* @param string $foreignKey 关联模型外键
|
||||||
* @param string $localKey 当前模型关联键
|
* @param string $localKey 当前模型关联键
|
||||||
* @param array $alias 别名定义
|
|
||||||
*/
|
*/
|
||||||
public function __construct(Model $parent, $model, $table, $foreignKey, $localKey, $alias = [])
|
public function __construct(Model $parent, $model, $table, $foreignKey, $localKey)
|
||||||
{
|
{
|
||||||
$this->parent = $parent;
|
$this->parent = $parent;
|
||||||
$this->model = $model;
|
$this->model = $model;
|
||||||
$this->foreignKey = $foreignKey;
|
$this->foreignKey = $foreignKey;
|
||||||
$this->localKey = $localKey;
|
$this->localKey = $localKey;
|
||||||
$this->middle = $table;
|
$this->middle = $table;
|
||||||
$this->alias = $alias;
|
|
||||||
$this->query = (new $model)->db();
|
$this->query = (new $model)->db();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 延迟获取关联数据
|
* 延迟获取关联数据
|
||||||
* @access public
|
* @param string $subRelation 子关联名
|
||||||
|
* @param \Closure $closure 闭包查询条件
|
||||||
|
* @return false|\PDOStatement|string|\think\Collection
|
||||||
*/
|
*/
|
||||||
public function getRelation()
|
public function getRelation($subRelation = '', $closure = null)
|
||||||
{
|
{
|
||||||
$foreignKey = $this->foreignKey;
|
$foreignKey = $this->foreignKey;
|
||||||
$localKey = $this->localKey;
|
$localKey = $this->localKey;
|
||||||
$middle = $this->middle;
|
$middle = $this->middle;
|
||||||
|
if ($closure) {
|
||||||
|
call_user_func_array($closure, [& $this->query]);
|
||||||
|
}
|
||||||
// 关联查询
|
// 关联查询
|
||||||
$pk = $this->parent->getPk();
|
$pk = $this->parent->getPk();
|
||||||
$condition['pivot.' . $localKey] = $this->parent->$pk;
|
$condition['pivot.' . $localKey] = $this->parent->$pk;
|
||||||
$result = $this->belongsToManyQuery($middle, $foreignKey, $localKey, $condition)->select();
|
$result = $this->belongsToManyQuery($middle, $foreignKey, $localKey, $condition)->relation($subRelation)->select();
|
||||||
foreach ($result as $set) {
|
foreach ($result as $set) {
|
||||||
$pivot = [];
|
$pivot = [];
|
||||||
foreach ($set->getData() as $key => $val) {
|
foreach ($set->getData() as $key => $val) {
|
||||||
@@ -80,10 +83,9 @@ class BelongsToMany extends Relation
|
|||||||
* @param string $relation 当前关联名
|
* @param string $relation 当前关联名
|
||||||
* @param string $subRelation 子关联名
|
* @param string $subRelation 子关联名
|
||||||
* @param \Closure $closure 闭包
|
* @param \Closure $closure 闭包
|
||||||
* @param string $class 数据集对象名 为空表示数组
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function eagerlyResultSet(&$resultSet, $relation, $subRelation, $closure, $class)
|
public function eagerlyResultSet(&$resultSet, $relation, $subRelation, $closure)
|
||||||
{
|
{
|
||||||
$localKey = $this->localKey;
|
$localKey = $this->localKey;
|
||||||
$foreignKey = $this->foreignKey;
|
$foreignKey = $this->foreignKey;
|
||||||
@@ -105,14 +107,15 @@ class BelongsToMany extends Relation
|
|||||||
$range,
|
$range,
|
||||||
],
|
],
|
||||||
], $relation, $subRelation);
|
], $relation, $subRelation);
|
||||||
|
// 关联属性名
|
||||||
|
$attr = Loader::parseName($relation);
|
||||||
// 关联数据封装
|
// 关联数据封装
|
||||||
foreach ($resultSet as $result) {
|
foreach ($resultSet as $result) {
|
||||||
if (!isset($data[$result->$pk])) {
|
if (!isset($data[$result->$pk])) {
|
||||||
$data[$result->$pk] = [];
|
$data[$result->$pk] = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$result->setAttr($relation, $this->resultSetBuild($data[$result->$pk], $class));
|
$result->setAttr($attr, $this->resultSetBuild($data[$result->$pk]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,10 +127,9 @@ class BelongsToMany extends Relation
|
|||||||
* @param string $relation 当前关联名
|
* @param string $relation 当前关联名
|
||||||
* @param string $subRelation 子关联名
|
* @param string $subRelation 子关联名
|
||||||
* @param \Closure $closure 闭包
|
* @param \Closure $closure 闭包
|
||||||
* @param string $class 数据集对象名 为空表示数组
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function eagerlyResult(&$result, $relation, $subRelation, $closure, $class)
|
public function eagerlyResult(&$result, $relation, $subRelation, $closure)
|
||||||
{
|
{
|
||||||
$pk = $result->getPk();
|
$pk = $result->getPk();
|
||||||
if (isset($result->$pk)) {
|
if (isset($result->$pk)) {
|
||||||
@@ -139,7 +141,7 @@ class BelongsToMany extends Relation
|
|||||||
if (!isset($data[$pk])) {
|
if (!isset($data[$pk])) {
|
||||||
$data[$pk] = [];
|
$data[$pk] = [];
|
||||||
}
|
}
|
||||||
$result->setAttr($relation, $this->resultSetBuild($data[$pk], $class));
|
$result->setAttr(Loader::parseName($relation), $this->resultSetBuild($data[$pk]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +171,12 @@ class BelongsToMany extends Relation
|
|||||||
*/
|
*/
|
||||||
public function getRelationCountQuery($closure)
|
public function getRelationCountQuery($closure)
|
||||||
{
|
{
|
||||||
return $this->belongsToManyQuery($this->middle, $this->foreignKey, $this->localKey, ['pivot.' . $this->localKey => ['exp', '=' . $this->parent->getTable() . '.' . $this->parent->getPk()]])->fetchSql()->count();
|
return $this->belongsToManyQuery($this->middle, $this->foreignKey, $this->localKey, [
|
||||||
|
'pivot.' . $this->localKey => [
|
||||||
|
'exp',
|
||||||
|
'=' . $this->parent->getTable() . '.' . $this->parent->getPk()
|
||||||
|
]
|
||||||
|
])->fetchSql()->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -264,7 +271,8 @@ class BelongsToMany extends Relation
|
|||||||
* @access public
|
* @access public
|
||||||
* @param mixed $data 数据 可以使用数组、关联模型对象 或者 关联对象的主键
|
* @param mixed $data 数据 可以使用数组、关联模型对象 或者 关联对象的主键
|
||||||
* @param array $pivot 中间表额外数据
|
* @param array $pivot 中间表额外数据
|
||||||
* @return integer
|
* @return int
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function attach($data, $pivot = [])
|
public function attach($data, $pivot = [])
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace think\model\relation;
|
|||||||
|
|
||||||
use think\Db;
|
use think\Db;
|
||||||
use think\db\Query;
|
use think\db\Query;
|
||||||
|
use think\Loader;
|
||||||
use think\Model;
|
use think\Model;
|
||||||
use think\model\Relation;
|
use think\model\Relation;
|
||||||
|
|
||||||
@@ -25,25 +26,28 @@ class HasMany extends Relation
|
|||||||
* @param string $model 模型名
|
* @param string $model 模型名
|
||||||
* @param string $foreignKey 关联外键
|
* @param string $foreignKey 关联外键
|
||||||
* @param string $localKey 关联主键
|
* @param string $localKey 关联主键
|
||||||
* @param array $alias 别名定义
|
|
||||||
*/
|
*/
|
||||||
public function __construct(Model $parent, $model, $foreignKey, $localKey, $alias = [])
|
public function __construct(Model $parent, $model, $foreignKey, $localKey)
|
||||||
{
|
{
|
||||||
$this->parent = $parent;
|
$this->parent = $parent;
|
||||||
$this->model = $model;
|
$this->model = $model;
|
||||||
$this->foreignKey = $foreignKey;
|
$this->foreignKey = $foreignKey;
|
||||||
$this->localKey = $localKey;
|
$this->localKey = $localKey;
|
||||||
$this->alias = $alias;
|
|
||||||
$this->query = (new $model)->db();
|
$this->query = (new $model)->db();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 延迟获取关联数据
|
* 延迟获取关联数据
|
||||||
* @access public
|
* @param string $subRelation 子关联名
|
||||||
|
* @param \Closure $closure 闭包查询条件
|
||||||
|
* @return false|\PDOStatement|string|\think\Collection
|
||||||
*/
|
*/
|
||||||
public function getRelation()
|
public function getRelation($subRelation = '', $closure = null)
|
||||||
{
|
{
|
||||||
return $this->select();
|
if ($closure) {
|
||||||
|
call_user_func_array($closure, [& $this->query]);
|
||||||
|
}
|
||||||
|
return $this->relation($subRelation)->select();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,10 +57,9 @@ class HasMany extends Relation
|
|||||||
* @param string $relation 当前关联名
|
* @param string $relation 当前关联名
|
||||||
* @param string $subRelation 子关联名
|
* @param string $subRelation 子关联名
|
||||||
* @param \Closure $closure 闭包
|
* @param \Closure $closure 闭包
|
||||||
* @param string $class 数据集对象名 为空表示数组
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function eagerlyResultSet(&$resultSet, $relation, $subRelation, $closure, $class)
|
public function eagerlyResultSet(&$resultSet, $relation, $subRelation, $closure)
|
||||||
{
|
{
|
||||||
$localKey = $this->localKey;
|
$localKey = $this->localKey;
|
||||||
$range = [];
|
$range = [];
|
||||||
@@ -68,20 +71,20 @@ class HasMany extends Relation
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($range)) {
|
if (!empty($range)) {
|
||||||
$this->where[$this->foreignKey] = ['in', $range];
|
|
||||||
$data = $this->eagerlyOneToMany($this, [
|
$data = $this->eagerlyOneToMany($this, [
|
||||||
$this->foreignKey => [
|
$this->foreignKey => [
|
||||||
'in',
|
'in',
|
||||||
$range,
|
$range,
|
||||||
],
|
],
|
||||||
], $relation, $subRelation, $closure);
|
], $relation, $subRelation, $closure);
|
||||||
|
// 关联属性名
|
||||||
|
$attr = Loader::parseName($relation);
|
||||||
// 关联数据封装
|
// 关联数据封装
|
||||||
foreach ($resultSet as $result) {
|
foreach ($resultSet as $result) {
|
||||||
if (!isset($data[$result->$localKey])) {
|
if (!isset($data[$result->$localKey])) {
|
||||||
$data[$result->$localKey] = [];
|
$data[$result->$localKey] = [];
|
||||||
}
|
}
|
||||||
$result->setAttr($relation, $this->resultSetBuild($data[$result->$localKey], $class));
|
$result->setAttr($attr, $this->resultSetBuild($data[$result->$localKey]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,10 +96,9 @@ class HasMany extends Relation
|
|||||||
* @param string $relation 当前关联名
|
* @param string $relation 当前关联名
|
||||||
* @param string $subRelation 子关联名
|
* @param string $subRelation 子关联名
|
||||||
* @param \Closure $closure 闭包
|
* @param \Closure $closure 闭包
|
||||||
* @param string $class 数据集对象名 为空表示数组
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function eagerlyResult(&$result, $relation, $subRelation, $closure, $class)
|
public function eagerlyResult(&$result, $relation, $subRelation, $closure)
|
||||||
{
|
{
|
||||||
$localKey = $this->localKey;
|
$localKey = $this->localKey;
|
||||||
|
|
||||||
@@ -106,7 +108,7 @@ class HasMany extends Relation
|
|||||||
if (!isset($data[$result->$localKey])) {
|
if (!isset($data[$result->$localKey])) {
|
||||||
$data[$result->$localKey] = [];
|
$data[$result->$localKey] = [];
|
||||||
}
|
}
|
||||||
$result->setAttr($relation, $this->resultSetBuild($data[$result->$localKey], $class));
|
$result->setAttr(Loader::parseName($relation), $this->resultSetBuild($data[$result->$localKey]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +144,12 @@ class HasMany extends Relation
|
|||||||
call_user_func_array($closure, [& $this->query]);
|
call_user_func_array($closure, [& $this->query]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->query->where([$this->foreignKey => ['exp', '=' . $this->parent->getTable() . '.' . $this->parent->getPk()]])->fetchSql()->count();
|
return $this->query->where([
|
||||||
|
$this->foreignKey => [
|
||||||
|
'exp',
|
||||||
|
'=' . $this->parent->getTable() . '.' . $this->parent->getPk()
|
||||||
|
]
|
||||||
|
])->fetchSql()->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -207,16 +214,15 @@ class HasMany extends Relation
|
|||||||
/**
|
/**
|
||||||
* 根据关联条件查询当前模型
|
* 根据关联条件查询当前模型
|
||||||
* @access public
|
* @access public
|
||||||
* @param Model $model 模型对象
|
|
||||||
* @param string $operator 比较操作符
|
* @param string $operator 比较操作符
|
||||||
* @param integer $count 个数
|
* @param integer $count 个数
|
||||||
* @param string $id 关联表的统计字段
|
* @param string $id 关联表的统计字段
|
||||||
* @return Query
|
* @return Query
|
||||||
*/
|
*/
|
||||||
public function has($model, $operator = '>=', $count = 1, $id = '*')
|
public function has($operator = '>=', $count = 1, $id = '*')
|
||||||
{
|
{
|
||||||
$table = $this->query->getTable();
|
$table = $this->query->getTable();
|
||||||
return $model->db()->alias('a')
|
return $this->parent->db()->alias('a')
|
||||||
->join($table . ' b', 'a.' . $this->localKey . '=b.' . $this->foreignKey, $this->joinType)
|
->join($table . ' b', 'a.' . $this->localKey . '=b.' . $this->foreignKey, $this->joinType)
|
||||||
->group('b.' . $this->foreignKey)
|
->group('b.' . $this->foreignKey)
|
||||||
->having('count(' . $id . ')' . $operator . $count);
|
->having('count(' . $id . ')' . $operator . $count);
|
||||||
@@ -225,24 +231,25 @@ class HasMany extends Relation
|
|||||||
/**
|
/**
|
||||||
* 根据关联条件查询当前模型
|
* 根据关联条件查询当前模型
|
||||||
* @access public
|
* @access public
|
||||||
* @param Model $model 模型对象
|
|
||||||
* @param mixed $where 查询条件(数组或者闭包)
|
* @param mixed $where 查询条件(数组或者闭包)
|
||||||
* @return Query
|
* @return Query
|
||||||
*/
|
*/
|
||||||
public function hasWhere($model, $where = [])
|
public function hasWhere($where = [])
|
||||||
{
|
{
|
||||||
$table = $this->query->getTable();
|
$table = $this->query->getTable();
|
||||||
|
$model = basename(str_replace('\\', '/', get_class($this->parent)));
|
||||||
|
$relation = basename(str_replace('\\', '/', $this->model));
|
||||||
if (is_array($where)) {
|
if (is_array($where)) {
|
||||||
foreach ($where as $key => $val) {
|
foreach ($where as $key => $val) {
|
||||||
if (false === strpos($key, '.')) {
|
if (false === strpos($key, '.')) {
|
||||||
$where['b.' . $key] = $val;
|
$where[$relation . '.' . $key] = $val;
|
||||||
unset($where[$key]);
|
unset($where[$key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $model->db()->alias('a')
|
return $this->parent->db()->alias($model)
|
||||||
->field('a.*')
|
->field($model . '.*')
|
||||||
->join($table . ' b', 'a.' . $this->localKey . '=b.' . $this->foreignKey, $this->joinType)
|
->join($table . ' ' . $relation, $model . '.' . $this->localKey . '=' . $relation . '.' . $this->foreignKey)
|
||||||
->where($where);
|
->where($where);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,9 +261,7 @@ class HasMany extends Relation
|
|||||||
protected function baseQuery()
|
protected function baseQuery()
|
||||||
{
|
{
|
||||||
if (empty($this->baseQuery)) {
|
if (empty($this->baseQuery)) {
|
||||||
if (isset($this->where)) {
|
if (isset($this->parent->{$this->localKey})) {
|
||||||
$this->query->where($this->where);
|
|
||||||
} elseif (isset($this->parent->{$this->localKey})) {
|
|
||||||
// 关联查询带入关联条件
|
// 关联查询带入关联条件
|
||||||
$this->query->where($this->foreignKey, $this->parent->{$this->localKey});
|
$this->query->where($this->foreignKey, $this->parent->{$this->localKey});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,12 +30,11 @@ class HasManyThrough extends Relation
|
|||||||
* @param Model $parent 上级模型对象
|
* @param Model $parent 上级模型对象
|
||||||
* @param string $model 模型名
|
* @param string $model 模型名
|
||||||
* @param string $through 中间模型名
|
* @param string $through 中间模型名
|
||||||
* @param string $firstkey 关联外键
|
* @param string $foreignKey 关联外键
|
||||||
* @param string $secondKey 关联外键
|
* @param string $throughKey 关联外键
|
||||||
* @param string $localKey 关联主键
|
* @param string $localKey 关联主键
|
||||||
* @param array $alias 别名定义
|
|
||||||
*/
|
*/
|
||||||
public function __construct(Model $parent, $model, $through, $foreignKey, $throughKey, $localKey, $alias = [])
|
public function __construct(Model $parent, $model, $through, $foreignKey, $throughKey, $localKey)
|
||||||
{
|
{
|
||||||
$this->parent = $parent;
|
$this->parent = $parent;
|
||||||
$this->model = $model;
|
$this->model = $model;
|
||||||
@@ -43,17 +42,21 @@ class HasManyThrough extends Relation
|
|||||||
$this->foreignKey = $foreignKey;
|
$this->foreignKey = $foreignKey;
|
||||||
$this->throughKey = $throughKey;
|
$this->throughKey = $throughKey;
|
||||||
$this->localKey = $localKey;
|
$this->localKey = $localKey;
|
||||||
$this->alias = $alias;
|
|
||||||
$this->query = (new $model)->db();
|
$this->query = (new $model)->db();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 延迟获取关联数据
|
* 延迟获取关联数据
|
||||||
* @access public
|
* @param string $subRelation 子关联名
|
||||||
|
* @param \Closure $closure 闭包查询条件
|
||||||
|
* @return false|\PDOStatement|string|\think\Collection
|
||||||
*/
|
*/
|
||||||
public function getRelation()
|
public function getRelation($subRelation = '', $closure = null)
|
||||||
{
|
{
|
||||||
return $this->select();
|
if ($closure) {
|
||||||
|
call_user_func_array($closure, [& $this->query]);
|
||||||
|
}
|
||||||
|
return $this->relation($subRelation)->select();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,7 +70,8 @@ class HasManyThrough extends Relation
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function eagerlyResultSet(&$resultSet, $relation, $subRelation, $closure, $class)
|
public function eagerlyResultSet(&$resultSet, $relation, $subRelation, $closure, $class)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 预载入关联查询 返回模型对象
|
* 预载入关联查询 返回模型对象
|
||||||
@@ -80,7 +84,8 @@ class HasManyThrough extends Relation
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function eagerlyResult(&$result, $relation, $subRelation, $closure, $class)
|
public function eagerlyResult(&$result, $relation, $subRelation, $closure, $class)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关联统计
|
* 关联统计
|
||||||
@@ -90,7 +95,8 @@ class HasManyThrough extends Relation
|
|||||||
* @return integer
|
* @return integer
|
||||||
*/
|
*/
|
||||||
public function relationCount($result, $closure)
|
public function relationCount($result, $closure)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行基础查询(进执行一次)
|
* 执行基础查询(进执行一次)
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
namespace think\model\relation;
|
namespace think\model\relation;
|
||||||
|
|
||||||
|
use think\db\Query;
|
||||||
|
use think\Loader;
|
||||||
use think\Model;
|
use think\Model;
|
||||||
|
|
||||||
class HasOne extends OneToOne
|
class HasOne extends OneToOne
|
||||||
@@ -22,54 +24,57 @@ class HasOne extends OneToOne
|
|||||||
* @param string $model 模型名
|
* @param string $model 模型名
|
||||||
* @param string $foreignKey 关联外键
|
* @param string $foreignKey 关联外键
|
||||||
* @param string $localKey 关联主键
|
* @param string $localKey 关联主键
|
||||||
* @param array $alias 别名定义
|
|
||||||
* @param string $joinType JOIN类型
|
* @param string $joinType JOIN类型
|
||||||
*/
|
*/
|
||||||
public function __construct(Model $parent, $model, $foreignKey, $localKey, $alias = [], $joinType = 'INNER')
|
public function __construct(Model $parent, $model, $foreignKey, $localKey, $joinType = 'INNER')
|
||||||
{
|
{
|
||||||
$this->parent = $parent;
|
$this->parent = $parent;
|
||||||
$this->model = $model;
|
$this->model = $model;
|
||||||
$this->foreignKey = $foreignKey;
|
$this->foreignKey = $foreignKey;
|
||||||
$this->localKey = $localKey;
|
$this->localKey = $localKey;
|
||||||
$this->alias = $alias;
|
|
||||||
$this->joinType = $joinType;
|
$this->joinType = $joinType;
|
||||||
$this->query = (new $model)->db();
|
$this->query = (new $model)->db();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 延迟获取关联数据
|
* 延迟获取关联数据
|
||||||
* @access public
|
* @param string $subRelation 子关联名
|
||||||
|
* @param \Closure $closure 闭包查询条件
|
||||||
|
* @return array|false|\PDOStatement|string|Model
|
||||||
*/
|
*/
|
||||||
public function getRelation()
|
public function getRelation($subRelation = '', $closure = null)
|
||||||
{
|
{
|
||||||
// 执行关联定义方法
|
// 执行关联定义方法
|
||||||
$localKey = $this->localKey;
|
$localKey = $this->localKey;
|
||||||
|
if ($closure) {
|
||||||
|
call_user_func_array($closure, [& $this->query]);
|
||||||
|
}
|
||||||
// 判断关联类型执行查询
|
// 判断关联类型执行查询
|
||||||
return $this->query->where($this->foreignKey, $this->parent->$localKey)->find();
|
return $this->query->where($this->foreignKey, $this->parent->$localKey)->relation($subRelation)->find();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据关联条件查询当前模型
|
* 根据关联条件查询当前模型
|
||||||
* @access public
|
* @access public
|
||||||
* @param Model $model 模型对象
|
|
||||||
* @param mixed $where 查询条件(数组或者闭包)
|
* @param mixed $where 查询条件(数组或者闭包)
|
||||||
* @return Query
|
* @return Query
|
||||||
*/
|
*/
|
||||||
public function hasWhere($model, $where = [])
|
public function hasWhere($where = [])
|
||||||
{
|
{
|
||||||
$table = $this->query->getTable();
|
$table = $this->query->getTable();
|
||||||
|
$model = basename(str_replace('\\', '/', get_class($this->parent)));
|
||||||
|
$relation = basename(str_replace('\\', '/', $this->model));
|
||||||
if (is_array($where)) {
|
if (is_array($where)) {
|
||||||
foreach ($where as $key => $val) {
|
foreach ($where as $key => $val) {
|
||||||
if (false === strpos($key, '.')) {
|
if (false === strpos($key, '.')) {
|
||||||
$where['b.' . $key] = $val;
|
$where[$relation . '.' . $key] = $val;
|
||||||
unset($where[$key]);
|
unset($where[$key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $model->db()->alias('a')
|
return $this->parent->db()->alias($model)
|
||||||
->field('a.*')
|
->field($model . '.*')
|
||||||
->join($table . ' b', 'a.' . $this->localKey . '=b.' . $this->foreignKey, $this->joinType)
|
->join($table . ' ' . $relation, $model . '.' . $this->localKey . '=' . $relation . '.' . $this->foreignKey, $this->joinType)
|
||||||
->where($where);
|
->where($where);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,10 +85,9 @@ class HasOne extends OneToOne
|
|||||||
* @param string $relation 当前关联名
|
* @param string $relation 当前关联名
|
||||||
* @param string $subRelation 子关联名
|
* @param string $subRelation 子关联名
|
||||||
* @param \Closure $closure 闭包
|
* @param \Closure $closure 闭包
|
||||||
* @param string $class 数据集对象名 为空表示数组
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function eagerlySet(&$resultSet, $relation, $subRelation, $closure, $class)
|
protected function eagerlySet(&$resultSet, $relation, $subRelation, $closure)
|
||||||
{
|
{
|
||||||
$localKey = $this->localKey;
|
$localKey = $this->localKey;
|
||||||
$foreignKey = $this->foreignKey;
|
$foreignKey = $this->foreignKey;
|
||||||
@@ -97,26 +101,28 @@ class HasOne extends OneToOne
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($range)) {
|
if (!empty($range)) {
|
||||||
$this->where[$foreignKey] = ['in', $range];
|
|
||||||
$data = $this->eagerlyWhere($this, [
|
$data = $this->eagerlyWhere($this, [
|
||||||
$foreignKey => [
|
$foreignKey => [
|
||||||
'in',
|
'in',
|
||||||
$range,
|
$range,
|
||||||
],
|
],
|
||||||
], $foreignKey, $relation, $subRelation, $closure);
|
], $foreignKey, $relation, $subRelation, $closure);
|
||||||
|
// 关联属性名
|
||||||
|
$attr = Loader::parseName($relation);
|
||||||
// 关联数据封装
|
// 关联数据封装
|
||||||
foreach ($resultSet as $result) {
|
foreach ($resultSet as $result) {
|
||||||
|
// 关联模型
|
||||||
if (!isset($data[$result->$localKey])) {
|
if (!isset($data[$result->$localKey])) {
|
||||||
$data[$result->$localKey] = [];
|
$relationModel = null;
|
||||||
|
} else {
|
||||||
|
$relationModel = $data[$result->$localKey];
|
||||||
}
|
}
|
||||||
$relationModel = $this->resultSetBuild($data[$result->$localKey], $class);
|
if ($relationModel && !empty($this->bindAttr)) {
|
||||||
if (!empty($this->bindAttr)) {
|
|
||||||
// 绑定关联属性
|
// 绑定关联属性
|
||||||
$this->bindAttr($relationModel, $result, $this->bindAttr);
|
$this->bindAttr($relationModel, $result, $this->bindAttr);
|
||||||
}
|
}
|
||||||
// 设置关联属性
|
// 设置关联属性
|
||||||
$result->setAttr($relation, $relationModel);
|
$result->setAttr($attr, $relationModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,24 +134,26 @@ class HasOne extends OneToOne
|
|||||||
* @param string $relation 当前关联名
|
* @param string $relation 当前关联名
|
||||||
* @param string $subRelation 子关联名
|
* @param string $subRelation 子关联名
|
||||||
* @param \Closure $closure 闭包
|
* @param \Closure $closure 闭包
|
||||||
* @param string $class 数据集对象名 为空表示数组
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function eagerlyOne(&$result, $relation, $subRelation, $closure, $class)
|
protected function eagerlyOne(&$result, $relation, $subRelation, $closure)
|
||||||
{
|
{
|
||||||
$localKey = $this->localKey;
|
$localKey = $this->localKey;
|
||||||
$foreignKey = $this->foreignKey;
|
$foreignKey = $this->foreignKey;
|
||||||
$data = $this->eagerlyWhere($this, [$foreignKey => $result->$localKey], $foreignKey, $relation, $subRelation, $closure);
|
$data = $this->eagerlyWhere($this, [$foreignKey => $result->$localKey], $foreignKey, $relation, $subRelation, $closure);
|
||||||
// 关联数据封装
|
|
||||||
|
// 关联模型
|
||||||
if (!isset($data[$result->$localKey])) {
|
if (!isset($data[$result->$localKey])) {
|
||||||
$data[$result->$localKey] = [];
|
$relationModel = null;
|
||||||
|
} else {
|
||||||
|
$relationModel = $data[$result->$localKey];
|
||||||
}
|
}
|
||||||
$relationModel = $this->resultSetBuild($data[$result->$localKey], $class);
|
|
||||||
if (!empty($this->bindAttr)) {
|
if ($relationModel && !empty($this->bindAttr)) {
|
||||||
// 绑定关联属性
|
// 绑定关联属性
|
||||||
$this->bindAttr($relationModel, $result, $this->bindAttr);
|
$this->bindAttr($relationModel, $result, $this->bindAttr);
|
||||||
}
|
}
|
||||||
$result->setAttr($relation, $relationModel);
|
$result->setAttr(Loader::parseName($relation), $relationModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace think\model\relation;
|
|||||||
|
|
||||||
use think\Db;
|
use think\Db;
|
||||||
use think\db\Query;
|
use think\db\Query;
|
||||||
|
use think\Loader;
|
||||||
use think\Model;
|
use think\Model;
|
||||||
use think\model\Relation;
|
use think\model\Relation;
|
||||||
|
|
||||||
@@ -45,11 +46,16 @@ class MorphMany extends Relation
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 延迟获取关联数据
|
* 延迟获取关联数据
|
||||||
* @access public
|
* @param string $subRelation 子关联名
|
||||||
|
* @param \Closure $closure 闭包查询条件
|
||||||
|
* @return false|\PDOStatement|string|\think\Collection
|
||||||
*/
|
*/
|
||||||
public function getRelation()
|
public function getRelation($subRelation = '', $closure = null)
|
||||||
{
|
{
|
||||||
return $this->select();
|
if ($closure) {
|
||||||
|
call_user_func_array($closure, [& $this->query]);
|
||||||
|
}
|
||||||
|
return $this->relation($subRelation)->select();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,10 +65,9 @@ class MorphMany extends Relation
|
|||||||
* @param string $relation 当前关联名
|
* @param string $relation 当前关联名
|
||||||
* @param string $subRelation 子关联名
|
* @param string $subRelation 子关联名
|
||||||
* @param \Closure $closure 闭包
|
* @param \Closure $closure 闭包
|
||||||
* @param string $class 数据集对象名 为空表示数组
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function eagerlyResultSet(&$resultSet, $relation, $subRelation, $closure, $class)
|
public function eagerlyResultSet(&$resultSet, $relation, $subRelation, $closure)
|
||||||
{
|
{
|
||||||
$morphType = $this->morphType;
|
$morphType = $this->morphType;
|
||||||
$morphKey = $this->morphKey;
|
$morphKey = $this->morphKey;
|
||||||
@@ -77,19 +82,18 @@ class MorphMany extends Relation
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($range)) {
|
if (!empty($range)) {
|
||||||
$this->where[$morphKey] = ['in', $range];
|
|
||||||
$this->where[$morphType] = $type;
|
|
||||||
$data = $this->eagerlyMorphToMany([
|
$data = $this->eagerlyMorphToMany([
|
||||||
$morphKey => ['in', $range],
|
$morphKey => ['in', $range],
|
||||||
$morphType => $type,
|
$morphType => $type,
|
||||||
], $relation, $subRelation, $closure);
|
], $relation, $subRelation, $closure);
|
||||||
|
// 关联属性名
|
||||||
|
$attr = Loader::parseName($relation);
|
||||||
// 关联数据封装
|
// 关联数据封装
|
||||||
foreach ($resultSet as $result) {
|
foreach ($resultSet as $result) {
|
||||||
if (!isset($data[$result->$pk])) {
|
if (!isset($data[$result->$pk])) {
|
||||||
$data[$result->$pk] = [];
|
$data[$result->$pk] = [];
|
||||||
}
|
}
|
||||||
$result->setAttr($relation, $this->resultSetBuild($data[$result->$pk], $class));
|
$result->setAttr($attr, $this->resultSetBuild($data[$result->$pk]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,15 +105,17 @@ class MorphMany extends Relation
|
|||||||
* @param string $relation 当前关联名
|
* @param string $relation 当前关联名
|
||||||
* @param string $subRelation 子关联名
|
* @param string $subRelation 子关联名
|
||||||
* @param \Closure $closure 闭包
|
* @param \Closure $closure 闭包
|
||||||
* @param string $class 数据集对象名 为空表示数组
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function eagerlyResult(&$result, $relation, $subRelation, $closure, $class)
|
public function eagerlyResult(&$result, $relation, $subRelation, $closure)
|
||||||
{
|
{
|
||||||
$pk = $result->getPk();
|
$pk = $result->getPk();
|
||||||
if (isset($result->$pk)) {
|
if (isset($result->$pk)) {
|
||||||
$data = $this->eagerlyMorphToMany([$this->morphKey => $result->$pk, $this->morphType => $this->type], $relation, $subRelation, $closure);
|
$data = $this->eagerlyMorphToMany([
|
||||||
$result->setAttr($relation, $this->resultSetBuild($data[$result->$pk], $class));
|
$this->morphKey => $result->$pk,
|
||||||
|
$this->morphType => $this->type
|
||||||
|
], $relation, $subRelation, $closure);
|
||||||
|
$result->setAttr(Loader::parseName($relation), $this->resultSetBuild($data[$result->$pk]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,16 +151,22 @@ class MorphMany extends Relation
|
|||||||
call_user_func_array($closure, [& $this->query]);
|
call_user_func_array($closure, [& $this->query]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->query->where([$this->morphKey => ['exp', '=' . $this->parent->getTable() . '.' . $this->parent->getPk()], $this->morphType => $this->type])->fetchSql()->count();
|
return $this->query->where([
|
||||||
|
$this->morphKey => [
|
||||||
|
'exp',
|
||||||
|
'=' . $this->parent->getTable() . '.' . $this->parent->getPk()
|
||||||
|
],
|
||||||
|
$this->morphType => $this->type
|
||||||
|
])->fetchSql()->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 多态一对多 关联模型预查询
|
* 多态一对多 关联模型预查询
|
||||||
* @access public
|
* @access public
|
||||||
* @param object $model 关联模型对象
|
|
||||||
* @param array $where 关联预查询条件
|
* @param array $where 关联预查询条件
|
||||||
* @param string $relation 关联名
|
* @param string $relation 关联名
|
||||||
* @param string $subRelation 子关联
|
* @param string $subRelation 子关联
|
||||||
|
* @param bool|\Closure $closure 闭包
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function eagerlyMorphToMany($where, $relation, $subRelation = '', $closure = false)
|
protected function eagerlyMorphToMany($where, $relation, $subRelation = '', $closure = false)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace think\model\relation;
|
namespace think\model\relation;
|
||||||
|
|
||||||
|
use think\Exception;
|
||||||
use think\Loader;
|
use think\Loader;
|
||||||
use think\Model;
|
use think\Model;
|
||||||
use think\model\Relation;
|
use think\model\Relation;
|
||||||
@@ -20,6 +21,8 @@ class MorphTo extends Relation
|
|||||||
// 多态字段
|
// 多态字段
|
||||||
protected $morphKey;
|
protected $morphKey;
|
||||||
protected $morphType;
|
protected $morphType;
|
||||||
|
// 多态别名
|
||||||
|
protected $alias;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 架构函数
|
* 架构函数
|
||||||
@@ -39,9 +42,11 @@ class MorphTo extends Relation
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 延迟获取关联数据
|
* 延迟获取关联数据
|
||||||
* @access public
|
* @param string $subRelation 子关联名
|
||||||
|
* @param \Closure $closure 闭包查询条件
|
||||||
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getRelation()
|
public function getRelation($subRelation = '', $closure = null)
|
||||||
{
|
{
|
||||||
$morphKey = $this->morphKey;
|
$morphKey = $this->morphKey;
|
||||||
$morphType = $this->morphType;
|
$morphType = $this->morphType;
|
||||||
@@ -49,7 +54,7 @@ class MorphTo extends Relation
|
|||||||
$model = $this->parseModel($this->parent->$morphType);
|
$model = $this->parseModel($this->parent->$morphType);
|
||||||
// 主键数据
|
// 主键数据
|
||||||
$pk = $this->parent->$morphKey;
|
$pk = $this->parent->$morphKey;
|
||||||
return (new $model)->find($pk);
|
return (new $model)->relation($subRelation)->find($pk);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,6 +77,18 @@ class MorphTo extends Relation
|
|||||||
return $model;
|
return $model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置多态别名
|
||||||
|
* @access public
|
||||||
|
* @param array $alias 别名定义
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setAlias($alias)
|
||||||
|
{
|
||||||
|
$this->alias = $alias;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 预载入关联查询
|
* 预载入关联查询
|
||||||
* @access public
|
* @access public
|
||||||
@@ -79,10 +96,10 @@ class MorphTo extends Relation
|
|||||||
* @param string $relation 当前关联名
|
* @param string $relation 当前关联名
|
||||||
* @param string $subRelation 子关联名
|
* @param string $subRelation 子关联名
|
||||||
* @param \Closure $closure 闭包
|
* @param \Closure $closure 闭包
|
||||||
* @param string $class 数据集对象名 为空表示数组
|
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function eagerlyResultSet(&$resultSet, $relation, $subRelation, $closure, $class)
|
public function eagerlyResultSet(&$resultSet, $relation, $subRelation, $closure)
|
||||||
{
|
{
|
||||||
$morphKey = $this->morphKey;
|
$morphKey = $this->morphKey;
|
||||||
$morphType = $this->morphType;
|
$morphType = $this->morphType;
|
||||||
@@ -95,6 +112,8 @@ class MorphTo extends Relation
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($range)) {
|
if (!empty($range)) {
|
||||||
|
// 关联属性名
|
||||||
|
$attr = Loader::parseName($relation);
|
||||||
foreach ($range as $key => $val) {
|
foreach ($range as $key => $val) {
|
||||||
// 多态类型映射
|
// 多态类型映射
|
||||||
$model = $this->parseModel($key);
|
$model = $this->parseModel($key);
|
||||||
@@ -107,10 +126,12 @@ class MorphTo extends Relation
|
|||||||
}
|
}
|
||||||
foreach ($resultSet as $result) {
|
foreach ($resultSet as $result) {
|
||||||
if ($key == $result->$morphType) {
|
if ($key == $result->$morphType) {
|
||||||
|
// 关联模型
|
||||||
if (!isset($data[$result->$morphKey])) {
|
if (!isset($data[$result->$morphKey])) {
|
||||||
$data[$result->$morphKey] = [];
|
throw new Exception('relation data not exists :' . $this->model);
|
||||||
|
} else {
|
||||||
|
$result->setAttr($attr, $data[$result->$morphKey]);
|
||||||
}
|
}
|
||||||
$result->setAttr($relation, $this->resultSetBuild($data[$result->$morphKey], $class));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,10 +145,9 @@ class MorphTo extends Relation
|
|||||||
* @param string $relation 当前关联名
|
* @param string $relation 当前关联名
|
||||||
* @param string $subRelation 子关联名
|
* @param string $subRelation 子关联名
|
||||||
* @param \Closure $closure 闭包
|
* @param \Closure $closure 闭包
|
||||||
* @param string $class 数据集对象名 为空表示数组
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function eagerlyResult(&$result, $relation, $subRelation, $closure, $class)
|
public function eagerlyResult(&$result, $relation, $subRelation, $closure)
|
||||||
{
|
{
|
||||||
$morphKey = $this->morphKey;
|
$morphKey = $this->morphKey;
|
||||||
$morphType = $this->morphType;
|
$morphType = $this->morphType;
|
||||||
@@ -144,14 +164,15 @@ class MorphTo extends Relation
|
|||||||
* @return integer
|
* @return integer
|
||||||
*/
|
*/
|
||||||
public function relationCount($result, $closure)
|
public function relationCount($result, $closure)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 多态MorphTo 关联模型预查询
|
* 多态MorphTo 关联模型预查询
|
||||||
* @access public
|
* @access public
|
||||||
* @param object $model 关联模型对象
|
* @param object $model 关联模型对象
|
||||||
* @param array $where 关联预查询条件
|
|
||||||
* @param string $relation 关联名
|
* @param string $relation 关联名
|
||||||
|
* @param $result
|
||||||
* @param string $subRelation 子关联
|
* @param string $subRelation 子关联
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
@@ -163,7 +184,7 @@ class MorphTo extends Relation
|
|||||||
if ($data) {
|
if ($data) {
|
||||||
$data->isUpdate(true);
|
$data->isUpdate(true);
|
||||||
}
|
}
|
||||||
$result->setAttr($relation, $data ?: null);
|
$result->setAttr(Loader::parseName($relation), $data ?: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,13 +17,32 @@ use think\Loader;
|
|||||||
use think\Model;
|
use think\Model;
|
||||||
use think\model\Relation;
|
use think\model\Relation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class OneToOne
|
||||||
|
* @package think\model\relation
|
||||||
|
*
|
||||||
|
*/
|
||||||
abstract class OneToOne extends Relation
|
abstract class OneToOne extends Relation
|
||||||
{
|
{
|
||||||
// 预载入方式
|
// 预载入方式 0 -JOIN 1 -IN
|
||||||
protected $eagerlyType = 0;
|
protected $eagerlyType = 1;
|
||||||
|
// 当前关联的JOIN类型
|
||||||
|
protected $joinType;
|
||||||
// 要绑定的属性
|
// 要绑定的属性
|
||||||
protected $bindAttr = [];
|
protected $bindAttr = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置join类型
|
||||||
|
* @access public
|
||||||
|
* @param string $type JOIN类型
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function joinType($type)
|
||||||
|
{
|
||||||
|
$this->joinType = $type;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 预载入关联查询(JOIN方式)
|
* 预载入关联查询(JOIN方式)
|
||||||
* @access public
|
* @access public
|
||||||
@@ -37,7 +56,7 @@ abstract class OneToOne extends Relation
|
|||||||
public function eagerly(Query $query, $relation, $subRelation, $closure, $first)
|
public function eagerly(Query $query, $relation, $subRelation, $closure, $first)
|
||||||
{
|
{
|
||||||
$name = Loader::parseName(basename(str_replace('\\', '/', $query->getModel())));
|
$name = Loader::parseName(basename(str_replace('\\', '/', $query->getModel())));
|
||||||
$alias = isset($this->alias[$name]) ? $this->alias[$name] : $name;
|
$alias = $name;
|
||||||
if ($first) {
|
if ($first) {
|
||||||
$table = $query->getTable();
|
$table = $query->getTable();
|
||||||
$query->table([$table => $alias]);
|
$query->table([$table => $alias]);
|
||||||
@@ -52,8 +71,7 @@ abstract class OneToOne extends Relation
|
|||||||
|
|
||||||
// 预载入封装
|
// 预载入封装
|
||||||
$joinTable = $this->query->getTable();
|
$joinTable = $this->query->getTable();
|
||||||
$joinName = Loader::parseName(basename(str_replace('\\', '/', $this->model)));
|
$joinAlias = $relation;
|
||||||
$joinAlias = isset($this->alias[$joinName]) ? $this->alias[$joinName] : $relation;
|
|
||||||
$query->via($joinAlias);
|
$query->via($joinAlias);
|
||||||
|
|
||||||
if ($this instanceof BelongsTo) {
|
if ($this instanceof BelongsTo) {
|
||||||
@@ -65,8 +83,7 @@ abstract class OneToOne extends Relation
|
|||||||
if ($closure) {
|
if ($closure) {
|
||||||
// 执行闭包查询
|
// 执行闭包查询
|
||||||
call_user_func_array($closure, [& $query]);
|
call_user_func_array($closure, [& $query]);
|
||||||
//指定获取关联的字段
|
// 使用withField指定获取关联的字段,如
|
||||||
//需要在 回调中 调方法 withField 方法,如
|
|
||||||
// $query->where(['id'=>1])->withField('id,name');
|
// $query->where(['id'=>1])->withField('id,name');
|
||||||
if ($query->getOptions('with_field')) {
|
if ($query->getOptions('with_field')) {
|
||||||
$field = $query->getOptions('with_field');
|
$field = $query->getOptions('with_field');
|
||||||
@@ -80,6 +97,26 @@ abstract class OneToOne extends Relation
|
|||||||
$query->field($field, false, $joinTable, $joinAlias, $relation . '__');
|
$query->field($field, false, $joinTable, $joinAlias, $relation . '__');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预载入关联查询(数据集)
|
||||||
|
* @param array $resultSet
|
||||||
|
* @param string $relation
|
||||||
|
* @param string $subRelation
|
||||||
|
* @param \Closure $closure
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
abstract protected function eagerlySet(&$resultSet, $relation, $subRelation, $closure);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预载入关联查询(数据)
|
||||||
|
* @param Model $result
|
||||||
|
* @param string $relation
|
||||||
|
* @param string $subRelation
|
||||||
|
* @param \Closure $closure
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
abstract protected function eagerlyOne(&$result, $relation, $subRelation, $closure);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 预载入关联查询(数据集)
|
* 预载入关联查询(数据集)
|
||||||
* @access public
|
* @access public
|
||||||
@@ -87,14 +124,13 @@ abstract class OneToOne extends Relation
|
|||||||
* @param string $relation 当前关联名
|
* @param string $relation 当前关联名
|
||||||
* @param string $subRelation 子关联名
|
* @param string $subRelation 子关联名
|
||||||
* @param \Closure $closure 闭包
|
* @param \Closure $closure 闭包
|
||||||
* @param string $class 数据集对象名 为空表示数组
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function eagerlyResultSet(&$resultSet, $relation, $subRelation, $closure, $class)
|
public function eagerlyResultSet(&$resultSet, $relation, $subRelation, $closure)
|
||||||
{
|
{
|
||||||
if (1 == $this->eagerlyType) {
|
if (1 == $this->eagerlyType) {
|
||||||
// IN查询
|
// IN查询
|
||||||
$this->eagerlySet($resultSet, $relation, $subRelation, $closure, $class);
|
$this->eagerlySet($resultSet, $relation, $subRelation, $closure);
|
||||||
} else {
|
} else {
|
||||||
// 模型关联组装
|
// 模型关联组装
|
||||||
foreach ($resultSet as $result) {
|
foreach ($resultSet as $result) {
|
||||||
@@ -110,14 +146,13 @@ abstract class OneToOne extends Relation
|
|||||||
* @param string $relation 当前关联名
|
* @param string $relation 当前关联名
|
||||||
* @param string $subRelation 子关联名
|
* @param string $subRelation 子关联名
|
||||||
* @param \Closure $closure 闭包
|
* @param \Closure $closure 闭包
|
||||||
* @param string $class 数据集对象名 为空表示数组
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function eagerlyResult(&$result, $relation, $subRelation, $closure, $class)
|
public function eagerlyResult(&$result, $relation, $subRelation, $closure)
|
||||||
{
|
{
|
||||||
if (1 == $this->eagerlyType) {
|
if (1 == $this->eagerlyType) {
|
||||||
// IN查询
|
// IN查询
|
||||||
$this->eagerlyOne($result, $relation, $subRelation, $closure, $class);
|
$this->eagerlyOne($result, $relation, $subRelation, $closure);
|
||||||
} else {
|
} else {
|
||||||
// 模型关联组装
|
// 模型关联组装
|
||||||
$this->match($this->model, $relation, $result);
|
$this->match($this->model, $relation, $result);
|
||||||
@@ -145,7 +180,7 @@ abstract class OneToOne extends Relation
|
|||||||
* 设置预载入方式
|
* 设置预载入方式
|
||||||
* @access public
|
* @access public
|
||||||
* @param integer $type 预载入方式 0 JOIN查询 1 IN查询
|
* @param integer $type 预载入方式 0 JOIN查询 1 IN查询
|
||||||
* @return this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function setEagerlyType($type)
|
public function setEagerlyType($type)
|
||||||
{
|
{
|
||||||
@@ -168,7 +203,7 @@ abstract class OneToOne extends Relation
|
|||||||
* 绑定关联表的属性到父模型属性
|
* 绑定关联表的属性到父模型属性
|
||||||
* @access public
|
* @access public
|
||||||
* @param mixed $attr 要绑定的属性列表
|
* @param mixed $attr 要绑定的属性列表
|
||||||
* @return this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function bind($attr)
|
public function bind($attr)
|
||||||
{
|
{
|
||||||
@@ -187,7 +222,8 @@ abstract class OneToOne extends Relation
|
|||||||
* @return integer
|
* @return integer
|
||||||
*/
|
*/
|
||||||
public function relationCount($result, $closure)
|
public function relationCount($result, $closure)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 一对一 关联模型预查询拼装
|
* 一对一 关联模型预查询拼装
|
||||||
@@ -215,7 +251,7 @@ abstract class OneToOne extends Relation
|
|||||||
$this->bindAttr($relationModel, $result, $this->bindAttr);
|
$this->bindAttr($relationModel, $result, $this->bindAttr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$result->setAttr($relation, !isset($relationModel) ? null : $relationModel->isUpdate(true));
|
$result->setAttr(Loader::parseName($relation), !isset($relationModel) ? null : $relationModel->isUpdate(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -225,6 +261,7 @@ abstract class OneToOne extends Relation
|
|||||||
* @param Model $result 父模型对象
|
* @param Model $result 父模型对象
|
||||||
* @param array $bindAttr 绑定属性
|
* @param array $bindAttr 绑定属性
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function bindAttr($model, &$result, $bindAttr)
|
protected function bindAttr($model, &$result, $bindAttr)
|
||||||
{
|
{
|
||||||
@@ -246,7 +283,7 @@ abstract class OneToOne extends Relation
|
|||||||
* @param string $key 关联键名
|
* @param string $key 关联键名
|
||||||
* @param string $relation 关联名
|
* @param string $relation 关联名
|
||||||
* @param string $subRelation 子关联
|
* @param string $subRelation 子关联
|
||||||
* @param bool $closure
|
* @param bool|\Closure $closure
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function eagerlyWhere($model, $where, $key, $relation, $subRelation = '', $closure = false)
|
protected function eagerlyWhere($model, $where, $key, $relation, $subRelation = '', $closure = false)
|
||||||
@@ -254,13 +291,16 @@ abstract class OneToOne extends Relation
|
|||||||
// 预载入关联查询 支持嵌套预载入
|
// 预载入关联查询 支持嵌套预载入
|
||||||
if ($closure) {
|
if ($closure) {
|
||||||
call_user_func_array($closure, [& $model]);
|
call_user_func_array($closure, [& $model]);
|
||||||
|
if ($field = $model->getOptions('with_field')) {
|
||||||
|
$model->field($field)->removeOption('with_field');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$list = $model->where($where)->with($subRelation)->select();
|
$list = $model->where($where)->with($subRelation)->select();
|
||||||
|
|
||||||
// 组装模型数据
|
// 组装模型数据
|
||||||
$data = [];
|
$data = [];
|
||||||
foreach ($list as $set) {
|
foreach ($list as $set) {
|
||||||
$data[$set->$key][] = $set;
|
$data[$set->$key] = $set;
|
||||||
}
|
}
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ class Cx extends Taglib
|
|||||||
$name = $this->autoBuildVar($name);
|
$name = $this->autoBuildVar($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
$parseStr .= 'if(is_array(' . $name . ') || ' . $name . ' instanceof \think\Collection): $' . $key . ' = 0;';
|
$parseStr .= 'if(is_array(' . $name . ') || ' . $name . ' instanceof \think\Collection || ' . $name . ' instanceof \think\Paginator): $' . $key . ' = 0;';
|
||||||
// 设置了输出数组长度
|
// 设置了输出数组长度
|
||||||
if (0 != $offset || 'null' != $length) {
|
if (0 != $offset || 'null' != $length) {
|
||||||
$parseStr .= '$__LIST__ = is_array(' . $name . ') ? array_slice(' . $name . ',' . $offset . ',' . $length . ', true) : ' . $name . '->slice(' . $offset . ',' . $length . ', true); ';
|
$parseStr .= '$__LIST__ = is_array(' . $name . ') ? array_slice(' . $name . ',' . $offset . ',' . $length . ', true) : ' . $name . '->slice(' . $offset . ',' . $length . ', true); ';
|
||||||
@@ -158,7 +158,7 @@ class Cx extends Taglib
|
|||||||
} else {
|
} else {
|
||||||
$name = $this->autoBuildVar($name);
|
$name = $this->autoBuildVar($name);
|
||||||
}
|
}
|
||||||
$parseStr .= 'if(is_array(' . $name . ') || ' . $name . ' instanceof \think\Collection): ';
|
$parseStr .= 'if(is_array(' . $name . ') || ' . $name . ' instanceof \think\Collection || ' . $name . ' instanceof \think\Paginator): ';
|
||||||
// 设置了输出数组长度
|
// 设置了输出数组长度
|
||||||
if (0 != $offset || 'null' != $length) {
|
if (0 != $offset || 'null' != $length) {
|
||||||
if (!isset($var)) {
|
if (!isset($var)) {
|
||||||
@@ -431,7 +431,7 @@ class Cx extends Taglib
|
|||||||
{
|
{
|
||||||
$name = $tag['name'];
|
$name = $tag['name'];
|
||||||
$name = $this->autoBuildVar($name);
|
$name = $this->autoBuildVar($name);
|
||||||
$parseStr = '<?php if(empty(' . $name . ') || (' . $name . ' instanceof \think\Collection && ' . $name . '->isEmpty())): ?>' . $content . '<?php endif; ?>';
|
$parseStr = '<?php if(empty(' . $name . ') || ((' . $name . ' instanceof \think\Collection || ' . $name . ' instanceof \think\Paginator ) && ' . $name . '->isEmpty())): ?>' . $content . '<?php endif; ?>';
|
||||||
return $parseStr;
|
return $parseStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,7 +448,7 @@ class Cx extends Taglib
|
|||||||
{
|
{
|
||||||
$name = $tag['name'];
|
$name = $tag['name'];
|
||||||
$name = $this->autoBuildVar($name);
|
$name = $this->autoBuildVar($name);
|
||||||
$parseStr = '<?php if(!(empty(' . $name . ') || (' . $name . ' instanceof \think\Collection && ' . $name . '->isEmpty()))): ?>' . $content . '<?php endif; ?>';
|
$parseStr = '<?php if(!(empty(' . $name . ') || ((' . $name . ' instanceof \think\Collection || ' . $name . ' instanceof \think\Paginator ) && ' . $name . '->isEmpty()))): ?>' . $content . '<?php endif; ?>';
|
||||||
return $parseStr;
|
return $parseStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ trait SoftDelete
|
|||||||
$this->data[$name] = $this->autoWriteTimestamp($name);
|
$this->data[$name] = $this->autoWriteTimestamp($name);
|
||||||
$result = $this->isUpdate()->save();
|
$result = $this->isUpdate()->save();
|
||||||
} else {
|
} else {
|
||||||
$result = $this->db()->delete($this->data);
|
$result = $this->db(false)->delete($this->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->trigger('after_delete', $this);
|
$this->trigger('after_delete', $this);
|
||||||
|
|||||||
@@ -24,8 +24,8 @@
|
|||||||
<li>
|
<li>
|
||||||
<a href="{:url('index/content/detail?model_id='.$item['model_id'],array('id'=>$item['id']))}">
|
<a href="{:url('index/content/detail?model_id='.$item['model_id'],array('id'=>$item['id']))}">
|
||||||
<div class="time">
|
<div class="time">
|
||||||
<span class="day">{$item['create_time']|date='d',###}</span>
|
<span class="day">{$item['create_time']|date='Y-m-d H:i:s',###}</span>
|
||||||
<span class="moth">{$item['create_time']|date='m',###}</span>
|
<span class="moth">{$item['create_time']|date='Y-m-d H:i:s',###}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<div class="tit">{$item['title']|msubstr=###,0,80}</div>
|
<div class="tit">{$item['title']|msubstr=###,0,80}</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user