From da90d38b9a51b10fdf993bbf65483742d5d31614 Mon Sep 17 00:00:00 2001 From: thinkphp Date: Wed, 13 Apr 2016 16:15:57 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E5=85=B3=E8=81=94=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E9=A2=84=E8=BD=BD=E5=85=A5=E6=B7=B7=E5=90=88=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E7=9A=84=E9=97=AE=E9=A2=98=20=E5=AF=B9=E5=85=B3?= =?UTF-8?q?=E8=81=94=E6=9F=A5=E8=AF=A2=E4=BD=BF=E7=94=A8=E9=97=AD=E5=8C=85?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E7=9A=84=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- library/think/Model.php | 70 ++++++++---------------------- library/think/db/Driver.php | 85 ++++++++++++++++++++++++++++++++++--- 2 files changed, 95 insertions(+), 60 deletions(-) diff --git a/library/think/Model.php b/library/think/Model.php index edba1496..a3b851d5 100644 --- a/library/think/Model.php +++ b/library/think/Model.php @@ -275,14 +275,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess // 判断关联类型执行查询 switch ($this->relation[0]) { case self::HAS_ONE: - $result = $db->find(); - break; - case self::HAS_MANY: - $result = $db->select(); - break; case self::BELONGS_TO: $result = $db->find(); break; + case self::HAS_MANY: case self::BELONGS_TO_MANY: $result = $db->select(); break; @@ -479,6 +475,18 @@ abstract class Model implements \JsonSerializable, \ArrayAccess return $result; } + /** + * 设置自动完成的字段 + * @access public + * @param array $fields 需要自动完成的字段( 规则通过修改器定义) + * @return $this + */ + public function auto($fields) + { + $this->auto = $fields; + return $this; + } + /** * 设置字段验证 * @access public @@ -738,53 +746,9 @@ abstract class Model implements \JsonSerializable, \ArrayAccess return $this; } - /** - * 使用关联预载入查询 - * @access public - * @param string|array $relations 关联名 - * @return \think\db\Driver - */ - public static function with($with = []) + public function getRelationInfo() { - if (is_string($with)) { - $with = explode(',', $with); - } - $db = self::db(); - if (empty($with)) { - return $db; - } - foreach ($with as $key => &$relation) { - if ($relation instanceof \Closure) { - // 支持闭包查询过滤关联条件 - call_user_func_array($relation, [ & $db]); - $relation = $key; - } - } - - $class = new static(); - - foreach ($with as $key => $name) { - if (is_string($name) && strpos($name, '.')) { - list($name) = explode('.', $name); - } - $i = 0; - $model = $class->$name(); - list($type, $foreignKey, $localKey) = $class->relation; - if (in_array($type, [self::HAS_ONE, self::BELONGS_TO])) { - if (0 == $i) { - $joinName = strtolower(basename(str_replace('\\', '/', get_called_class()))); - $joinTable = Db::name($joinName)->getTableName(); - $db->table($joinTable)->alias($joinName)->field(true, false, $joinTable, $joinName); - } - - // 预载入封装 - $table = $model::getTableName(); - $name = strtolower(basename(str_replace('\\', '/', $model))); - $db->join($table . ' ' . $name, $joinName . '.' . $localKey . '=' . $name . '.' . $foreignKey)->field(true, false, $table, $name); - $i++; - } - } - return $db->with($with)->model(get_called_class()); + return $this->relation; } /** @@ -812,7 +776,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess switch ($type) { case self::HAS_ONE: case self::BELONGS_TO: - foreach ($resultSet as &$result) { + foreach ($resultSet as $result) { // 模型关联组装 $this->modelRelationBuild($model, $relation, $result); } @@ -831,7 +795,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess $data = $this->modelRelationQuery($model, [$foreignKey => ['in', $range]], $relation, $subRelation); // 关联数据封装 - foreach ($resultSet as &$result) { + foreach ($resultSet as $result) { if (isset($data[$result->$localKey])) { $result->__set($relation, $data[$result->$localKey]); } else { diff --git a/library/think/db/Driver.php b/library/think/db/Driver.php index 2501ce75..ce158a96 100644 --- a/library/think/db/Driver.php +++ b/library/think/db/Driver.php @@ -21,6 +21,7 @@ use think\exception\DbBindParamException; use think\exception\PDOException; use think\Loader; use think\Log; +use think\Model; abstract class Driver { @@ -720,6 +721,9 @@ abstract class Driver */ protected function parseWhereExp($field, $op, $condition) { + if (is_string($field) && !empty($this->options['via'])) { + $field = $this->options['via'] . '.' . $field; + } if ($field instanceof \Closure) { $where[] = $field; } elseif (is_null($op) && is_null($condition)) { @@ -869,7 +873,15 @@ abstract class Driver { if (!empty($field)) { if (is_string($field)) { + if (!empty($this->options['via'])) { + $field = $this->options['via'] . '.' . $field; + } $field = empty($order) ? $field : [$field => $order]; + } elseif (!empty($this->options['via'])) { + foreach ($field as $key => $val) { + $field[$this->options['via'] . '.' . $key] = $val; + unset($field[$key]); + } } $this->options['order'] = $field; } @@ -1976,6 +1988,7 @@ abstract class Driver */ public function select($data = []) { + dump($this->options['where']); if (false === $data) { // 用于子查询 不查询只返回SQL $this->options['fetch_sql'] = true; @@ -1983,7 +1996,7 @@ abstract class Driver // AR模式主键条件分析 $this->parsePkWhere($data); } - + dump($this->options['where']); $options = $this->_parseOptions(); $sql = $this->buildSelectSql($options); $resultSet = $this->query($sql, $this->getBindParams(), !empty($options['fetch_sql']) ? true : false, !empty($options['master']) ? true : false, isset($options['fetch_pdo']) ? $options['fetch_pdo'] : false); @@ -2015,8 +2028,7 @@ abstract class Driver } if (!empty($options['with'])) { // 预载入 - $result = new $options['model'](); - return $result->eagerlyResultSet($resultSet, $options['with']); + $resultSet = $result->eagerlyResultSet($resultSet, $options['with']); } } } @@ -2024,17 +2036,76 @@ abstract class Driver } /** - * 设置关联查询预载入 + * 设置关联查询JOIN预查询 * @access public - * @param string $with 关联名称 + * @param string|array $with 关联方法名称 * @return Db */ public function with($with) { + if (is_string($with) && strpos($with, ',')) { + $with = explode(',', $with); + } + + if (empty($with)) { + return $this; + } + + $i = 0; + $currentModel = $this->options['model']; + $class = new $this->options['model']; + foreach ($with as $key => $relation) { + $closure = false; + if ($relation instanceof \Closure) { + // 支持闭包查询过滤关联条件 + $closure = $relation; + $relation = $key; + $with[$key] = $key; + } elseif (is_string($relation) && strpos($relation, '.')) { + $with[$key] = $relation; + list($relation, $subRelation) = explode('.', $relation, 2); + } + + $model = $class->$relation(); + list($type, $foreignKey, $localKey) = $class->getRelationInfo(); + if (in_array($type, [Model::HAS_ONE, Model::BELONGS_TO])) { + if (0 == $i) { + $joinName = strtolower(basename(str_replace('\\', '/', $this->options['model']))); + $joinTable = $this->getTableName(); + $this->table($joinTable)->alias($joinName)->field(true, false, $joinTable, $joinName); + } + // 预载入封装 + + $table = $model::getTableName(); + $name = strtolower(basename(str_replace('\\', '/', $model))); + $this->via($name); + $this->join($table . ' ' . $name, $joinName . '.' . $localKey . '=' . $name . '.' . $foreignKey)->field(true, false, $table, $name); + if ($closure) { + // 执行闭包查询 + call_user_func_array($closure, [ & $this]); + } + $i++; + } + } + $this->via(); + $this->model($currentModel); + dump($with); $this->options['with'] = $with; return $this; } + /** + * 设置当前字段添加的表别名 + * @access public + * @param string $relation 关联名称 + * @return Db + */ + public function via($via = '') + { + $this->options['via'] = $via; + return $this; + } + /** * 设置关联查询 * @access public @@ -2069,7 +2140,7 @@ abstract class Driver } else { $where[$key] = strpos($data, ',') ? ['IN', $data] : $data; } - $this->options['where']['AND'] = $where; + $this->where($where); } elseif (is_array($pk) && is_array($data) && !empty($data)) { // 根据复合主键查询 foreach ($pk as $key) { @@ -2080,7 +2151,7 @@ abstract class Driver throw new Exception('miss complex primary data'); } } - $this->options['where']['AND'] = $where; + $this->where($where); } return; }