如何在雄辩的子查询函数中使用“ Select()”

时间:2019-11-21 23:46:53

标签: laravel eloquent

我可能没有使用正确的措词,但是我的问题是这样:

我有这个查询

$result = Table_one_model::with(['Table_two' => function($query) use ($thing_id) {
    $query->where('thing_id', $thing_id);
}])
->select('col_one', 'col_two')
->get();

我想向table_two中的select添加更多内容,但是,如果我将其添加到上方现有的select中,如select('col_one', 'col_two', 'col_from_other_table'),则不起作用,并且如果我将select添加到table_two查询中像下面这样也不起作用:

$result = Table_one_model::with(['Table_two' => function($query) use ($thing_id) {
    $query->where('thing_id', $thing_id)->select('col_from_other_table');
}])
->select('col_one', 'col_two')
->get();

在这两种情况下,我都得到结果,但是table_two的结果只是显示为'null'

不选择第二个表,我得到以下结果:

{
  "col_one": 0,
  "col_two": 0,
  "table_one": {
    "id":1,
    "blah":0,
    "col_from_other_table":0
    ...all the contents of table two
  }
}

通过table_two查询中的选择,我得到了:

{
  "col_one": 0,
  "col_two": 0,
  "table_one": {
    null
  }
}

将select与其他select列放在同一位置时,它完全中断并表示该列不存在。

我认为这只是通过table_one.col_from_other_tabletable_one->col_from_other_table之类的方式到达该列的问题,但我不能在select中使用任何一个

有什么想法吗?

3 个答案:

答案 0 :(得分:0)

您无法在with()方法中选择列,而将其移出父级列

尝试使用toSql()getQueryLog()查看原始SQL:

 $result = Table_one_model::with(
            [
                'Table_two' => function($query) use ($thing_id) {
                    $query->where('thing_id', $thing_id);
                }
            ]
        )
            ->select('col_one', 'col_two');
 print_r($result->toSql()); #=> this will return only one table_one raw sql. So that you cannot select table_two column from table_one.

 \DB::enableQueryLog();
 print_r(\DB::getQueryLog()); #=> this will return two raw sql, the one is table_one, and second is table_two. They are splited.

Laravel可以将它们水合在一起。

检查源代码:

    /**
     * Set the relationships that should be eager loaded.
     *
     * @param  mixed  $relations
     * @return $this
     */
    public function with($relations)
    {
        $eagerLoad = $this->parseWithRelations(is_string($relations) ? func_get_args() : $relations);
        $this->eagerLoad = array_merge($this->eagerLoad, $eagerLoad);
        return $this;
    }

返回eagerLoad,我们检查eagerLoad源代码:

    /**
     * Eagerly load the relationship on a set of models.
     *
     * @param  array  $models
     * @param  string  $name
     * @param  \Closure  $constraints
     * @return array
     */
    protected function eagerLoadRelation(array $models, $name, Closure $constraints)
    {
        // First we will "back up" the existing where conditions on the query so we can
        // add our eager constraints. Then we will merge the wheres that were on the
        // query back to it in order that any where conditions might be specified.
        $relation = $this->getRelation($name);
        $relation->addEagerConstraints($models);
        $constraints($relation);
        // Once we have the results, we just match those back up to their parent models
        // using the relationship instance. Then we just return the finished arrays
        // of models which have been eagerly hydrated and are readied for return.
        return $relation->match(
            $relation->initRelation($models, $name),
            $relation->getEager(), $name
        );
    }

它表示一旦获得结果,我们就可以使用关系实例将那些结果与其父模型进行匹配。然后,我们只返回完成的模型数组,这些模型已经急需水化并准备返回。

解决方案:

因此,如果要获取其他表列, 我想我有两种推荐方法:

  1. 使用with()并对其进行循环,将col从子查询获取到父查询。构建所需的数据结构

  2. 尝试使用leftjoin,它可以选择两个表列,并在db之外按table_one分组。构建所需的数据结构。

答案 1 :(得分:0)

还需要根据关系选择ID或外部ID。这就是为什么它抛出空值的原因。例如,假设有两个模型。

Parent: id (pk), name, phone, email
Child:  id (pk), name, phone, email, parent_id (fk)

假设我们只需要获取名称。在Eloquent中看起来像这样:

$children = Child::select('children.name'. 'children.parent_id') /* Need to select children.parent_id */
->with(['parent' => function ($query) {
    $query->select('parents.id', 'parents.name');                /* Need to select parents.id */
}])
->get();

$parents = Parent::select('parents.id', 'parents.name')    /* Need to select parents.id */
->with(['children' => function ($query) {
    $query->select('children.name', 'children.parent_id'); /* Need to select children.parent_id */
}])
->get();

答案 2 :(得分:0)

 'Table_two' => function($query) use ($thing_id) {
                    $query->where('thing_id', $thing_id);
                }

只需在子查询条件中附加查询对象

$query->from('other_table')
    ->selectRaw('col')
    ->where('condition', '>=', val)
    ->where('condition', val);

它将为您生成子查询