Obtenga columnas específicas utilizando la función "Con ()" en Laravel Eloquent


197

Tengo dos mesas Usery Post. Uno Userpuede tener muchos postsy uno postpertenece a uno solo user.

En mi Usermodelo tengo una hasManyrelación ...

public function post(){
    return $this->hasmany('post');
}

Y en mi postmodelo tengo una belongsTorelación ...

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

Ahora quiero unir estas dos tablas usando Eloquent with()pero quiero columnas específicas de la segunda tabla. Sé que puedo usar el generador de consultas, pero no quiero hacerlo.

Cuando en el Postmodelo escribo ...

public function getAllPosts() {
    return Post::with('user')->get();
}

Ejecuta las siguientes consultas ...

select * from `posts`
select * from `users` where `users`.`id` in (<1>, <2>)

Pero lo que quiero es ...

select * from `posts`
select id,username from `users` where `users`.`id` in (<1>, <2>)

Cuando uso ...

Post::with('user')->get(array('columns'....));

Solo devuelve la columna de la primera tabla. Quiero columnas específicas usando with()de la segunda tabla. ¿Cómo puedo hacer eso?

Respuestas:


347

Bueno, encontré la solución. Se puede hacer uno pasando una closurefunción with()como segundo índice de matriz como

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

Solo seleccionará idy usernamede otra tabla. Espero que esto ayude a otros.


Recuerde que la clave primaria (id en este caso) debe ser el primer parámetro en $ query-> select () para recuperar realmente los resultados necesarios. *


1
Eso es extraño, no pude hacer que esto funcione. Tan pronto como agregué $query->select('id','username');, estaba obteniendoTrying to get property of non-object
user1669496 el

55
¡Extraño! Todavía devuelve todos los campos del usuario. @AwaisQarni
justin

2
Gracias por compartir esto. ¿Dónde descubriste esta posibilidad? No encontré esto en los documentos de Laravel.
Symen Timmermans

80
Para aquellos que ven esto, recuerden que la clave primaria ( iden este caso) es necesaria $query->select()para recuperar los resultados necesarios. Omití esto en mi código y no pude entender por qué no encontraría ningún resultado. ¡Tonto de mí! Espero que esto ayude a cualquier otra persona con el mismo problema
Azirius

44
genial, solo necesito agregar una clave foránea, aquí su post_id de lo contrario el resultado estará vacío. Mencionar la clave externa es importante aquí. Gracias :)
Hashaam Ahmed

102

Puedes hacerlo así desde Laravel 5.5:

Post::with('user:id,username')->get();

Cuide el idcampo y foreign keyscomo se indica en los documentos :

Al usar esta función, siempre debe incluir la columna de identificación y las columnas de clave externa relevantes en la lista de columnas que desea recuperar.

Por ejemplo, si el usuario pertenece a un equipo y tiene una team_idcolumna de clave externa, entonces $post->user->teamestá vacía si no especifica team_id

Post::with('user:id,username,team_id')->get();

13
No olvide incluir la clave foránea (suponiendo que sea post_id aquí) para resolver la relación, de lo contrario obtendrá resultados vacíos para su relación.
Hashaam Ahmed

2
Esta realmente debería ser la respuesta seleccionada. Funciona como un encanto :)
Graham

@ Adam, esto restringirá las columnas en la tabla secundaria, ¿cómo puedo restringir las columnas de la tabla Tabla principal junto con la tabla secundaria?
Sodio

@GauravGenius todo lo que desea restringir de las pertenencias de los parant en el get()métodoPost::with('user:id,username')->get(['age', 'color']);
Adam

82

En su Postmodelo

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

El crédito original va a Laravel Eager Loading: carga solo columnas específicas


14
Pero esta relación lo hará como codificado. En todas las condiciones, siempre me devolverá estos dos campos. Puede suceder que necesite más campos en algunas otras situaciones
Awais Qarni

Luego debe usar el generador de consultas.
user1669496

55
Esta debería ser la respuesta aceptada. Esta es la forma correcta de hacerlo.
BugHunterUK

1
¿Hay alguna manera de hacer esto en la versión Laravel 5.3? Creo que lo cambiaron ... otra vez ... y ahora vuelve nulo cuando intento con este enfoque
Andre F.

Ha pasado un tiempo, pero puedes agregar un $fieldsparámetro.
JordyvD

69

Al ir hacia el otro lado (hasMany):

User::with(array('post'=>function($query){
    $query->select('id','user_id');
}))->get();

No olvide incluir la clave externa (suponiendo que sea user_id en este ejemplo) para resolver la relación, de lo contrario obtendrá cero resultados para su relación.


66
Sí, exactamente, "No te olvides de incluir la clave foránea (suponiendo que sea user_id en este ejemplo)"
aqingsao

debe incluir una columna que defina su relación en los campos seleccionados, en este caso user_id
alimfazeli

Buena captura hermano.
Shahrukh Anwar

asombroso hermano, ese uso de clave externa es realmente importante, por suerte te vi y de lo contrario me habría rascado la cabeza durante horas jajaja. ¡Gracias hombre!
Hashaam Ahmed

34

En Laravel 5.7 puedes llamar a un campo específico como este

$users = App\Book::with('author:id,name')->get();

Es importante agregar un foreign_keycampo en la selección.


11
no se olvide de añadir el extranjero clave de campo
hendra1

2
No olvide notar el comentario de @ hendra1, todos los campos de clave externa también son necesarios junto con la clave primaria, de lo contrario obtendrá una colección en blanco. Amigo me salvó el tiempo. Gracias
Rajesh Vishnani

14

En su Postmodelo:

public function userWithName()
{
    return $this->belongsTo('User')->select(array('id', 'first_name', 'last_name'));
}

Ahora puedes usar $post->userWithName


2
De Verdad? Para mí esto simplemente no devuelve nada, es decir, ¿lo rompe?
Sjwdavies

12

Si desea obtener columnas específicas usando with()laravel elocuente, puede usar el código que se muestra a continuación, que originalmente fue respondido por @Adam en su respuesta aquí en respuesta a esta misma pregunta:

Post::with('user:id,username')->get();

Así que lo he usado en mi código pero me estaba dando un error 1052: Column 'id' in field list is ambiguous, así que si ustedes también enfrentan el mismo problema

Luego, para resolverlo, debe especificar el nombre de la tabla antes de la columna de identificación en el with()método como se muestra a continuación :

Post::with('user:user.id,username')->get();

¡Esto devuelve nulo para mí pero no sabía que esto era posible antes! Ok, publiqué prematuramente pero encontré un resultado. Para usar este método (se ve mucho más limpio) debe incluir el enlace de la relación, por ejemplo, la columna ID al extraer los datos. Sin este especificador, obtienes un retorno nulo.
Adsy2010

sí @ Adsy2010, para obtener datos de relaciones relacionadas, también debe obtener la columna de identificación o la clave principal o la identificación que sea responsable de esa relación.
Haritsinh Gohil

10

Encontré este problema pero con una segunda capa de objetos relacionados. La respuesta de @Awais Qarni se mantiene con la inclusión de la clave externa apropiada en la instrucción de selección anidada. Así como se requiere una identificación en la primera instrucción select anidada para hacer referencia al modelo relacionado, la clave externa se requiere para hacer referencia al segundo grado de modelos relacionados; en este ejemplo el modelo de empresa.

Post::with(['user' => function ($query) {
        $query->select('id','company_id', 'username');
    }, 'user.company' => function ($query) {
        $query->select('id', 'name');
    }])->get();

Además, si desea seleccionar columnas específicas del modelo de publicación, deberá incluir la columna user_id en la instrucción select para hacer referencia a ella.

Post::with(['user' => function ($query) {
        $query->select('id', 'username');
    }])
    ->select('title', 'content', 'user_id')
    ->get();

4

Tenga en cuenta que si solo necesita una columna de la tabla, entonces usar 'listas' es bastante bueno. En mi caso, estoy recuperando los artículos favoritos de un usuario, pero solo quiero la identificación del artículo:

$favourites = $user->favourites->lists('id');

Devuelve una matriz de identificadores, por ejemplo:

Array
(
    [0] => 3
    [1] => 7
    [2] => 8
)

¡devuelve una colección!
Giovanni Far

si quieres una matriz entonces llama toArray()!!! $user->favourites->lists('id')->toArray();
Giovanni Far

La consulta aún obtendrá las otras columnas porque el método list () solo cambia la matriz de resultados, por lo que si solo necesita el 'id' de esa tabla, es posible que desee especificarlo en la consulta. Siempre es un buen hábito tener en cuenta el rendimiento al hacer consultas. ¡Disfruta codificando!
Ervin Llojku

-1 $user->favouritesserá devuelto Collectioncon todos los campos seleccionados. El uso correcto es: $user->favourites()->lists('id').
Wallace Maxters

Seleccionar todo para usar luego el filtrado de PHP es una mala idea. Es mejor usar solo los campos necesarios en la consulta. Es importante saber la diferencia entre Query\Builder::listsmétodo y Collection::listsmétodo.
Wallace Maxters

1

También puede especificar columnas en el modelo relacionado al momento de acceder a él.

Post::first()->user()->get(['columns....']);


0

Ahora puede usar el pluckmétodo en una Collectioninstancia:

Esto devolverá solo el uuidatributo dePost model

App\Models\User::find(2)->posts->pluck('uuid')
=> Illuminate\Support\Collection {#983
     all: [
       "1",
       "2",
       "3",
     ],
   }

0

Probar con condiciones.

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

-3
EmployeeGatePassStatus::with('user:id,name')->get();

1
Esta es la misma sintaxis que en esta respuesta (solo nombres diferentes para modelo y columna)
barbsan
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.