Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

279
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda