【问题标题】:Laravel Eloquent: How to get only certain columns from joined tablesLaravel Eloquent:如何从连接表中仅获取某些列
【发布时间】:2013-01-21 12:45:02
【问题描述】:

我在 Eloquent 中有 2 个连接表,即主题和用户。

主题模型:

public function user() {
  return $this->belongs_to('User');
}

用户模型:

public function themes() {
  return $this->has_many('Theme');
}

我的 Eloquent api 调用如下所示:

return Response::eloquent(Theme::with('user')->get());

返回主题的所有列(很好),以及用户的所有列(不好)。我只需要用户模型中的“用户名”列,我该如何限制查询?

【问题讨论】:

  • 我正在做类似的任务,请问我是否使用Response 需要导入什么样的类?

标签: php laravel eloquent


【解决方案1】:

#您可以从两个或三个不同的表中获取选定的列

$users= DB::Table('profiles')->select('users.name','users.status','users.avatar','users.phone','profiles.user_id','profiles.full_name','profiles.email','profiles.experience','profiles.gender','profiles.profession','profiles.dob',)->join('users','profiles.user_id','=','users.id')
            ->paginate(10);

【讨论】:

    【解决方案2】:

    在 Laravel 5.5 上,最简洁的方法是:

    Theme::with('user:userid,name,address')->get()
    

    您添加一个冒号和您希望选择的字段,用逗号分隔,它们之间没有空格。

    【讨论】:

    • 你知道在使用分页时如何获取相关表的特定列吗?
    • @Kamlesh ,如果你没有在 Theme 表上指定 select() 语句,你会得到所有的字段。
    • 感谢您的回复。但是我认为您没有得到我的要求,即“我想要第一个表的所有字段,并且还想要获取连接表的某些字段”。根据我的最后评论。再次感谢。
    • 所以我猜你想要两张桌子?然后是这样的: Theme::with(['user:userid,name,address', 'table2'])->get() 这将从主题表中获取所有字段,从 table2 中获取所有字段以及用户的某些字段
    【解决方案3】:

    我知道这是一个老问题,但如果您正在构建 API,就像问题的作者所做的那样,请使用输出转换器来执行此类任务。

    Transofrmer 是实际数据库查询结果和控制器之间的一层。它允许轻松控制和修改将要输出给用户或 API 使用者的内容。

    我推荐Fractal 作为输出转换层的坚实基础。您可以阅读文档here

    【讨论】:

      【解决方案4】:

      使用模型:

      Model::where('column','value')->get(['column1','column2','column3',...]);
      

      使用查询生成器:

      DB::table('table_name')->where('column','value')->get(['column1','column2','column3',...]);
      

      【讨论】:

        【解决方案5】:

        对于 Laravel >= 5.2

        使用->pluck() 方法

        $roles = DB::table('roles')->pluck('title');
        

        如果你想检索一个包含单列值的数组,你可以使用 pluck 方法


        对于 Laravel

        使用->lists() 方法

        $roles = DB::table('roles')->lists('title');
        

        此方法将返回一个角色标题数组。您还可以为返回的数组指定自定义键列:

        【讨论】:

        • 这并不是问题的真正答案(特别是关于联接/关系)。
        【解决方案6】:

        这条路:

        Post::with(array('user'=>function($query){
            $query->select('id','username');
        }))->get();
        

        【讨论】:

        • 请始终解释您的答案。
        • 遇到了类似的问题,这是迄今为止最聪明的方法!这个答案被低估了!
        • 这与 Sajjad Ashraf 之前已经提交的答案相同。
        【解决方案7】:

        您可以像这样在 get 参数中提供一组字段:

        return Response::eloquent(Theme::with('user')->get(array('user.username'));
        

        更新(对于 Laravel 5.2) 从docs,您可以这样做:

        $response = DB::table('themes')
            ->select('themes.*', 'users.username')
            ->join('users', 'users.id', '=', 'themes.user_id')
            ->get();
        

        【讨论】:

        • 我试过这个,它显示错误SQLSTATE[42S22]: Column not found,它的 SQL 不包括with 中的表。它出现在错误上的sql是“SELECT fk_table.column1 FROM main_table”。
        • 它是“users.username”(不是“user.username”)。如果您的表名和列名与您的实际数据库匹配,则答案中的代码将起作用。这是这个解决方案的缺点,它是构建一个 SQL 查询而不是使用 Eloquent,因此名称必须与您的实际数据库表和列相匹配。
        【解决方案8】:

        我就是这样做的

        $posts = Post::with(['category' => function($query){
                $query->select('id', 'name');
              }])->get();
        

        user2317976 的第一个答案对我不起作用,我使用的是 laravel 5.1

        【讨论】:

        • 最新答案 = 有用!
        • 谢谢。这对我来说可以。我必须像使用 'id' 一样在 select 语句中添加外键,否则返回 null。
        • 但是,这仍然会为每个结果检索一个“pivot”字段,其中包含两个 id(post_id 和 category_id)对吧?我怎样才能搭上它?
        • @mayid 您可以尝试将pivot 添加到 Post Model protected $hidden = ['pivot'] 的 $hidden 数组中
        • 这是最好的解决方案(假设你使用的是相当现代的 Laravel 版本)
        【解决方案9】:

        如果我很好理解这一点,返回的内容很好,除非您只想查看一列。如果是这样,下面应该更简单:

        return Response::eloquent(Theme::with('user')->get(['username']));
        

        【讨论】:

          【解决方案10】:

          与分页一起使用

          $data = DB::table('themes')
          ->join('users', 'users.id', '=', 'themes.user_id')
          ->select('themes.*', 'users.username')
          ->paginate(6);
          

          【讨论】:

            【解决方案11】:

            更改模型以指定要选择的列:

            public function user() {
              return $this->belongs_to('User')->select(array('id', 'username'));
            }
            

            别忘了包括您要加入的列。

            【讨论】:

            • 很好的答案,关于加入列的提示也为我节省了大量时间!
            • 如果在某些地方我只需要 id 而不是 id 和用户名怎么办?还是要两个都选?
            • 嗨,模型查询构建器中的选择功能是否具有相同的功能?
            • 我认为这不是一个好方法。这将是对列名进行硬编码。所有地点将仅返回这些列。在其他一些 api 中,我可能需要更多的列,所以这不会在这里工作。我认为使用 QueryBuilder 是这里的选择。
            • 这是一种戏剧性的方法,因为每次您拨打电话时都会发生这种情况。我相信 Sajjad Ashraf 的回答是大多数人都会感兴趣的。
            【解决方案12】:

            user2317976 引入了一种很棒的静态方式来选择相关表的列。

            这是我发现的一个动态技巧,因此您可以在使用模型时获得任何想要的东西:

            return Response::eloquent(Theme::with(array('user' => function ($q) {
                $q->addSelect(array('id','username'))
            }))->get();
            

            我刚刚发现这个技巧也适用于 load()。这很方便。

            $queriedTheme->load(array('user'=>function($q){$q->addSelect(..)});
            

            确保您还包含目标表的键,否则将无法找到它。

            【讨论】:

              【解决方案13】:

              我知道,您要求 Eloquent,但您可以使用 Fluent Query Builder 来完成

              $data = DB::table('themes')
                  ->join('users', 'users.id', '=', 'themes.user_id')
                  ->get(array('themes.*', 'users.username'));
              

              【讨论】:

                【解决方案14】:

                在 Laravel 4 中,您可以通过在模型中添加以下内容来隐藏某些字段以防止返回。

                protected $hidden = array('password','secret_field');
                

                http://laravel.com/docs/eloquent#converting-to-arrays-or-json

                【讨论】:

                  【解决方案15】:

                  另一种选择是利用模型上的$hidden 属性来隐藏您不想显示的列。您可以动态定义此属性或在模型上设置默认值。

                  public static $hidden = array('password');
                  

                  现在,当您返回 JSON 响应时,用户密码将被隐藏。

                  您也可以以类似的方式即时设置它。

                  User::$hidden = array('password');
                  

                  【讨论】:

                  • 在 Laravel 4.2 中尝试动态设置时,我得到“无法访问受保护的属性 User::$hidden”。
                  • 不应该是static
                  • @StackOverflowed,我认为你没有注意到这个问题/答案有多老以及它与 Laravel 3 相关。
                  【解决方案16】:

                  退房,http://laravel.com/docs/database/eloquent#to-array

                  您应该能够定义不希望在 api 中显示的列。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2018-01-08
                    • 1970-01-01
                    • 2021-10-03
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-10-28
                    • 2013-05-17
                    相关资源
                    最近更新 更多