LaravelEloquent: 如何从联接的表中获取特定的列

我有两个合并表在雄辩即主题和用户。

主题模型:

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

用户模式:

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

我雄辩的 API 调用如下:

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

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

204658 次浏览

I know, you ask for Eloquent but you can do it with Fluent Query Builder

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

Check out, http://laravel.com/docs/database/eloquent#to-array

You should be able to define which columns you do not want displayed in your api.

Change your model to specify what columns you want selected:

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

And don't forget to include the column you're joining on.

Another option is to make use of the $hidden property on the model to hide the columns you don't want to display. You can define this property on the fly or set defaults on your model.

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

Now the users password will be hidden when you return the JSON response.

You can also set it on the fly in a similar manner.

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

You can supply an array of fields in the get parameter like so:

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

UPDATE (for Laravel 5.2) From the docs, you can do this:

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

In Laravel 4 you can hide certain fields from being returned by adding the following in your model.

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

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

For Laravel >= 5.2

Use the ->pluck() method

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

If you would like to retrieve an array containing the values of a single column, you may use the pluck method


For Laravel <= 5.1

Use the ->lists() method

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

This method will return an array of role titles. You may also specify a custom key column for the returned array:

I know that this is an old question, but if you are building an API, as the author of the question does, use output transformers to perform such tasks.

Transofrmer is a layer between your actual database query result and a controller. It allows to easily control and modify what is going to be output to a user or an API consumer.

I recommend Fractal as a solid foundation of your output transformation layer. You can read the documentation here.

user2317976 has introduced a great static way of selecting related tables' columns.

Here is a dynamic trick I've found so you can get whatever you want when using the model:

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

I just found this trick also works well with load() too. This is very convenient.

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

Make sure you also include target table's key otherwise it won't be able to find it.

Using with pagination

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

If I good understood this what is returned is fine except you want to see only one column. If so this below should be much simpler:

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

This is how i do it

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

First answer by user2317976 did not work for me, i am using laravel 5.1

This Way:

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

Using Model:

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

Using Query Builder:

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

On Laravel 5.5, the cleanest way to do this is:

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

You add a colon and the fields you wish to select separated by a comma and without a space between them.

#You can get selected columns from two or three different tables

$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);