内核更新
This commit is contained in:
@@ -11,18 +11,23 @@
|
||||
|
||||
namespace think\model\relation;
|
||||
|
||||
use think\Collection;
|
||||
use think\db\Query;
|
||||
use think\Exception;
|
||||
use think\Loader;
|
||||
use think\Model;
|
||||
use think\model\Pivot;
|
||||
use think\model\Relation;
|
||||
use think\Paginator;
|
||||
|
||||
class BelongsToMany extends Relation
|
||||
{
|
||||
// 中间表模型
|
||||
// 中间表表名
|
||||
protected $middle;
|
||||
|
||||
// 中间表模型
|
||||
protected $pivot;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @access public
|
||||
@@ -42,6 +47,64 @@ class BelongsToMany extends Relation
|
||||
$this->query = (new $model)->db();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置中间表模型
|
||||
* @param $pivot
|
||||
* @return $this
|
||||
*/
|
||||
public function pivot($pivot)
|
||||
{
|
||||
$this->pivot = $pivot;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 实例化中间表模型
|
||||
* @param $data
|
||||
* @return mixed
|
||||
*/
|
||||
protected function newPivot($data)
|
||||
{
|
||||
$pivot = $this->pivot ?: '\\think\\model\\Pivot';
|
||||
return new $pivot($this->parent, $data, $this->middle);
|
||||
}
|
||||
|
||||
/**
|
||||
* 合成中间表模型
|
||||
* @param array|Collection|Paginator $models
|
||||
*/
|
||||
protected function hydratePivot($models)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$pivot = [];
|
||||
foreach ($model->getData() as $key => $val) {
|
||||
if (strpos($key, '__')) {
|
||||
list($name, $attr) = explode('__', $key, 2);
|
||||
if ('pivot' == $name) {
|
||||
$pivot[$attr] = $val;
|
||||
unset($model->$key);
|
||||
}
|
||||
}
|
||||
}
|
||||
$model->pivot = $this->newPivot($pivot);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建关联查询Query对象
|
||||
* @return Query
|
||||
*/
|
||||
protected function buildQuery()
|
||||
{
|
||||
$foreignKey = $this->foreignKey;
|
||||
$localKey = $this->localKey;
|
||||
$middle = $this->middle;
|
||||
// 关联查询
|
||||
$pk = $this->parent->getPk();
|
||||
$condition['pivot.' . $localKey] = $this->parent->$pk;
|
||||
return $this->belongsToManyQuery($middle, $foreignKey, $localKey, $condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* 延迟获取关联数据
|
||||
* @param string $subRelation 子关联名
|
||||
@@ -50,32 +113,74 @@ class BelongsToMany extends Relation
|
||||
*/
|
||||
public function getRelation($subRelation = '', $closure = null)
|
||||
{
|
||||
$foreignKey = $this->foreignKey;
|
||||
$localKey = $this->localKey;
|
||||
$middle = $this->middle;
|
||||
if ($closure) {
|
||||
call_user_func_array($closure, [ & $this->query]);
|
||||
}
|
||||
// 关联查询
|
||||
$pk = $this->parent->getPk();
|
||||
$condition['pivot.' . $localKey] = $this->parent->$pk;
|
||||
$result = $this->belongsToManyQuery($middle, $foreignKey, $localKey, $condition)->relation($subRelation)->select();
|
||||
foreach ($result as $set) {
|
||||
$pivot = [];
|
||||
foreach ($set->getData() as $key => $val) {
|
||||
if (strpos($key, '__')) {
|
||||
list($name, $attr) = explode('__', $key, 2);
|
||||
if ('pivot' == $name) {
|
||||
$pivot[$attr] = $val;
|
||||
unset($set->$key);
|
||||
}
|
||||
}
|
||||
}
|
||||
$set->pivot = new Pivot($pivot, $this->middle);
|
||||
call_user_func_array($closure, [& $this->query]);
|
||||
}
|
||||
$result = $this->buildQuery()->relation($subRelation)->select();
|
||||
$this->hydratePivot($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重载select方法
|
||||
* @param null $data
|
||||
* @return false|\PDOStatement|string|Collection
|
||||
*/
|
||||
public function select($data = null)
|
||||
{
|
||||
$result = $this->buildQuery()->select($data);
|
||||
$this->hydratePivot($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重载paginate方法
|
||||
* @param null $listRows
|
||||
* @param bool $simple
|
||||
* @param array $config
|
||||
* @return Paginator
|
||||
*/
|
||||
public function paginate($listRows = null, $simple = false, $config = [])
|
||||
{
|
||||
$result = $this->buildQuery()->paginate($listRows, $simple, $config);
|
||||
$this->hydratePivot($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重载find方法
|
||||
* @param null $data
|
||||
* @return array|false|\PDOStatement|string|Model
|
||||
*/
|
||||
public function find($data = null)
|
||||
{
|
||||
$result = $this->buildQuery()->find($data);
|
||||
$this->hydratePivot([$result]);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找多条记录 如果不存在则抛出异常
|
||||
* @access public
|
||||
* @param array|string|Query|\Closure $data
|
||||
* @return array|\PDOStatement|string|Model
|
||||
*/
|
||||
public function selectOrFail($data = null)
|
||||
{
|
||||
return $this->failException(true)->select($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找单条记录 如果不存在则抛出异常
|
||||
* @access public
|
||||
* @param array|string|Query|\Closure $data
|
||||
* @return array|\PDOStatement|string|Model
|
||||
*/
|
||||
public function findOrFail($data = null)
|
||||
{
|
||||
return $this->failException(true)->find($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据关联条件查询当前模型
|
||||
* @access public
|
||||
@@ -95,12 +200,27 @@ class BelongsToMany extends Relation
|
||||
* @access public
|
||||
* @param mixed $where 查询条件(数组或者闭包)
|
||||
* @return Query
|
||||
* @throws Exception
|
||||
*/
|
||||
public function hasWhere($where = [])
|
||||
{
|
||||
throw new Exception('relation not support: hasWhere');
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置中间表的查询条件
|
||||
* @param $field
|
||||
* @param null $op
|
||||
* @param null $condition
|
||||
* @return $this
|
||||
*/
|
||||
public function wherePivot($field, $op = null, $condition = null)
|
||||
{
|
||||
$field = 'pivot.' . $field;
|
||||
$this->query->where($field, $op, $condition);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 预载入关联查询(数据集)
|
||||
* @access public
|
||||
@@ -230,7 +350,7 @@ class BelongsToMany extends Relation
|
||||
}
|
||||
}
|
||||
}
|
||||
$set->pivot = new Pivot($pivot, $this->middle);
|
||||
$set->pivot = $this->newPivot($pivot);
|
||||
$data[$pivot[$this->localKey]][] = $set;
|
||||
}
|
||||
return $data;
|
||||
@@ -250,10 +370,14 @@ class BelongsToMany extends Relation
|
||||
// 关联查询封装
|
||||
$tableName = $this->query->getTable();
|
||||
$relationFk = $this->query->getPk();
|
||||
return $this->query->field($tableName . '.*')
|
||||
->field(true, false, $table, 'pivot', 'pivot__')
|
||||
->join($table . ' pivot', 'pivot.' . $foreignKey . '=' . $tableName . '.' . $relationFk)
|
||||
->where($condition);
|
||||
$query = $this->query->field($tableName . '.*')
|
||||
->field(true, false, $table, 'pivot', 'pivot__');
|
||||
|
||||
if (empty($this->baseQuery)) {
|
||||
$query->join($table . ' pivot', 'pivot.' . $foreignKey . '=' . $tableName . '.' . $relationFk)
|
||||
->where($condition);
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -327,7 +451,7 @@ class BelongsToMany extends Relation
|
||||
foreach ($ids as $id) {
|
||||
$pivot[$this->foreignKey] = $id;
|
||||
$this->query->table($this->middle)->insert($pivot, true);
|
||||
$result[] = new Pivot($pivot, $this->middle);
|
||||
$result[] = $this->newPivot($pivot);
|
||||
}
|
||||
if (count($result) == 1) {
|
||||
// 返回中间表模型对象
|
||||
|
||||
@@ -183,7 +183,7 @@ class HasMany extends Relation
|
||||
* 保存(新增)当前关联数据对象
|
||||
* @access public
|
||||
* @param mixed $data 数据 可以使用数组 关联模型对象 和 关联对象的主键
|
||||
* @return integer
|
||||
* @return Model|false
|
||||
*/
|
||||
public function save($data)
|
||||
{
|
||||
@@ -191,9 +191,9 @@ class HasMany extends Relation
|
||||
$data = $data->getData();
|
||||
}
|
||||
// 保存关联表数据
|
||||
$data[$this->foreignKey] = $this->parent->{$this->localKey};
|
||||
$model = new $this->model;
|
||||
return $model->save($data);
|
||||
$data[$this->foreignKey] = $this->parent->{$this->localKey};
|
||||
return $model->save($data) ? $model : false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -215,7 +215,7 @@ class MorphMany extends Relation
|
||||
* 保存(新增)当前关联数据对象
|
||||
* @access public
|
||||
* @param mixed $data 数据 可以使用数组 关联模型对象 和 关联对象的主键
|
||||
* @return integer
|
||||
* @return Model|false
|
||||
*/
|
||||
public function save($data)
|
||||
{
|
||||
@@ -225,10 +225,10 @@ class MorphMany extends Relation
|
||||
// 保存关联表数据
|
||||
$pk = $this->parent->getPk();
|
||||
|
||||
$model = new $this->model;
|
||||
$data[$this->morphKey] = $this->parent->$pk;
|
||||
$data[$this->morphType] = $this->type;
|
||||
$model = new $this->model;
|
||||
return $model->save($data);
|
||||
return $model->save($data) ? $model : false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -114,6 +114,16 @@ class MorphTo extends Relation
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除关联查询参数
|
||||
* @access public
|
||||
* @return $this
|
||||
*/
|
||||
public function removeOption()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 预载入关联查询
|
||||
* @access public
|
||||
|
||||
@@ -67,6 +67,7 @@ abstract class OneToOne extends Relation
|
||||
$field = true;
|
||||
}
|
||||
$query->field($field, false, $table, $alias);
|
||||
$field = null;
|
||||
}
|
||||
|
||||
// 预载入封装
|
||||
@@ -82,7 +83,7 @@ abstract class OneToOne extends Relation
|
||||
|
||||
if ($closure) {
|
||||
// 执行闭包查询
|
||||
call_user_func_array($closure, [& $query]);
|
||||
call_user_func_array($closure, [ & $query]);
|
||||
// 使用withField指定获取关联的字段,如
|
||||
// $query->where(['id'=>1])->withField('id,name');
|
||||
if ($query->getOptions('with_field')) {
|
||||
@@ -91,10 +92,8 @@ abstract class OneToOne extends Relation
|
||||
}
|
||||
} elseif (isset($this->option['field'])) {
|
||||
$field = $this->option['field'];
|
||||
} else {
|
||||
$field = true;
|
||||
}
|
||||
$query->field($field, false, $joinTable, $joinAlias, $relation . '__');
|
||||
$query->field(isset($field) ? $field : true, false, $joinTable, $joinAlias, $relation . '__');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,17 +162,17 @@ abstract class OneToOne extends Relation
|
||||
* 保存(新增)当前关联数据对象
|
||||
* @access public
|
||||
* @param mixed $data 数据 可以使用数组 关联模型对象 和 关联对象的主键
|
||||
* @return integer
|
||||
* @return Model|false
|
||||
*/
|
||||
public function save($data)
|
||||
{
|
||||
if ($data instanceof Model) {
|
||||
$data = $data->getData();
|
||||
}
|
||||
$model = new $this->model;
|
||||
// 保存关联表数据
|
||||
$data[$this->foreignKey] = $this->parent->{$this->localKey};
|
||||
$model = new $this->model;
|
||||
return $model->save($data);
|
||||
return $model->save($data) ? $model : false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,7 +194,6 @@ abstract class OneToOne extends Relation
|
||||
*/
|
||||
public function getEagerlyType()
|
||||
{
|
||||
$this->removeOption();
|
||||
return $this->eagerlyType;
|
||||
}
|
||||
|
||||
@@ -290,7 +288,7 @@ abstract class OneToOne extends Relation
|
||||
{
|
||||
// 预载入关联查询 支持嵌套预载入
|
||||
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');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user