laravel hydrateRaw/fromQuery and eager loading with pagination
Asked Answered
J

2

6

I currently found out that you can hydrate an Raw sql query.

I have following query:

DB::table(DB::raw('(SELECT *, Y(location) AS longitude, X(location) AS latitude FROM meetings WHERE MBRCONTAINS(@quadrat, location)) AS sub'))
            ->select(DB::raw('(FLOOR(SQRT(POW((@ibk_breite - sub.latitude) * 111, 2) + POW((@ibk_laenge - sub.longitude) * 111 * ABS(COS(RADIANS(@ibk_breite))),2)))) AS distance, sub.*, latitude, longitude'));

which I hydrate as following

$meetings = Meeting::fromQuery($query->toSql());

In the blade view i need to get some additional data from different tables, for example:

 $meeting->user

which references to the User Model. But if I'm not complety wrong that would result to a n+1 problem in a for each loop, because I'm not eager loading it?! So is it possible to eager load the required models as you would normally do with

->with('user', 'books', 'etc...')

??

Also is it possible to paginate it like $meetings = $query->paginate(5); and do $meetings->withPath('home');

EDIT: Found a solution:

// Do your query stuff
 // Get count before the query because it won't work with skip and take     parameter
    $count = $query->count();

    $query->skip($skip);
    $query->take($meetingsPerPage);
    $meetings = Meeting::fromQuery($query->toSql());
    $meetings->load('user', 'interest.image', 'img_thumbnail');
    $meetings = new LengthAwarePaginator($meetings, $count, $meetingsPerPage);

$meetings->load acts as ->with(). As last step you need to create a paginator. IMPORTANT: Use query->count() before you set skip() and/or take() Otherwise it will not work.

Original answer from laracasts. Theres also another possibily stated that didn't work for me.

Jambalaya answered 27/6, 2017 at 15:39 Comment(5)
Did you find a solution to this? Very good questionHydrophobia
I asked in another forum and got this part of answer linkJambalaya
Edited my original postJambalaya
@Jambalaya You have no idea how much frustration this just saved meJockstrap
@Jambalaya It would be better if you add your answer as a actual answer and mark it as accepted instead of providing the answer in the question. See self answer documentation. Thanks.Procto
J
1

My solution:

// Do your query stuff
// Get count before the query because it won't work with skip and take parameter
$count = $query->count();

$query->skip($skip);
$query->take($meetingsPerPage);
$meetings = Meeting::fromQuery($query->toSql());
$meetings->load('user', 'interest.image', 'img_thumbnail');
$meetings = new LengthAwarePaginator($meetings, $count, $meetingsPerPage);

$meetings->load acts as ->with(). As last step you need to create a paginator. IMPORTANT: Use query->count() before you set skip() and/or take() Otherwise it will not work.

Original answer from laracasts. Theres also another possibily stated that didn't work for me.

Jambalaya answered 14/10, 2019 at 18:15 Comment(1)
Awsm! The Eloquent collection "load()" method is exactly what I was looking for!Laveen
O
2

You can use setCollection() function with LengthAwarePaginator object (found in Illuminate/Pagination/AbstractPaginator.php). Use load() for eager loading.

 $users = DB::table('users')->paginate();
 $users->setCollection(User::hydrate($users->items())->load(['category']));
Orthotropous answered 27/3, 2020 at 9:35 Comment(0)
J
1

My solution:

// Do your query stuff
// Get count before the query because it won't work with skip and take parameter
$count = $query->count();

$query->skip($skip);
$query->take($meetingsPerPage);
$meetings = Meeting::fromQuery($query->toSql());
$meetings->load('user', 'interest.image', 'img_thumbnail');
$meetings = new LengthAwarePaginator($meetings, $count, $meetingsPerPage);

$meetings->load acts as ->with(). As last step you need to create a paginator. IMPORTANT: Use query->count() before you set skip() and/or take() Otherwise it will not work.

Original answer from laracasts. Theres also another possibily stated that didn't work for me.

Jambalaya answered 14/10, 2019 at 18:15 Comment(1)
Awsm! The Eloquent collection "load()" method is exactly what I was looking for!Laveen

© 2022 - 2024 — McMap. All rights reserved.