From a01c43472d6714dc61396dc20fb9bbd030256cf6 Mon Sep 17 00:00:00 2001 From: thinkphp Date: Thu, 9 Feb 2017 14:26:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E8=BF=9BModel=E7=B1=BB=E7=9A=84has?= =?UTF-8?q?=E5=92=8ChasWhere=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lang/zh-cn.php | 1 + library/think/Model.php | 21 +++------- library/think/model/relation/BelongsTo.php | 39 ++++++++++++++++++ .../think/model/relation/BelongsToMany.php | 25 ++++++++++++ .../think/model/relation/HasManyThrough.php | 28 ++++++++++++- library/think/model/relation/HasOne.php | 18 ++++++++- library/think/model/relation/MorphMany.php | 40 +++++++++++++++---- library/think/model/relation/MorphTo.php | 25 ++++++++++++ 8 files changed, 172 insertions(+), 25 deletions(-) diff --git a/lang/zh-cn.php b/lang/zh-cn.php index b837bc41..c6c5a50f 100644 --- a/lang/zh-cn.php +++ b/lang/zh-cn.php @@ -64,4 +64,5 @@ return [ 'invalid request' => '非法请求', 'bind attr has exists' => '模型的属性已经存在', 'relation data not exists' => '关联数据不存在', + 'relation not support' => '关联不支持', ]; diff --git a/library/think/Model.php b/library/think/Model.php index 8da1ce4a..1222b548 100644 --- a/library/think/Model.php +++ b/library/think/Model.php @@ -1426,16 +1426,11 @@ abstract class Model implements \JsonSerializable, \ArrayAccess */ public static function has($relation, $operator = '>=', $count = 1, $id = '*') { - $model = new static(); - $relation = $model->$relation(); - if ($relation instanceof HasMany) { - if (is_array($operator) || $operator instanceof \Closure) { - return $relation->hasWhere($operator); - } - return $relation->has($operator, $count, $id); - } else { - return $relation; + $relation = (new static())->$relation(); + if (is_array($operator) || $operator instanceof \Closure) { + return $relation->hasWhere($operator); } + return $relation->has($operator, $count, $id); } /** @@ -1447,13 +1442,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess */ public static function hasWhere($relation, $where = []) { - $model = new static(); - $relation = $model->$relation(); - if ($relation instanceof HasMany) { - return $relation->hasWhere($where); - } else { - return $relation; - } + return (new static())->$relation()->hasWhere($where); } /** diff --git a/library/think/model/relation/BelongsTo.php b/library/think/model/relation/BelongsTo.php index 1997badc..5cee16d8 100644 --- a/library/think/model/relation/BelongsTo.php +++ b/library/think/model/relation/BelongsTo.php @@ -51,6 +51,45 @@ class BelongsTo extends OneToOne return $this->query->where($this->localKey, $this->parent->$foreignKey)->relation($subRelation)->find(); } + /** + * 根据关联条件查询当前模型 + * @access public + * @param string $operator 比较操作符 + * @param integer $count 个数 + * @param string $id 关联表的统计字段 + * @param string $joinType JOIN类型 + * @return Query + */ + public function has($operator = '>=', $count = 1, $id = '*') + { + return $this->parent; + } + + /** + * 根据关联条件查询当前模型 + * @access public + * @param mixed $where 查询条件(数组或者闭包) + * @return Query + */ + public function hasWhere($where = []) + { + $table = $this->query->getTable(); + $model = basename(str_replace('\\', '/', get_class($this->parent))); + $relation = basename(str_replace('\\', '/', $this->model)); + if (is_array($where)) { + foreach ($where as $key => $val) { + if (false === strpos($key, '.')) { + $where[$relation . '.' . $key] = $val; + unset($where[$key]); + } + } + } + return $this->parent->db()->alias($model) + ->field($model . '.*') + ->join($table . ' ' . $relation, $model . '.' . $this->foreignKey . '=' . $relation . '.' . $this->localKey, $this->joinType) + ->where($where); + } + /** * 预载入关联查询(数据集) * @access public diff --git a/library/think/model/relation/BelongsToMany.php b/library/think/model/relation/BelongsToMany.php index 128287e0..691ad846 100644 --- a/library/think/model/relation/BelongsToMany.php +++ b/library/think/model/relation/BelongsToMany.php @@ -76,6 +76,31 @@ class BelongsToMany extends Relation return $result; } + /** + * 根据关联条件查询当前模型 + * @access public + * @param string $operator 比较操作符 + * @param integer $count 个数 + * @param string $id 关联表的统计字段 + * @param string $joinType JOIN类型 + * @return Query + */ + public function has($operator = '>=', $count = 1, $id = '*', $joinType = 'INNER') + { + return $this->parent; + } + + /** + * 根据关联条件查询当前模型 + * @access public + * @param mixed $where 查询条件(数组或者闭包) + * @return Query + */ + public function hasWhere($where = []) + { + throw new Exception('relation not support: hasWhere'); + } + /** * 预载入关联查询(数据集) * @access public diff --git a/library/think/model/relation/HasManyThrough.php b/library/think/model/relation/HasManyThrough.php index e1518972..04b71e04 100644 --- a/library/think/model/relation/HasManyThrough.php +++ b/library/think/model/relation/HasManyThrough.php @@ -13,6 +13,7 @@ namespace think\model\relation; use think\Db; use think\db\Query; +use think\Exception; use think\Loader; use think\Model; use think\model\Relation; @@ -54,11 +55,36 @@ class HasManyThrough extends Relation public function getRelation($subRelation = '', $closure = null) { if ($closure) { - call_user_func_array($closure, [& $this->query]); + call_user_func_array($closure, [ & $this->query]); } return $this->relation($subRelation)->select(); } + /** + * 根据关联条件查询当前模型 + * @access public + * @param string $operator 比较操作符 + * @param integer $count 个数 + * @param string $id 关联表的统计字段 + * @param string $joinType JOIN类型 + * @return Query + */ + public function has($operator = '>=', $count = 1, $id = '*', $joinType = 'INNER') + { + return $this->parent; + } + + /** + * 根据关联条件查询当前模型 + * @access public + * @param mixed $where 查询条件(数组或者闭包) + * @return Query + */ + public function hasWhere($where = []) + { + throw new Exception('relation not support: hasWhere'); + } + /** * 预载入关联查询 * @access public diff --git a/library/think/model/relation/HasOne.php b/library/think/model/relation/HasOne.php index 2c0cf350..a2ff72be 100644 --- a/library/think/model/relation/HasOne.php +++ b/library/think/model/relation/HasOne.php @@ -47,12 +47,28 @@ class HasOne extends OneToOne // 执行关联定义方法 $localKey = $this->localKey; if ($closure) { - call_user_func_array($closure, [& $this->query]); + call_user_func_array($closure, [ & $this->query]); } // 判断关联类型执行查询 return $this->query->where($this->foreignKey, $this->parent->$localKey)->relation($subRelation)->find(); } + /** + * 根据关联条件查询当前模型 + * @access public + * @return Query + */ + public function has() + { + $table = $this->query->getTable(); + $localKey = $this->localKey; + $foreignKey = $this->foreignKey; + return $this->parent->db()->alias('a') + ->whereExists(function ($query) use ($table, $localKey, $foreignKey) { + $query->table([$table => 'b'])->whereExp('a.' . $localKey, '=b.' . $foreignKey); + }); + } + /** * 根据关联条件查询当前模型 * @access public diff --git a/library/think/model/relation/MorphMany.php b/library/think/model/relation/MorphMany.php index 3fc8179c..4dbd2ef5 100644 --- a/library/think/model/relation/MorphMany.php +++ b/library/think/model/relation/MorphMany.php @@ -13,6 +13,7 @@ namespace think\model\relation; use think\Db; use think\db\Query; +use think\Exception; use think\Loader; use think\Model; use think\model\Relation; @@ -53,11 +54,36 @@ class MorphMany extends Relation public function getRelation($subRelation = '', $closure = null) { if ($closure) { - call_user_func_array($closure, [& $this->query]); + call_user_func_array($closure, [ & $this->query]); } return $this->relation($subRelation)->select(); } + /** + * 根据关联条件查询当前模型 + * @access public + * @param string $operator 比较操作符 + * @param integer $count 个数 + * @param string $id 关联表的统计字段 + * @param string $joinType JOIN类型 + * @return Query + */ + public function has($operator = '>=', $count = 1, $id = '*', $joinType = 'INNER') + { + throw new Exception('relation not support: has'); + } + + /** + * 根据关联条件查询当前模型 + * @access public + * @param mixed $where 查询条件(数组或者闭包) + * @return Query + */ + public function hasWhere($where = []) + { + throw new Exception('relation not support: hasWhere'); + } + /** * 预载入关联查询 * @access public @@ -113,7 +139,7 @@ class MorphMany extends Relation if (isset($result->$pk)) { $data = $this->eagerlyMorphToMany([ $this->morphKey => $result->$pk, - $this->morphType => $this->type + $this->morphType => $this->type, ], $relation, $subRelation, $closure); $result->setAttr(Loader::parseName($relation), $this->resultSetBuild($data[$result->$pk])); } @@ -132,7 +158,7 @@ class MorphMany extends Relation $count = 0; if (isset($result->$pk)) { if ($closure) { - call_user_func_array($closure, [& $this->query]); + call_user_func_array($closure, [ & $this->query]); } $count = $this->query->where([$this->morphKey => $result->$pk, $this->morphType => $this->type])->count(); } @@ -148,15 +174,15 @@ class MorphMany extends Relation public function getRelationCountQuery($closure) { if ($closure) { - 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->parent->getTable() . '.' . $this->parent->getPk(), ], - $this->morphType => $this->type + $this->morphType => $this->type, ])->fetchSql()->count(); } @@ -173,7 +199,7 @@ class MorphMany extends Relation { // 预载入关联查询 支持嵌套预载入 if ($closure) { - call_user_func_array($closure, [& $this]); + call_user_func_array($closure, [ & $this]); } $list = $this->query->where($where)->with($subRelation)->select(); $morphKey = $this->morphKey; diff --git a/library/think/model/relation/MorphTo.php b/library/think/model/relation/MorphTo.php index 5e1867f2..04df0e79 100644 --- a/library/think/model/relation/MorphTo.php +++ b/library/think/model/relation/MorphTo.php @@ -57,6 +57,31 @@ class MorphTo extends Relation return (new $model)->relation($subRelation)->find($pk); } + /** + * 根据关联条件查询当前模型 + * @access public + * @param string $operator 比较操作符 + * @param integer $count 个数 + * @param string $id 关联表的统计字段 + * @param string $joinType JOIN类型 + * @return Query + */ + public function has($operator = '>=', $count = 1, $id = '*', $joinType = 'INNER') + { + return $this->parent; + } + + /** + * 根据关联条件查询当前模型 + * @access public + * @param mixed $where 查询条件(数组或者闭包) + * @return Query + */ + public function hasWhere($where = []) + { + throw new Exception('relation not support: hasWhere'); + } + /** * 解析模型的完整命名空间 * @access public