Laravel Eloquent: Cómo obtener solo ciertas columnas de tablas unidas

102

Tengo 2 tablas unidas en Eloquent, a saber, temas y usuarios.

modelo de tema:

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

modelo de usuario:

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

Mi llamada a la API de Eloquent se ve a continuación:

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

Lo que devuelve todas las columnas del tema (está bien) y todas las columnas del usuario (no está bien). Solo necesito la columna 'nombre de usuario' del modelo de usuario, ¿cómo puedo limitar la consulta a eso?

ralu
fuente
Estoy trabajando en una tarea similar, ¿puedo saber si estoy usando Responsequé tipo de clase necesito importar?
Agnes Palit

Respuestas:

103

Cambie su modelo para especificar qué columnas desea seleccionar:

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

Y no olvide incluir la columna a la que se une.

usuario2317976
fuente
6
gran respuesta, ¡también el consejo sobre incluir la columna de unión me ahorró un montón de tiempo!
greatwitenorth
¿Qué sucede si en algunos lugares solo necesito identificación en lugar de identificación y nombre de usuario? ¿Aún tienes que seleccionar ambos?
Darius.V
Hola, ¿la función de selección tiene la misma función en el generador de consultas de modelos?
Gokigooooks
4
No creo que sea un buen enfoque. Será difícil codificar los nombres de las columnas. Todos los lugares devolverán solo estas columnas. En alguna otra API, es posible que necesite algunas columnas más, por lo que no funcionará aquí. Creo que usar QueryBuilder es la opción aquí.
Aman Sura
2
Este es un enfoque dramático, ya que ocurrirá cada vez que realice la llamada en el futuro. Creo que la respuesta de Sajjad Ashraf es la que le interesará a la mayoría de la gente.
MMMTroy
37

Para Laravel> = 5.2

Utilice el método -> pluck ()

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

Si desea recuperar una matriz que contiene los valores de una sola columna, puede utilizar el método de extracción


Para Laravel <= 5.1

Utilice el método -> lists ()

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

Este método devolverá una serie de títulos de roles. También puede especificar una columna de clave personalizada para la matriz devuelta:

Javi Stolz
fuente
2
Esta no es realmente una respuesta a la pregunta (que se refería específicamente a uniones / relaciones).
2017
30

Puede proporcionar una matriz de campos en el parámetro get de la siguiente manera:

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

ACTUALIZAR (para Laravel 5.2) Desde los documentos , puede hacer esto:

$response = DB::table('themes')
    ->select('themes.*', 'users.username')
    ->join('users', 'users.id', '=', 'themes.user_id')
    ->get();
Melvin
fuente
2
Intenté esto y muestra un error SQLSTATE[42S22]: Column not foundy su SQL no incluye la tabla en with. El sql que aparece en el error es "SELECT fk_table.column1 FROM main_table".
Michel Ayres
1
Es "users.username" (no "user.username"). El código de la respuesta funcionará si los nombres de las tablas y columnas coinciden con su base de datos real. Esa es la desventaja de esta solución, está construyendo una consulta SQL en lugar de usar Eloquent, por lo que los nombres deben coincidir con las tablas y columnas de su base de datos.
2017
22

Lo sé, pides Eloquent pero puedes hacerlo con Fluent Query Builder

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

Asi es como lo hago

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

La primera respuesta del usuario 2317976 no funcionó para mí, estoy usando laravel 5.1

Sajjad Ashraf
fuente
2
Respuesta actualizada = ¡útil!
thesunneversets
Gracias. Funciona bien para mí. Debo agregar la clave externa en la declaración de selección como lo hizo con 'id', de lo contrario, devuelve nulo.
Iman Sedighi
Sin embargo, esto todavía recupera un campo "pivote" para cada resultado, que contiene ambos identificadores (post_id y category_id), ¿verdad? ¿Cómo puedo librarme de él?
mayid
1
@mayid puede intentar agregar pivota $ matriz oculta del modelo de publicaciónprotected $hidden = ['pivot']
Sajjad Ashraf
Esta es la mejor solución (asumiendo que estás usando una versión bastante moderna de Laravel)
orrd
11

Otra opción es hacer uso de la $hiddenpropiedad del modelo para ocultar las columnas que no desea mostrar. Puede definir esta propiedad sobre la marcha o establecer valores predeterminados en su modelo.

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

Ahora, la contraseña de los usuarios se ocultará cuando devuelva la respuesta JSON.

También puede configurarlo sobre la marcha de manera similar.

User::$hidden = array('password');
Jason Lewis
fuente
2
en Laravel 4.2 obtengo 'No se puede acceder a la propiedad protegida User :: $ hidden' cuando intento configurar esto dinámicamente.
mtmacdonald
1
no debería serlo static.
StackOverflowed
@StackOverflowed, supongo que no se dio cuenta de la antigüedad de esta pregunta / respuesta y de que estaba relacionada con Laravel 3.
Jason Lewis
10

Usar con paginación

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

user2317976 ha introducido una excelente forma estática de seleccionar columnas de tablas relacionadas.

Aquí hay un truco dinámico que encontré para que pueda obtener lo que quiera cuando use el modelo:

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

Encontré que este truco también funciona bien con load (). Esto es muy conveniente.

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

Asegúrese de incluir también la clave de la tabla de destino, de lo contrario, no podrá encontrarla.

KinoP
fuente
6

De esta manera:

Post::with(array('user'=>function($query){
    $query->select('id','username');
}))->get();
Especificaciones
fuente
Explique siempre su respuesta.
Rohit Gupta
Tuve un problema similar, ¡esta es la forma más inteligente hasta ahora! ¡Esta respuesta está subestimada!
eldblz
Esta es la misma respuesta que ya presentó anteriormente Sajjad Ashraf.
2017
5

Sé que esta es una pregunta antigua, pero si está creando una API, como lo hace el autor de la pregunta, use transformadores de salida para realizar tales tareas.

Transofrmer es una capa entre el resultado real de la consulta de la base de datos y un controlador. Permite controlar y modificar fácilmente lo que se enviará a un usuario o consumidor de API.

Recomiendo Fractal como una base sólida de su capa de transformación de salida. Puedes leer la documentación aquí .

Armen Markossyan
fuente
4

En Laravel 5.5, la forma más limpia de hacer esto es:

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

Agrega dos puntos y los campos que desea seleccionar separados por una coma y sin un espacio entre ellos.

JoeGalind
fuente
¿Sabe cómo podemos obtener una columna específica de la tabla relacionada cuando usamos la paginación?
Daniyal Nasir
2

Usando el modelo:

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

Usando Query Builder:

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

Si entendí bien esto, lo que se devuelve está bien, excepto que solo desea ver una columna. Si es así, esto a continuación debería ser mucho más simple:

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