diff --git a/library/think/model/Pivot.php b/library/think/model/Pivot.php index 9fd45719..423921d7 100644 --- a/library/think/model/Pivot.php +++ b/library/think/model/Pivot.php @@ -16,13 +16,17 @@ use think\Model; class Pivot extends Model { + /** @var Model */ + public $parent; + /** * 构造函数 * @access public - * @param array|object $data 数据 - * @param string $table 中间数据表名 + * @param Model $parent + * @param array|object $data 数据 + * @param string $table 中间数据表名 */ - public function __construct($data = [], $table = '') + public function __construct(Model $parent, $data = [], $table = '') { if (is_object($data)) { $this->data = get_object_vars($data); @@ -30,6 +34,8 @@ class Pivot extends Model $this->data = $data; } + $this->parent = $parent; + $this->table = $table; } diff --git a/library/think/model/relation/BelongsToMany.php b/library/think/model/relation/BelongsToMany.php index 89eacfa1..34830e05 100644 --- a/library/think/model/relation/BelongsToMany.php +++ b/library/think/model/relation/BelongsToMany.php @@ -11,12 +11,14 @@ 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 { @@ -64,7 +66,43 @@ class BelongsToMany extends Relation protected function newPivot($data) { $pivot = $this->pivot ?: '\\think\\model\\Pivot'; - return new $pivot($data, $this->middle); + 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); } /** @@ -75,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 = $this->newPivot($pivot); - } + $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 @@ -290,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; } /**