Laravel/Eloquent pagination and groupBy for a postgres materialized view model - laravel

I've created a materialized view: accounts_index that has a couple left joins, so I need to do a group by with the eloquent model. I also need to paginate the collection and am having trouble nailing the order of things. The materialized view:
CREATE materialized VIEW accounts_index
AS SELECT a.account_uuid,
a.account_no,
a.person_owner_uuid,
a.company_owner_uuid,
a.account_group_uuid,
a.account_scope_uuid,
a.created_at,
a.deleted_at,
s.service_uuid,
s.status,
st.service_type
FROM accounts a
LEFT JOIN services s
ON a.account_uuid = s.account_uuid
LEFT JOIN service_types st
ON s.service_type_uuid = st.service_type_uuid
The eloquent model can grab that table like so: AccountIndex::all();.
I could paginate that: AccountIndex::paginate(); or do a groupBy: AccountIndex::all()->groupBy('account_uuid');, but lost on how to combine the two. Some attempts:
AccountIndex::all()->groupBy('account_uuid')->paginate(): Method Illuminate\Database\Eloquent\Collection::paginate does not exist.
AccountIndex::paginate()->groupBy('account_uuid');: returns the collection without paginating.
$accountsIndex = collect(\DB::table('accounts_index')->get());
$accountsIndex->groupBy('account_uuid')->paginate();: Same Method Illuminate\Support\Collection::paginate does not exist. exception.
The main problem I'm trying to solve is that these joins will be returning accounts that have multiple services (so multiple rows) and I need to then group by the account_uuid. Thanks in advance for any insights!

paginate method is related to Illuminate\Database\Query\Builder or Illuminate\Database\Eloquent\Builder classes, it is not exists in Collection class,
the corresponding method for it in Collection class is forPage method, you can get more information from the documentation

almost
AccountIndex::groupBy('account_uuid')->paginate()
paginate actually DOES something
groupBy() is just writing SQL just like ->where() ->join() etc that all prepares an SQL statement you can try by running ->toSql() returns an sql string.
get() all() paginate() all actually do something e.g. execute the SQL.

Related

Laravel - How to relate two collections like Eloquent method "belongsToMany" and "with"

How can you combine two collections, one being the collection of parent items together combined with your collection of child items?
I would like something like using the method with and belongsToMany,but in this scenario I cannot use both methods correctly because one table is in another schema and the pivot table is in another schema.
Area::with('permissoes')
->where('sistema', '<>', 'S')
->get()
Most Eloquent eagerloads are done with separate queries that just use an IN statement on keys from the previous one. Pivot tables are the exception. It sounds like you need to explicitly tell the Model relation what database your pivot table is in. See my answer here: belongsToMany relationship in Laravel across multiple databases

How Eloquent ORM creates its data structure on eager loading

I have been looking into eloquent's source code to see how it manages building its data structure when eager loaded with one or more relationships specified but I have not been successful.
For instance:
User has many photos, and a photo belongs to a User
How does eloquent perform its SQL query?
Does it make multiple SQL? A query to get the user and then another one to get his/her photo, or does it perform a single query.
I am also interested to see the structure of the SQL, because I have tried lots of options and there is absolutely no way I could tell what tables each field belonged to because the returned result is just plain array of objects.
Laravel will create at least two queries when you'll try to use eager loading.
For example, this code:
$users = User::with('photos')->get();
Will produce two queries similar to these:
select * from `users` where `users`.`deleted_at` is null
select * from `photos` where `photos`.`user_id` in ('1', '2', ... '99')
I'd recommend you to use Laravel Debugbar, if you want to better understand how raw SQL queries look like.
Sometimes using toSql() in php artisan tinker tool is also helpful:
\App\User::where('id', 2)->toSql()

Laravel Eloquent model data from 2 tables

I've just started using Laravel and I'm coming from a different system using an existing database. In this system there are 2 users table, one stock with the CMS and one custom one.
I want to create an Eloquent model which retrieves data from both tables into one model. I know I can use the following to create a relationship.
$this->hasOne('App\SecondUser', 'id', 'id);
But this results in 2 sql queries, and I want to join results from 2 tables before returning the model, in one join statement. How do I do this?
That might be a bit more complicated that you would expect.
First of all you have to use \DB facade to join the two collections(arrays) and then recreate the Eloquent collection from these arrays using Collection's make method.
More info about the Collection class here
An easier way might be to join them using standard laravel relationships and user something like Model::user->with('relation')->get.
But this will still create 2 queries (still relatively fast).

Laravel not returning join query to blade

I have two queries, one is lighter on data by using the pivot table as a filter to get data from the main table (student in this case).
$students=\DB::table('student')->join('school_student', 'student.id', '=','school_student.student_id')->get();
This returns a query result from the controller. But will not load into the blade:
$this->layout->content=\View::make('admin.students.index')->with('student', $students);
Whereas this versions returns a similar more data heavy (i.e. outputs all school data each time)
but works in blade.
$students = \Student::with(array('schools' => function($query){$query->where('school_id', '=', 1);}))->get();
Is it simply that DB and view are incompatible?
If so what is the Laravel 4 method to query one table and it's pivot only.
Any help appreciated.
In the blade
#if($student->count())
The first example produces this error:
Call to a member function count() on a non-object
DB::...->get() returns an array, so you can't call ->count() on it (hence "non-object"), but instead you need count($students).
The reason ->count() works when you do the 'more data heavy' method is that you're using Eloquent and it returns Eloquent Collections.
So, basically, you're doing two different things and expecting to treat them the same.
Also, while I'm here I should point out that I think your Eloquent query isn't quite right. First off you're hardcoding the id as 1 (whereas in the DB-style query you don't care about the school ID, and you just use it to join to the pivot table - maybe you used an incomplete query), but also you're using with but you should probably look at has. with eager-loads models, but has is what you want if you just want to check for a condition on a join table.

How to retrieve a Doctrine record with all relational records?

I was wondering if there is a way to get a record with all relational data, something like a 'Deep-Fetch'
So if a model Child were related to another model Parent,
can we fetch Child & then access Child->Parent->name thru a single query?
Doctrine today fires a query whenever a relationship is accessed. Is this too costly? does it need to be optimizeD?
thanks
Doctrine automatically hydrates related objects when you select fields from that relations:
Doctrine_Query::create()
->select('a.*, c.*)
->from('Article a')
->innerJoin('Category c');
In this example both Article and Category objects are being hydrated (no additional queries are made).

Resources