Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

275
Vistas
Load specific columns from eager loaded laravel collection

Consider books and authors relationship. Every book belongsTo an author and 1 author hasMany books. Books table has fields like (Id,Title,Version etc) and authors have fields like (Id,Name,Address etc). Note DB columns do not follow the default laravel naming convention.

Now; I want to fetch some fields from both tables. More speficic, I want title,version,name and address fields. This is desired output:

    {
        Title: "Oxford Maths",
        Version: "2.5",
        author: "John Doe",
    }

1st trial:

return Book::with('author')->get()->map(function ($book) {
    return collect($book)->only(
        [
            'Title',
            'Version',
            "author"
        ]);
});

1st Trial Output:

    {
        Title: "Oxford Maths",
        Version: "2.5",
        author: {
            Id: 1,
            Name: "John Doe",
            Address: "Tanzania",
            deleted_at: null
        }
    }

2nd trial: Tried this;

return Book::with([
        'author' => function($query){
            $query->select('Name','Id');
        }
    ])->get()->map(function ($data) {
    return collect($data)->only(
        [
            'Title',
            'Version',
            "author"
        ]);
});

And this;

return Book::with('authority:name,Id')->get()->map(function ($data) {
    return collect($data)->only(
        [
            'Title',
            'Version',
            "author"
        ]);
});

2nd Trial output:

    {
        Title: "Oxford Maths",
        Version: "2.5",
        author: {
            Name: "John Doe",
            Id: 1
        }
    }

3rd Trial:

return Book::with([
        'author' => function($query){
            $query->select('Name'); // *Removed foreignKey*
        }
    ])->get()->map(function ($data) {
    return collect($data)->only(
        [
            'Title',
            'Version',
            "author"
        ]);
});

3rd Trial output:

    {
        Title: "Oxford Maths",
        Version: "2.5",
        author: null
    }

What can I do to get the desired output?

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

Of course, you can do it afterwards on the collection but it makes more sense to do it directly on the query. You try to reflect that in your 3rd trial. However, in my opinion that's were Laravel behaves a bit odd. In order to do the eager loading, you need your foreign key. Even though, that's logical, it's human to forget about that nevertheless. But if you forget to include the foreign key, Laravel doesn't tell you this and instead returns null. So make sure, all necessary primary and foreign keys are always included in your relation.

return Book::with([
    'author' => function($query){
        $query->select('id', 'Name'); // *Removed foreignKey*
    }
])->get([ 'title' , 'version' ]);

One thing, I like to do when a relation should mostly return only one of its values:

class Author extends Model
{
    public function __toString()
    {
        return $this->Name;
    }
}

To make this automatically serialized this way, you can change __toString() to jsonSerialize()

class Author extends Model implements JsonSerializable
{
    public function jsonSerialize()
    {
        return $this->Name;
    }
}
over 4 years ago · Santiago Trujillo Denunciar

0

Maybe it will help you

in Model

protected $appends = [
    'author_name', 'address'
];

protected $fillable = [
    'title',
    'version',
];

public function author(){
    return $this->belongsTo(Author::class);
}

public function getAuthorNameAttribute(){
    return $this->author->name;
}

public function getAddressAttribute(){
    return $this->author->address;
}

and in controller use this

return Book::query()->with('author')->first()->makeHidden(['author','author_id']);

Output:

{
  "id": 1,
  "title": "book",
  "version": "v1",
  "created_at": null,
  "updated_at": null,
  "author_name": "komeyl",
  "address": "Iran"
}
over 4 years ago · Santiago Trujillo Denunciar

0

I ended up using trick suggested by @komeyl-dev. This is sample code:

//Book.php
class Book extends Model
{
    protected $appends = ['author_name']; // appended so I can access it as json

    public function author(){
        return $this->belongsTo(Author::class,'author_id');
    }
    
    public function getAuthorNameAttribute(){
        return $this->author->name;
    }
}

//Testing in web.php (Note: No eager loading here)
Route::get('url', function () {
    return Book::get()->map(function ($data) {
        return collect($data)->only(
            [
                'Title',
                'Version',
                "author_name"
            ]);
    });
});

Thank you @shaedrich and @komeyl-dev

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda