mirror of
https://gitee.com/fastadminnet/framework.git
synced 2026-07-07 23:22:48 +08:00
Model类支持关联查询预载入功能 增加__toString方法 Db类增加relation和with方法 修正Model一处BUG
This commit is contained in:
@@ -259,33 +259,40 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} elseif (is_null($value) && method_exists($this, $name)) {
|
} elseif (is_null($value) && method_exists($this, $name)) {
|
||||||
// 执行关联定义方法
|
// 获取关联数据
|
||||||
$db = $this->$name();
|
return $this->getRelation($name);
|
||||||
// 判断关联类型执行查询
|
|
||||||
switch ($this->relation) {
|
|
||||||
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::BELONGS_TO_MANY:
|
|
||||||
$result = $db->select();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// 直接返回
|
|
||||||
$result = $db;
|
|
||||||
}
|
|
||||||
// 避免影响其它操作方法
|
|
||||||
$this->relation = null;
|
|
||||||
return $result;
|
|
||||||
}
|
}
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取关联数据
|
||||||
|
protected function getRelation($relation)
|
||||||
|
{
|
||||||
|
// 执行关联定义方法
|
||||||
|
$db = $this->$relation();
|
||||||
|
// 判断关联类型执行查询
|
||||||
|
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::BELONGS_TO_MANY:
|
||||||
|
$result = $db->select();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// 直接返回
|
||||||
|
$result = $db;
|
||||||
|
}
|
||||||
|
// 避免影响其它操作方法
|
||||||
|
$this->relation = [];
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检测数据对象的值
|
* 检测数据对象的值
|
||||||
* @access public
|
* @access public
|
||||||
@@ -688,14 +695,71 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
return $model;
|
return $model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查询当前模型的关联数据
|
||||||
|
public function relation($relations)
|
||||||
|
{
|
||||||
|
if (is_string($relations)) {
|
||||||
|
$relations = explode(',', $relations);
|
||||||
|
}
|
||||||
|
foreach ($relations as $relation) {
|
||||||
|
$this->data[$relation] = $this->getRelation($relation);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预载入关联查询
|
||||||
|
public function eagerly($resultSet, $relation)
|
||||||
|
{
|
||||||
|
$relations = explode(',', $relation);
|
||||||
|
|
||||||
|
// 获取关联外键列表
|
||||||
|
foreach ($relations as $relation) {
|
||||||
|
$range = [];
|
||||||
|
$data = [];
|
||||||
|
$model = $this->$relation();
|
||||||
|
list($type, $foreignKey, $localKey) = $this->relation;
|
||||||
|
foreach ($resultSet as $result) {
|
||||||
|
$range[] = $result->$localKey;
|
||||||
|
}
|
||||||
|
$list = $model::where($foreignKey, 'in', $range)->select();
|
||||||
|
switch ($type) {
|
||||||
|
case self::HAS_ONE:
|
||||||
|
case self::BELONGS_TO:
|
||||||
|
foreach ($list as $set) {
|
||||||
|
$data[$set->$foreignKey] = $set;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case self::HAS_MANY:
|
||||||
|
case self::BELONGS_TO_MANY:
|
||||||
|
foreach ($list as $set) {
|
||||||
|
$data[$set->$foreignKey][] = $set;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
foreach ($resultSet as &$result) {
|
||||||
|
if (isset($data[$result->$localKey])) {
|
||||||
|
$result->$relation = $data[$result->$localKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->relation = [];
|
||||||
|
}
|
||||||
|
return $resultSet;
|
||||||
|
}
|
||||||
|
|
||||||
// HAS ONE
|
// HAS ONE
|
||||||
public function hasOne($model, $foreignKey = '', $localKey = '')
|
public function hasOne($model, $foreignKey = '', $localKey = '')
|
||||||
{
|
{
|
||||||
$model = $this->parseModel($model);
|
$model = $this->parseModel($model);
|
||||||
$localKey = $localKey ?: $this->pk;
|
$localKey = $localKey ?: $this->pk;
|
||||||
$foreignKey = $foreignKey ?: Loader::parseName($this->name) . '_id';
|
$foreignKey = $foreignKey ?: Loader::parseName($this->name) . '_id';
|
||||||
$this->relation = self::HAS_ONE;
|
$this->relation = [self::HAS_ONE, $foreignKey, $localKey];
|
||||||
return $model::where($foreignKey, $this->data[$localKey]);
|
if (isset($this->data[$localKey])) {
|
||||||
|
// 关联查询封装
|
||||||
|
return $model::where($foreignKey, $this->data[$localKey]);
|
||||||
|
} else {
|
||||||
|
// 预载入封装
|
||||||
|
return $model;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BELONGS TO
|
// BELONGS TO
|
||||||
@@ -704,8 +768,13 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
$model = $this->parseModel($model);
|
$model = $this->parseModel($model);
|
||||||
$foreignKey = $foreignKey ?: $this->pk;
|
$foreignKey = $foreignKey ?: $this->pk;
|
||||||
$localKey = $localKey ?: Loader::parseName(basename(str_replace('\\', '/', $model))) . '_id';
|
$localKey = $localKey ?: Loader::parseName(basename(str_replace('\\', '/', $model))) . '_id';
|
||||||
$this->relation = self::BELONGS_TO;
|
$this->relation = [self::BELONGS_TO, $foreignKey, $localKey];
|
||||||
return $model::where($foreignKey, $this->data[$localKey]);
|
if (isset($this->data[$localKey])) {
|
||||||
|
// 关联查询封装
|
||||||
|
return $model::where($foreignKey, $this->data[$localKey]);
|
||||||
|
} else {
|
||||||
|
return $model;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HAS MANY
|
// HAS MANY
|
||||||
@@ -714,8 +783,14 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
$model = $this->parseModel($model);
|
$model = $this->parseModel($model);
|
||||||
$localKey = $localKey ?: $this->pk;
|
$localKey = $localKey ?: $this->pk;
|
||||||
$foreignKey = $foreignKey ?: Loader::parseName($this->name) . '_id';
|
$foreignKey = $foreignKey ?: Loader::parseName($this->name) . '_id';
|
||||||
$this->relation = self::HAS_MANY;
|
$this->relation = [self::HAS_MANY, $foreignKey, $localKey];
|
||||||
return $model::where($foreignKey, $this->data[$localKey]);
|
|
||||||
|
if (isset($this->data[$localKey])) {
|
||||||
|
// 关联查询封装
|
||||||
|
return $model::where($foreignKey, $this->data[$localKey]);
|
||||||
|
} else {
|
||||||
|
return $model;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BELONGS TO MANY
|
// BELONGS TO MANY
|
||||||
@@ -724,8 +799,14 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
$model = $this->parseModel($model);
|
$model = $this->parseModel($model);
|
||||||
$foreignKey = $foreignKey ?: $this->pk;
|
$foreignKey = $foreignKey ?: $this->pk;
|
||||||
$localKey = $localKey ?: Loader::parseName(basename(str_replace('\\', '/', $model))) . '_id';
|
$localKey = $localKey ?: Loader::parseName(basename(str_replace('\\', '/', $model))) . '_id';
|
||||||
$this->relation = self::BELONGS_TO_MANY;
|
$this->relation = [self::BELONGS_TO_MANY, $foreignKey, $localKey];
|
||||||
return $model::where($foreignKey, $this->data[$localKey]);
|
|
||||||
|
if (isset($this->data[$localKey])) {
|
||||||
|
// 关联查询封装
|
||||||
|
return $model::where($foreignKey, $this->data[$localKey]);
|
||||||
|
} else {
|
||||||
|
return $model;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -736,14 +817,17 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
protected static function db()
|
protected static function db()
|
||||||
{
|
{
|
||||||
$model = get_called_class();
|
$model = get_called_class();
|
||||||
$name = basename(str_replace('\\', '/', $model));
|
|
||||||
if (!isset(self::$links[$model])) {
|
if (!isset(self::$links[$model])) {
|
||||||
self::$links[$model] = Db::connect(static::$connection);
|
self::$links[$model] = Db::connect(static::$connection);
|
||||||
self::$links[$model]->name($name);
|
|
||||||
if (isset(static::$tableName)) {
|
|
||||||
self::$links[$model]->setTable(static::$tableName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (isset(static::$tableName)) {
|
||||||
|
self::$links[$model]->setTable(static::$tableName);
|
||||||
|
} else {
|
||||||
|
$name = basename(str_replace('\\', '/', $model));
|
||||||
|
self::$links[$model]->name($name);
|
||||||
|
}
|
||||||
|
|
||||||
// 设置当前模型 确保查询返回模型对象
|
// 设置当前模型 确保查询返回模型对象
|
||||||
self::$links[$model]->model($model);
|
self::$links[$model]->model($model);
|
||||||
// 返回当前数据库对象
|
// 返回当前数据库对象
|
||||||
@@ -769,6 +853,11 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
|
|||||||
return call_user_func_array([self::db(), $method], $params);
|
return call_user_func_array([self::db(), $method], $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return json_encode($this->data);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解序列化后处理
|
* 解序列化后处理
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1190,12 +1190,24 @@ abstract class Driver
|
|||||||
return $tableName;
|
return $tableName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置当前name
|
||||||
|
* @access public
|
||||||
|
* @param string $name
|
||||||
|
* @return Db
|
||||||
|
*/
|
||||||
public function name($name)
|
public function name($name)
|
||||||
{
|
{
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 得到完整的数据表名
|
||||||
|
* @access public
|
||||||
|
* @param array $options 表达式参数
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function options(array $options)
|
public function options(array $options)
|
||||||
{
|
{
|
||||||
$this->options = $options;
|
$this->options = $options;
|
||||||
@@ -1927,19 +1939,53 @@ abstract class Driver
|
|||||||
|
|
||||||
// 数据列表读取后的处理
|
// 数据列表读取后的处理
|
||||||
if (!empty($options['model'])) {
|
if (!empty($options['model'])) {
|
||||||
|
|
||||||
foreach ($resultSet as $key => $result) {
|
foreach ($resultSet as $key => $result) {
|
||||||
if (!empty($options['model'])) {
|
if (!empty($options['model'])) {
|
||||||
// 返回模型对象
|
// 返回模型对象
|
||||||
$result = new $options['model']($result);
|
$result = new $options['model']($result);
|
||||||
$result->isUpdate(true);
|
$result->isUpdate(true);
|
||||||
|
// 关联查询
|
||||||
|
if (!empty($options['relation'])) {
|
||||||
|
$result->relation($options['relation']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$resultSet[$key] = $result;
|
$resultSet[$key] = $result;
|
||||||
}
|
}
|
||||||
|
if (!empty($options['with'])) {
|
||||||
|
// 预载入
|
||||||
|
$result = new $options['model']();
|
||||||
|
return $result->eagerly($resultSet, $options['with']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $resultSet;
|
return $resultSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置关联查询预载入
|
||||||
|
* @access public
|
||||||
|
* @param string $with 关联名称
|
||||||
|
* @return Db
|
||||||
|
*/
|
||||||
|
public function with($with)
|
||||||
|
{
|
||||||
|
$this->options['with'] = $with;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置关联查询
|
||||||
|
* @access public
|
||||||
|
* @param string $relation 关联名称
|
||||||
|
* @return Db
|
||||||
|
*/
|
||||||
|
public function relation($relation)
|
||||||
|
{
|
||||||
|
$this->options['relation'] = $relation;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 把主键值转换为查询条件 支持复合主键
|
* 把主键值转换为查询条件 支持复合主键
|
||||||
* @access public
|
* @access public
|
||||||
@@ -2006,6 +2052,10 @@ abstract class Driver
|
|||||||
// 返回模型对象
|
// 返回模型对象
|
||||||
$data = new $options['model']($data);
|
$data = new $options['model']($data);
|
||||||
$data->isUpdate(true);
|
$data->isUpdate(true);
|
||||||
|
// 关联查询
|
||||||
|
if (!empty($options['relation'])) {
|
||||||
|
$data->relation($options['relation']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$data = false;
|
$data = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user