hasManyThrough relations ships with join? - laravel

I have 4 tables (Cars, Vignettes, Inspections and Insurances). Vignettes, Inspections and Insurances are "belongsTo" to Cars.
I need to combine results of these three tables into one query and sorting by 'created_at' and take first 3-4 of them. How can I achieve that?
All of the three tables have same column names and types

You should be able to chain things together, something like
$car->with('Vignettes')
->orderBy('created_at', 'desc)
->take(4)
->get();
As with everything laravel, the docs are your friend.

Related

How to order by a second relationship in Laravel query?

I have a bit of an issue that I've been spinning my wheels on for a little while. I have a pretty complex (and maybe not correct - or rather most efficient) data structure that I'm trying to work my way through the logic for.
I am wondering how I perform a query (orderBy) on a second relationship function on a single query. I'm not even sure if that is the right way to describe it, so here's my code:
$players = $team->players()
->wherePivot('year_id', $year->id)
->with(['stats' => function ($query) {
$query->orderBy('score', 'desc');
}])
->get();
It seems like it should be pretty straight forward, but the orderBy clause is not working. The query otherwise works (returns players and their stats). Here is how my relationships are set up:
Team -> belongsToMany Player (and vice versa)
Player -> belongsToMany Stat (and vice versa)
Each of my pivot tables that have consequence in this situation have an extra key besides the two specified tables, they also have a year_id. This is because the relationship is only relevant for a particular year, and I think this may be what is making this more complicated. So for example, my team_player table looks like this:
team_id
player_id
year_id
And my player_stat table looks like this:
player_id
stat_id
year_id
I'm not sure if this is the most efficient or best way to accomplish what I want, but it made sense at the time of build. So how can I work through this architecture to make this query work? Also, any feedback on a data structure that may work better would be appreciated too.
If I understand you correctly you want to sort all players (not stats), you will need to join the tables:
$players = $team->players()
->wherePivot('year_id', $year->id)
->with(['stats'])
->join('stats', 'stats.player_id', '=', 'players.id')
->orderBy('stats.score', 'desc')
->get();
$players = $team->players()->wherePivot('year_id', $year->id)->with('stats')->orderBy('stats.score', 'desc')->get();

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

One for all or individual Pivot for every many to many in Laravel?

i dont know that i'm doing right or wrong..
i want to make a blog that have multiple categories and tags with many to many relation.
should i make a pivot table for each one like:
"category_post"
$table->integer('post_id')->unsigned()->index();
$table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
$table->integer('category_id')->unsigned()->index();
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
and another one for Tags table...
or can i make one table for both with an extra column that can filter throw that?
"pivot_post"
$table->integer('post_id')->unsigned()->index();
$table->integer('pivot_id')->unsigned()->index();
$table->string('type');
but.. if i can make one for all, i dont know hot make db and relation??
and which one is better for performance..?
1 big relation tableor multiple relation table?
tnx.
I think you're looking for a polymorphic relationship if you wanna accomplish this with a single table.
https://laravel.com/docs/5.6/eloquent-relationships#polymorphic-relations

Laravel Eloquent ORM - Get first and third table data

Category Table
Service Table
Branch Table
I have 3 tables link together. Above is my code, I want to produce the result same as below. Can I use a line of code to do that?
Or I have to get result from 2 tables first then only get the Branch table?
Thanks.
If you would like to obtain a collection of categories with service and branches you can eager load them in a single eloquent query.
$categories = Category::with('service.branches')->get();
But you still have to write a bit more if you would like to achieve your requirement.
Fractal Transformers might help you to do this. See their documentation here.

Laravel Eloquent: Order results by eaged loaded model.property, and paginate the result

Lets say I have three models: Post, Category and Tag.
The Post belongsTo Category and Category hasMany Post.
Theres manyToMany relation between Tag and Category.
I want to list my posts by Category name and paginate the results.
Post::with('category','category.tags')
->orderBy('category.name') //this is the bogus line
->paginate(10);
But this syntax doesn't work.
What I tried is this as:
Post::select('categories.*')
->join('categories','posts.category_id','=','categories.id')
->orderBy('categories.name)
->paginate(10);
But then I lose the eager loaded data.
If I drop the select() clause then I get rubbish data as categories.id overwrites posts.id. See here.
Is there any elegant way to solve this issue? After spending hours on this I'm one step away from iterating through paginated posts and 'manually' loading the relations as:
foreach($posts as $post) {
$post->load('category','category.tags');
}
Not even sure if there's downside to this but it doesn't seem right. Please correct me if I'm wrong.
UPDATE on last step: Eager loading on paginated results won't work so if I go that road I'll need to implement even uglier fix.
You should be able to use both join and with.
Post::select('posts.*') // select the posts table fields here, not categories
->with('category','category.tags')
->join('categories','posts.category_id','=','categories.id')
->orderBy('categories.name)
->paginate(10);
remember, the with clause does not alter your query. Only after the query is executed, it will collect the n+1 relations.
Your workaround indeed loses the eager loading benefits. But you can call load(..) on a collection/paginator (query result) as well, so calling ->paginate(10)->load('category','category.tags') is equivalent to the query above.

Resources