内核更新
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
namespace think\model;
|
||||
|
||||
use think\Db;
|
||||
use think\db\Query;
|
||||
use think\Model;
|
||||
|
||||
class Merge extends Model
|
||||
@@ -168,12 +169,13 @@ class Merge extends Model
|
||||
$this->autoCompleteData($this->auto);
|
||||
|
||||
// 自动写入更新时间
|
||||
if ($this->autoWriteTimestamp && $this->updateTime) {
|
||||
if ($this->autoWriteTimestamp && $this->updateTime && !isset($this->data[$this->updateTime])) {
|
||||
$this->setAttr($this->updateTime, null);
|
||||
}
|
||||
|
||||
$db = $this->db();
|
||||
$db->startTrans();
|
||||
$pk = $this->getPk();
|
||||
try {
|
||||
if ($this->isUpdate) {
|
||||
// 自动写入
|
||||
@@ -187,19 +189,15 @@ class Merge extends Model
|
||||
$where = $this->updateWhere;
|
||||
}
|
||||
|
||||
if (!empty($where)) {
|
||||
$pk = $this->getPk();
|
||||
|
||||
if (isset($this->mapFields[$pk])) {
|
||||
$pk = $this->mapFields[$pk];
|
||||
}
|
||||
if (isset($where[$pk])) {
|
||||
unset($where[$pk]);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理模型数据
|
||||
$data = $this->parseData($this->name, $this->data);
|
||||
if (is_string($pk) && isset($data[$pk])) {
|
||||
if (!isset($where[$pk])) {
|
||||
unset($where);
|
||||
$where[$pk] = $data[$pk];
|
||||
}
|
||||
unset($data[$pk]);
|
||||
}
|
||||
// 写入主表数据
|
||||
$result = $db->strict(false)->where($where)->update($data);
|
||||
|
||||
@@ -209,7 +207,7 @@ class Merge extends Model
|
||||
$table = is_int($key) ? $db->getTable($model) : $model;
|
||||
// 处理关联模型数据
|
||||
$data = $this->parseData($name, $this->data);
|
||||
$query = clone $db;
|
||||
$query = new Query;
|
||||
if ($query->table($table)->strict(false)->where($this->fk, $this->data[$this->getPk()])->update($data)) {
|
||||
$result = 1;
|
||||
}
|
||||
@@ -223,7 +221,7 @@ class Merge extends Model
|
||||
$this->autoCompleteData($this->insert);
|
||||
|
||||
// 自动写入创建时间
|
||||
if ($this->autoWriteTimestamp && $this->createTime) {
|
||||
if ($this->autoWriteTimestamp && $this->createTime && !isset($this->data[$this->createTime])) {
|
||||
$this->setAttr($this->createTime, null);
|
||||
}
|
||||
|
||||
@@ -238,7 +236,6 @@ class Merge extends Model
|
||||
if ($result) {
|
||||
$insertId = $db->getLastInsID($sequence);
|
||||
// 写入外键数据
|
||||
$pk = $this->getPk();
|
||||
if ($insertId) {
|
||||
if (is_string($pk)) {
|
||||
$this->data[$pk] = $insertId;
|
||||
@@ -259,7 +256,7 @@ class Merge extends Model
|
||||
$table = is_int($key) ? $db->getTable($model) : $model;
|
||||
// 处理关联模型数据
|
||||
$data = $this->parseData($name, $source, true);
|
||||
$query = clone $db;
|
||||
$query = new Query;
|
||||
$query->table($table)->strict(false)->insert($data);
|
||||
}
|
||||
}
|
||||
@@ -300,7 +297,7 @@ class Merge extends Model
|
||||
// 删除关联数据
|
||||
foreach ($this->relationModel as $key => $model) {
|
||||
$table = is_int($key) ? $db->getTable($model) : $model;
|
||||
$query = clone $db;
|
||||
$query = new Query;
|
||||
$query->table($table)->where($this->fk, $pk)->delete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
namespace think\model\relation;
|
||||
|
||||
use think\Model;
|
||||
use think\model\relation\OneToOne;
|
||||
|
||||
class BelongsTo extends OneToOne
|
||||
{
|
||||
@@ -22,7 +21,7 @@ class BelongsTo extends OneToOne
|
||||
* @param Model $parent 上级模型对象
|
||||
* @param string $model 模型名
|
||||
* @param string $foreignKey 关联外键
|
||||
* @param string $otherKey 关联主键
|
||||
* @param string $localKey 关联主键
|
||||
* @param array $alias 别名定义
|
||||
* @param string $joinType JOIN类型
|
||||
*/
|
||||
@@ -48,4 +47,80 @@ class BelongsTo extends OneToOne
|
||||
return $this->query->where($localKey, $this->parent->$foreignKey)->find();
|
||||
}
|
||||
|
||||
/**
|
||||
* 预载入关联查询(数据集)
|
||||
* @access public
|
||||
* @param array $resultSet 数据集
|
||||
* @param string $relation 当前关联名
|
||||
* @param string $subRelation 子关联名
|
||||
* @param \Closure $closure 闭包
|
||||
* @param string $class 数据集对象名 为空表示数组
|
||||
* @return void
|
||||
*/
|
||||
protected function eagerlySet(&$resultSet, $relation, $subRelation, $closure, $class)
|
||||
{
|
||||
$localKey = $this->localKey;
|
||||
$foreignKey = $this->foreignKey;
|
||||
|
||||
$range = [];
|
||||
foreach ($resultSet as $result) {
|
||||
// 获取关联外键列表
|
||||
if (isset($result->$foreignKey)) {
|
||||
$range[] = $result->$foreignKey;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($range)) {
|
||||
$this->where[$localKey] = ['in', $range];
|
||||
$data = $this->eagerlyWhere($this, [
|
||||
$localKey => [
|
||||
'in',
|
||||
$range,
|
||||
],
|
||||
], $localKey, $relation, $subRelation, $closure);
|
||||
|
||||
// 关联数据封装
|
||||
foreach ($resultSet as $result) {
|
||||
if (!isset($data[$result->$foreignKey])) {
|
||||
$data[$result->$foreignKey] = [];
|
||||
}
|
||||
$relationModel = $this->resultSetBuild($data[$result->$foreignKey], $class);
|
||||
if (!empty($this->bindAttr)) {
|
||||
// 绑定关联属性
|
||||
$this->bindAttr($relationModel, $result, $this->bindAttr);
|
||||
}
|
||||
// 设置关联属性
|
||||
$result->setAttr($relation, $relationModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 预载入关联查询(数据)
|
||||
* @access public
|
||||
* @param Model $result 数据对象
|
||||
* @param string $relation 当前关联名
|
||||
* @param string $subRelation 子关联名
|
||||
* @param \Closure $closure 闭包
|
||||
* @param string $class 数据集对象名 为空表示数组
|
||||
* @return void
|
||||
*/
|
||||
protected function eagerlyOne(&$result, $relation, $subRelation, $closure, $class)
|
||||
{
|
||||
$localKey = $this->localKey;
|
||||
$foreignKey = $this->foreignKey;
|
||||
$data = $this->eagerlyWhere($this, [$localKey => $result->$foreignKey], $localKey, $relation, $subRelation, $closure);
|
||||
// 关联数据封装
|
||||
if (!isset($data[$result->$foreignKey])) {
|
||||
$data[$result->$foreignKey] = [];
|
||||
}
|
||||
$relationModel = $this->resultSetBuild($data[$result->$foreignKey], $class);
|
||||
if (!empty($this->bindAttr)) {
|
||||
// 绑定关联属性
|
||||
$this->bindAttr($relationModel, $result, $this->bindAttr);
|
||||
}
|
||||
// 设置关联属性
|
||||
$result->setAttr($relation, $relationModel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace think\model\relation;
|
||||
|
||||
use think\Db;
|
||||
use think\db\Query;
|
||||
use think\Exception;
|
||||
use think\Model;
|
||||
use think\model\Pivot;
|
||||
use think\model\Relation;
|
||||
@@ -128,14 +129,11 @@ class BelongsToMany extends Relation
|
||||
*/
|
||||
public function eagerlyResult(&$result, $relation, $subRelation, $closure, $class)
|
||||
{
|
||||
$localKey = $this->localKey;
|
||||
$foreignKey = $this->foreignKey;
|
||||
|
||||
$pk = $result->getPk();
|
||||
if (isset($result->$pk)) {
|
||||
$pk = $result->$pk;
|
||||
// 查询管理数据
|
||||
$data = $this->eagerlyManyToMany(['pivot.' . $localKey => $pk], $relation, $subRelation);
|
||||
$data = $this->eagerlyManyToMany(['pivot.' . $this->localKey => $pk], $relation, $subRelation);
|
||||
|
||||
// 关联数据封装
|
||||
if (!isset($data[$pk])) {
|
||||
@@ -145,6 +143,35 @@ class BelongsToMany extends Relation
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关联统计
|
||||
* @access public
|
||||
* @param Model $result 数据对象
|
||||
* @param \Closure $closure 闭包
|
||||
* @return integer
|
||||
*/
|
||||
public function relationCount($result, $closure)
|
||||
{
|
||||
$pk = $result->getPk();
|
||||
$count = 0;
|
||||
if (isset($result->$pk)) {
|
||||
$pk = $result->$pk;
|
||||
$count = $this->belongsToManyQuery($this->middle, $this->foreignKey, $this->localKey, ['pivot.' . $this->localKey => $pk])->count();
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取关联统计子查询
|
||||
* @access public
|
||||
* @param \Closure $closure 闭包
|
||||
* @return string
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 多对多 关联模型预查询
|
||||
* @access public
|
||||
@@ -155,10 +182,8 @@ class BelongsToMany extends Relation
|
||||
*/
|
||||
protected function eagerlyManyToMany($where, $relation, $subRelation = '')
|
||||
{
|
||||
$foreignKey = $this->foreignKey;
|
||||
$localKey = $this->localKey;
|
||||
// 预载入关联查询 支持嵌套预载入
|
||||
$list = $this->belongsToManyQuery($this->middle, $foreignKey, $localKey, $where)->with($subRelation)->select();
|
||||
$list = $this->belongsToManyQuery($this->middle, $this->foreignKey, $this->localKey, $where)->with($subRelation)->select();
|
||||
|
||||
// 组装模型数据
|
||||
$data = [];
|
||||
@@ -173,8 +198,8 @@ class BelongsToMany extends Relation
|
||||
}
|
||||
}
|
||||
}
|
||||
$set->pivot = new Pivot($pivot, $this->middle);
|
||||
$data[$pivot[$localKey]][] = $set;
|
||||
$set->pivot = new Pivot($pivot, $this->middle);
|
||||
$data[$pivot[$this->localKey]][] = $set;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
@@ -217,13 +242,19 @@ class BelongsToMany extends Relation
|
||||
* @access public
|
||||
* @param array $dataSet 数据集
|
||||
* @param array $pivot 中间表额外数据
|
||||
* @param bool $samePivot 额外数据是否相同
|
||||
* @return integer
|
||||
*/
|
||||
public function saveAll(array $dataSet, array $pivot = [])
|
||||
public function saveAll(array $dataSet, array $pivot = [], $samePivot = false)
|
||||
{
|
||||
$result = false;
|
||||
foreach ($dataSet as $key => $data) {
|
||||
$result = $this->attach($data, !empty($pivot) ? $pivot[$key] : []);
|
||||
if (!$samePivot) {
|
||||
$pivotData = isset($pivot[$key]) ? $pivot[$key] : [];
|
||||
} else {
|
||||
$pivotData = $pivot;
|
||||
}
|
||||
$result = $this->attach($data, $pivotData);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
@@ -238,10 +269,14 @@ class BelongsToMany extends Relation
|
||||
public function attach($data, $pivot = [])
|
||||
{
|
||||
if (is_array($data)) {
|
||||
// 保存关联表数据
|
||||
$model = new $this->model;
|
||||
$model->save($data);
|
||||
$id = $model->getLastInsID();
|
||||
if (key($data) === 0) {
|
||||
$id = $data;
|
||||
} else {
|
||||
// 保存关联表数据
|
||||
$model = new $this->model;
|
||||
$model->save($data);
|
||||
$id = $model->getLastInsID();
|
||||
}
|
||||
} elseif (is_numeric($data) || is_string($data)) {
|
||||
// 根据关联表主键直接写入中间表
|
||||
$id = $data;
|
||||
@@ -253,10 +288,14 @@ class BelongsToMany extends Relation
|
||||
|
||||
if ($id) {
|
||||
// 保存中间表数据
|
||||
$pk = $this->parent->getPk();
|
||||
$pivot[$this->localKey] = $this->parent->$pk;
|
||||
$pivot[$this->foreignKey] = $id;
|
||||
return $this->query->table($this->middle)->insert($pivot);
|
||||
$pk = $this->parent->getPk();
|
||||
$pivot[$this->localKey] = $this->parent->$pk;
|
||||
$ids = (array) $id;
|
||||
foreach ($ids as $id) {
|
||||
$pivot[$this->foreignKey] = $id;
|
||||
$result = $this->query->table($this->middle)->insert($pivot, true);
|
||||
}
|
||||
return $result;
|
||||
} else {
|
||||
throw new Exception('miss relation data');
|
||||
}
|
||||
|
||||
@@ -58,10 +58,8 @@ class HasMany extends Relation
|
||||
*/
|
||||
public function eagerlyResultSet(&$resultSet, $relation, $subRelation, $closure, $class)
|
||||
{
|
||||
$localKey = $this->localKey;
|
||||
$foreignKey = $this->foreignKey;
|
||||
|
||||
$range = [];
|
||||
$localKey = $this->localKey;
|
||||
$range = [];
|
||||
foreach ($resultSet as $result) {
|
||||
// 获取关联外键列表
|
||||
if (isset($result->$localKey)) {
|
||||
@@ -70,9 +68,9 @@ class HasMany extends Relation
|
||||
}
|
||||
|
||||
if (!empty($range)) {
|
||||
$this->where[$foreignKey] = ['in', $range];
|
||||
$data = $this->eagerlyOneToMany($this, [
|
||||
$foreignKey => [
|
||||
$this->where[$this->foreignKey] = ['in', $range];
|
||||
$data = $this->eagerlyOneToMany($this, [
|
||||
$this->foreignKey => [
|
||||
'in',
|
||||
$range,
|
||||
],
|
||||
@@ -100,11 +98,10 @@ class HasMany extends Relation
|
||||
*/
|
||||
public function eagerlyResult(&$result, $relation, $subRelation, $closure, $class)
|
||||
{
|
||||
$localKey = $this->localKey;
|
||||
$foreignKey = $this->foreignKey;
|
||||
$localKey = $this->localKey;
|
||||
|
||||
if (isset($result->$localKey)) {
|
||||
$data = $this->eagerlyOneToMany($this, [$foreignKey => $result->$localKey], $relation, $subRelation, $closure);
|
||||
$data = $this->eagerlyOneToMany($this, [$this->foreignKey => $result->$localKey], $relation, $subRelation, $closure);
|
||||
// 关联数据封装
|
||||
if (!isset($data[$result->$localKey])) {
|
||||
$data[$result->$localKey] = [];
|
||||
@@ -113,6 +110,41 @@ class HasMany extends Relation
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关联统计
|
||||
* @access public
|
||||
* @param Model $result 数据对象
|
||||
* @param \Closure $closure 闭包
|
||||
* @return integer
|
||||
*/
|
||||
public function relationCount($result, $closure)
|
||||
{
|
||||
$localKey = $this->localKey;
|
||||
$count = 0;
|
||||
if (isset($result->$localKey)) {
|
||||
if ($closure) {
|
||||
call_user_func_array($closure, [ & $this->query]);
|
||||
}
|
||||
$count = $this->query->where([$this->foreignKey => $result->$localKey])->count();
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建关联统计子查询
|
||||
* @access public
|
||||
* @param \Closure $closure 闭包
|
||||
* @return string
|
||||
*/
|
||||
public function getRelationCountQuery($closure)
|
||||
{
|
||||
if ($closure) {
|
||||
call_user_func_array($closure, [ & $this->query]);
|
||||
}
|
||||
|
||||
return $this->query->where([$this->foreignKey => ['exp', '=' . $this->parent->getTable() . '.' . $this->parent->getPk()]])->fetchSql()->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* 一对多 关联模型预查询
|
||||
* @access public
|
||||
|
||||
@@ -21,6 +21,8 @@ class HasManyThrough extends Relation
|
||||
{
|
||||
// 中间关联表外键
|
||||
protected $throughKey;
|
||||
// 中间表模型
|
||||
protected $through;
|
||||
|
||||
/**
|
||||
* 架构函数
|
||||
@@ -37,7 +39,7 @@ class HasManyThrough extends Relation
|
||||
{
|
||||
$this->parent = $parent;
|
||||
$this->model = $model;
|
||||
$this->middle = $through;
|
||||
$this->through = $through;
|
||||
$this->foreignKey = $foreignKey;
|
||||
$this->throughKey = $throughKey;
|
||||
$this->localKey = $localKey;
|
||||
@@ -65,8 +67,7 @@ class HasManyThrough extends Relation
|
||||
* @return void
|
||||
*/
|
||||
public function eagerlyResultSet(&$resultSet, $relation, $subRelation, $closure, $class)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
/**
|
||||
* 预载入关联查询 返回模型对象
|
||||
@@ -79,8 +80,17 @@ class HasManyThrough extends Relation
|
||||
* @return void
|
||||
*/
|
||||
public function eagerlyResult(&$result, $relation, $subRelation, $closure, $class)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
/**
|
||||
* 关联统计
|
||||
* @access public
|
||||
* @param Model $result 数据对象
|
||||
* @param \Closure $closure 闭包
|
||||
* @return integer
|
||||
*/
|
||||
public function relationCount($result, $closure)
|
||||
{}
|
||||
|
||||
/**
|
||||
* 执行基础查询(进执行一次)
|
||||
@@ -90,7 +100,7 @@ class HasManyThrough extends Relation
|
||||
protected function baseQuery()
|
||||
{
|
||||
if (empty($this->baseQuery)) {
|
||||
$through = $this->middle;
|
||||
$through = $this->through;
|
||||
$model = $this->model;
|
||||
$alias = Loader::parseName(basename(str_replace('\\', '/', $model)));
|
||||
$throughTable = $through::getTable();
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
namespace think\model\relation;
|
||||
|
||||
use think\Model;
|
||||
use think\model\relation\OneToOne;
|
||||
|
||||
class HasOne extends OneToOne
|
||||
{
|
||||
@@ -73,4 +72,80 @@ class HasOne extends OneToOne
|
||||
->join($table . ' b', 'a.' . $this->localKey . '=b.' . $this->foreignKey, $this->joinType)
|
||||
->where($where);
|
||||
}
|
||||
|
||||
/**
|
||||
* 预载入关联查询(数据集)
|
||||
* @access public
|
||||
* @param array $resultSet 数据集
|
||||
* @param string $relation 当前关联名
|
||||
* @param string $subRelation 子关联名
|
||||
* @param \Closure $closure 闭包
|
||||
* @param string $class 数据集对象名 为空表示数组
|
||||
* @return void
|
||||
*/
|
||||
protected function eagerlySet(&$resultSet, $relation, $subRelation, $closure, $class)
|
||||
{
|
||||
$localKey = $this->localKey;
|
||||
$foreignKey = $this->foreignKey;
|
||||
|
||||
$range = [];
|
||||
foreach ($resultSet as $result) {
|
||||
// 获取关联外键列表
|
||||
if (isset($result->$localKey)) {
|
||||
$range[] = $result->$localKey;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($range)) {
|
||||
$this->where[$foreignKey] = ['in', $range];
|
||||
$data = $this->eagerlyWhere($this, [
|
||||
$foreignKey => [
|
||||
'in',
|
||||
$range,
|
||||
],
|
||||
], $foreignKey, $relation, $subRelation, $closure);
|
||||
|
||||
// 关联数据封装
|
||||
foreach ($resultSet as $result) {
|
||||
if (!isset($data[$result->$localKey])) {
|
||||
$data[$result->$localKey] = [];
|
||||
}
|
||||
$relationModel = $this->resultSetBuild($data[$result->$localKey], $class);
|
||||
if (!empty($this->bindAttr)) {
|
||||
// 绑定关联属性
|
||||
$this->bindAttr($relationModel, $result, $this->bindAttr);
|
||||
}
|
||||
// 设置关联属性
|
||||
$result->setAttr($relation, $relationModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 预载入关联查询(数据)
|
||||
* @access public
|
||||
* @param Model $result 数据对象
|
||||
* @param string $relation 当前关联名
|
||||
* @param string $subRelation 子关联名
|
||||
* @param \Closure $closure 闭包
|
||||
* @param string $class 数据集对象名 为空表示数组
|
||||
* @return void
|
||||
*/
|
||||
protected function eagerlyOne(&$result, $relation, $subRelation, $closure, $class)
|
||||
{
|
||||
$localKey = $this->localKey;
|
||||
$foreignKey = $this->foreignKey;
|
||||
$data = $this->eagerlyWhere($this, [$foreignKey => $result->$localKey], $foreignKey, $relation, $subRelation, $closure);
|
||||
// 关联数据封装
|
||||
if (!isset($data[$result->$localKey])) {
|
||||
$data[$result->$localKey] = [];
|
||||
}
|
||||
$relationModel = $this->resultSetBuild($data[$result->$localKey], $class);
|
||||
if (!empty($this->bindAttr)) {
|
||||
// 绑定关联属性
|
||||
$this->bindAttr($relationModel, $result, $this->bindAttr);
|
||||
}
|
||||
$result->setAttr($relation, $relationModel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -106,16 +106,48 @@ class MorphMany extends Relation
|
||||
*/
|
||||
public function eagerlyResult(&$result, $relation, $subRelation, $closure, $class)
|
||||
{
|
||||
$morphType = $this->morphType;
|
||||
$morphKey = $this->morphKey;
|
||||
$type = $this->type;
|
||||
$pk = $result->getPk();
|
||||
$pk = $result->getPk();
|
||||
if (isset($result->$pk)) {
|
||||
$data = $this->eagerlyMorphToMany([$morphKey => $result->$pk, $morphType => $type], $relation, $subRelation, $closure);
|
||||
$data = $this->eagerlyMorphToMany([$this->morphKey => $result->$pk, $this->morphType => $this->type], $relation, $subRelation, $closure);
|
||||
$result->setAttr($relation, $this->resultSetBuild($data[$result->$pk], $class));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关联统计
|
||||
* @access public
|
||||
* @param Model $result 数据对象
|
||||
* @param \Closure $closure 闭包
|
||||
* @return integer
|
||||
*/
|
||||
public function relationCount($result, $closure)
|
||||
{
|
||||
$pk = $result->getPk();
|
||||
$count = 0;
|
||||
if (isset($result->$pk)) {
|
||||
if ($closure) {
|
||||
call_user_func_array($closure, [ & $this->query]);
|
||||
}
|
||||
$count = $this->query->where([$this->morphKey => $result->$pk, $this->morphType => $this->type])->count();
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取关联统计子查询
|
||||
* @access public
|
||||
* @param \Closure $closure 闭包
|
||||
* @return string
|
||||
*/
|
||||
public function getRelationCountQuery($closure)
|
||||
{
|
||||
if ($closure) {
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 多态一对多 关联模型预查询
|
||||
* @access public
|
||||
|
||||
@@ -136,6 +136,16 @@ class MorphTo extends Relation
|
||||
$this->eagerlyMorphToOne($model, $relation, $result, $subRelation);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关联统计
|
||||
* @access public
|
||||
* @param Model $result 数据对象
|
||||
* @param \Closure $closure 闭包
|
||||
* @return integer
|
||||
*/
|
||||
public function relationCount($result, $closure)
|
||||
{}
|
||||
|
||||
/**
|
||||
* 多态MorphTo 关联模型预查询
|
||||
* @access public
|
||||
|
||||
@@ -12,15 +12,20 @@
|
||||
namespace think\model\relation;
|
||||
|
||||
use think\db\Query;
|
||||
use think\Exception;
|
||||
use think\Loader;
|
||||
use think\Model;
|
||||
use think\model\Relation;
|
||||
use think\model\relation\BelongsTo;
|
||||
|
||||
abstract class OneToOne extends Relation
|
||||
{
|
||||
// 预载入方式
|
||||
protected $eagerlyType = 0;
|
||||
// 要绑定的属性
|
||||
protected $bindAttr = [];
|
||||
|
||||
/**
|
||||
* 预载入关联查询
|
||||
* 预载入关联查询(JOIN方式)
|
||||
* @access public
|
||||
* @param Query $query 查询对象
|
||||
* @param string $relation 关联名
|
||||
@@ -76,7 +81,7 @@ abstract class OneToOne extends Relation
|
||||
}
|
||||
|
||||
/**
|
||||
* 预载入关联查询
|
||||
* 预载入关联查询(数据集)
|
||||
* @access public
|
||||
* @param array $resultSet 数据集
|
||||
* @param string $relation 当前关联名
|
||||
@@ -85,16 +90,21 @@ abstract class OneToOne extends Relation
|
||||
* @param string $class 数据集对象名 为空表示数组
|
||||
* @return void
|
||||
*/
|
||||
public function eagerlyResultSet(&$resultSet, $relation)
|
||||
public function eagerlyResultSet(&$resultSet, $relation, $subRelation, $closure, $class)
|
||||
{
|
||||
foreach ($resultSet as $result) {
|
||||
if (1 == $this->eagerlyType) {
|
||||
// IN查询
|
||||
$this->eagerlySet($resultSet, $relation, $subRelation, $closure, $class);
|
||||
} else {
|
||||
// 模型关联组装
|
||||
$this->match($this->model, $relation, $result);
|
||||
foreach ($resultSet as $result) {
|
||||
$this->match($this->model, $relation, $result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 预载入关联查询 返回模型对象
|
||||
* 预载入关联查询(数据)
|
||||
* @access public
|
||||
* @param Model $result 数据对象
|
||||
* @param string $relation 当前关联名
|
||||
@@ -103,12 +113,81 @@ abstract class OneToOne extends Relation
|
||||
* @param string $class 数据集对象名 为空表示数组
|
||||
* @return void
|
||||
*/
|
||||
public function eagerlyResult(&$result, $relation)
|
||||
public function eagerlyResult(&$result, $relation, $subRelation, $closure, $class)
|
||||
{
|
||||
// 模型关联组装
|
||||
$this->match($this->model, $relation, $result);
|
||||
if (1 == $this->eagerlyType) {
|
||||
// IN查询
|
||||
$this->eagerlyOne($result, $relation, $subRelation, $closure, $class);
|
||||
} else {
|
||||
// 模型关联组装
|
||||
$this->match($this->model, $relation, $result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存(新增)当前关联数据对象
|
||||
* @access public
|
||||
* @param mixed $data 数据 可以使用数组 关联模型对象 和 关联对象的主键
|
||||
* @return integer
|
||||
*/
|
||||
public function save($data)
|
||||
{
|
||||
if ($data instanceof Model) {
|
||||
$data = $data->getData();
|
||||
}
|
||||
// 保存关联表数据
|
||||
$data[$this->foreignKey] = $this->parent->{$this->localKey};
|
||||
$model = new $this->model;
|
||||
return $model->save($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置预载入方式
|
||||
* @access public
|
||||
* @param integer $type 预载入方式 0 JOIN查询 1 IN查询
|
||||
* @return this
|
||||
*/
|
||||
public function setEagerlyType($type)
|
||||
{
|
||||
$this->eagerlyType = $type;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取预载入方式
|
||||
* @access public
|
||||
* @return integer
|
||||
*/
|
||||
public function getEagerlyType()
|
||||
{
|
||||
return $this->eagerlyType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定关联表的属性到父模型属性
|
||||
* @access public
|
||||
* @param mixed $attr 要绑定的属性列表
|
||||
* @return this
|
||||
*/
|
||||
public function bind($attr)
|
||||
{
|
||||
if (is_string($attr)) {
|
||||
$attr = explode(',', $attr);
|
||||
}
|
||||
$this->bindAttr = $attr;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关联统计
|
||||
* @access public
|
||||
* @param Model $result 数据对象
|
||||
* @param \Closure $closure 闭包
|
||||
* @return integer
|
||||
*/
|
||||
public function relationCount($result, $closure)
|
||||
{}
|
||||
|
||||
/**
|
||||
* 一对一 关联模型预查询拼装
|
||||
* @access public
|
||||
@@ -129,25 +208,60 @@ abstract class OneToOne extends Relation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$result->setAttr($relation, !isset($list[$relation]) ? null : (new $model($list[$relation]))->isUpdate(true));
|
||||
if (isset($list[$relation])) {
|
||||
$relationModel = new $model($list[$relation]);
|
||||
if (!empty($this->bindAttr)) {
|
||||
$this->bindAttr($relationModel, $result, $this->bindAttr);
|
||||
}
|
||||
}
|
||||
$result->setAttr($relation, !isset($relationModel) ? null : $relationModel->isUpdate(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存(新增)当前关联数据对象
|
||||
* @access public
|
||||
* @param mixed $data 数据 可以使用数组 关联模型对象 和 关联对象的主键
|
||||
* @return integer
|
||||
* 绑定关联属性到父模型
|
||||
* @access protected
|
||||
* @param Model $model 关联模型对象
|
||||
* @param Model $result 父模型对象
|
||||
* @param array $bindAttr 绑定属性
|
||||
* @return void
|
||||
*/
|
||||
public function save($data)
|
||||
protected function bindAttr($model, &$result, $bindAttr)
|
||||
{
|
||||
if ($data instanceof Model) {
|
||||
$data = $data->getData();
|
||||
foreach ($bindAttr as $key => $attr) {
|
||||
$key = is_numeric($key) ? $attr : $key;
|
||||
if (isset($result->$key)) {
|
||||
throw new Exception('bind attr has exists:' . $key);
|
||||
} else {
|
||||
$result->setAttr($key, $model->$attr);
|
||||
}
|
||||
}
|
||||
// 保存关联表数据
|
||||
$data[$this->foreignKey] = $this->parent->{$this->localKey};
|
||||
$model = new $this->model;
|
||||
return $model->save($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 一对一 关联模型预查询(IN方式)
|
||||
* @access public
|
||||
* @param object $model 关联模型对象
|
||||
* @param array $where 关联预查询条件
|
||||
* @param string $key 关联键名
|
||||
* @param string $relation 关联名
|
||||
* @param string $subRelation 子关联
|
||||
* @param bool $closure
|
||||
* @return array
|
||||
*/
|
||||
protected function eagerlyWhere($model, $where, $key, $relation, $subRelation = '', $closure = false)
|
||||
{
|
||||
// 预载入关联查询 支持嵌套预载入
|
||||
if ($closure) {
|
||||
call_user_func_array($closure, [ & $model]);
|
||||
}
|
||||
$list = $model->where($where)->with($subRelation)->select();
|
||||
|
||||
// 组装模型数据
|
||||
$data = [];
|
||||
foreach ($list as $set) {
|
||||
$data[$set->$key][] = $set;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user