public function with($with)
{
if (empty($with)) {
return $this;
}
if (is_string($with)) {
$with = explode(',', $with);
}
$i = 0;
$currentModel = $this->model;
/** @var Model $class */
$class = new $currentModel();
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);
}
/** @var Relation $model */
$model = $class->{$relation}();
$info = $model->getRelationInfo();
if (in_array($info['type'], [Relation::HAS_ONE, Relation::BELONGS_TO])) {
if (0 == $i) {
$name = Loader::parseName(basename(str_replace('\\', '/', $currentModel)));
$table = $this->getTable();
$alias = isset($info['alias'][$name]) ? $info['alias'][$name] : $name;
$this->table([$table => $alias]);
if (isset($this->options['field'])) {
$field = $this->options['field'];
unset($this->options['field']);
} else {
$field = true;
}
$this->field($field, false, $table, $alias);
}
// 预载入封装
$joinTable = $model->getTable();
$joinName = Loader::parseName(basename(str_replace('\\', '/', $info['model'])));
$joinAlias = isset($info['alias'][$joinName]) ? $info['alias'][$joinName] : $relation;
$this->via($joinAlias);
if (Relation::HAS_ONE == $info['type']) {
$this->join($joinTable . ' ' . $joinAlias, $alias . '.' . $info['localKey'] . '=' . $joinAlias . '.' . $info['foreignKey'], $info['joinType']);
} else {
$this->join($joinTable . ' ' . $joinAlias, $alias . '.' . $info['foreignKey'] . '=' . $joinAlias . '.' . $info['localKey'], $info['joinType']);
}
if ($closure) {
// 执行闭包查询
call_user_func_array($closure, [&$this]);
//指定获取关联的字段
//需要在 回调中 调方法 withField 方法,如
// $query->where(['id'=>1])->withField('id,name');
if (!empty($this->options['with_field'])) {
$field = $this->options['with_field'];
unset($this->options['with_field']);
}
}
$this->field($field, false, $joinTable, $joinAlias, $relation . '__');
$i++;
} elseif ($closure) {
$with[$key] = $closure;
}
}
$this->via();
$this->options['with'] = $with;
return $this;
}