mercredi 19 janvier 2022

Eloquent select field after aggregation

I have three models, User, Post and Comment. User and Post are in a One-To-Many relationship, and so are User and Comment. For the sake of this example, there isn't a Post-Comment relationship.

When I run the following query

User::withCount(['posts', 'comments'])->get()

I obtain the expected results:

[
...
  App\Models\User {#3459
    id: 18,
    username: "Foo",
    created_at: "2021-12-08 11:38:39",
    updated_at: "2021-12-08 11:38:39",
    posts_count: 5,
    comments_count: 15,
  }
...
]

I would like to remove the timestamps from the resulting models. I've tried putting the array of fields I want as parameter for get (as in ->get(['username', 'posts_count', 'comments_count']), but the result didn't change at all.

I've also tried replacing get(...) with select(...)->get(), but that produces this error:

Illuminate\Database\QueryException with message 
'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'posts_count' in 'field list'  
(SQL: select `username`, `posts_count`, `comments_count` from `users`)'

which I assume it is due to the fact that the aggregation function is not yet being executed.

So I came up with this solution

$usersWithCounts = User::withCount(['posts', 'comments'])->get()
    ->map(function ($item, $key) {
         return $item->only(['username', 'posts_count', 'comments_count']); 
      });

but it doesn't feel right: the returned collection is no longer made of Eloquent models, just simple arrays.

[
...
  [
    username: "Foo",
    posts_count: 5,
    comments_count: 15,
  ]
...
]

What's the right way of proceeding?



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire