Order by relationship with pagination laravel eloquent - laravel

I have the relationship below, an application belongs to a user.
Users table
ID | Name
1 | Danny
2 | Mark
Applications table
ID | user_id
1 | 1
2 | 2
Application.php
public function user()
{
return $this->belongsTo(User::class);
}
I'm trying to sort the application by user's name and paginate the result. I tried the code below, the pagination is working but the order by doesn't have any effect.
$query = Application::query();
$query = $query->with(['user' => function ($query){
$query->orderBy('name', 'DESC');
}]);
$query = $query->paginate(10);

Try using inner join and order by relation column:
$applications = Application::select('*')
->join('authors', 'applications.user_id', '=', 'users.id')
->orderBy('authors.name', 'DESC')
->paginate(10);

Try this:
Application::join('users', 'applications.user_id', '=', 'users.id')
->orderBy('users.name','desc')
->with('users')
->get();

Related

How to fetch count from distant relationship in laravel way?

I am trying to fetch all the attributes with product count that is associated with products in the given category.
table structure
attributes table:
| id | name | value | filterable |
products table:
| id | name |
categories table:
| id | name |
attribute_product pivot table:
| id | attribute_id | product_id
category_product pivot table:
| id | category_id | product_id
Below is how my models look like.
Attribute
public function products(){
return $this->belongsToMany('App\Models\Product');
}
Product
public function attributes(){
return $this->belongsToMany('App\Models\Attribute');
}
public function categories(){
return $this->belongsToMany('App\Models\Category');
}
Category
public function products(){
return $this->belongsToMany('App\Models\Product');
}
I can get all the attributes associated with a product in the given category with the below query.
Attribute::where('filterable', '=', 1)
->whereHas('products.categories', function (Builder $query) use ($category) {
$query->where('category_product.category_id', '=', $category->id);
})->get();
However, I cannot figure out how I should get product counts.
I started testing query builder to achieve this but condition on where pivot seems to be binding attribute_product.attribute_id as a string value instead of the column value.
$data = DB::table('attributes')->where('filterable', '=', true)
->whereExists(function ($query) {
$query->select('*')->from('products')
->join('attribute_product', function ($join){
$join->on('products.id', '=', 'attribute_product.product_id');
})->where('attributes.id', '=', 'attribute_product.attribute_id');
})->get();
Below is more or less the final SQL query I need to send to the database
select `attributes`.*,
(SELECT
count(*) from `products`
inner join `attribute_product` on `products`.`id` = `attribute_product`.`product_id`
where `attributes`.`id` = `attribute_product`.`attribute_id`) as `products_count`
from `attributes` where `filterable` = 1
and EXISTS
(select * from `products` inner join `attribute_product` on `products`.`id` = `attribute_product`.`product_id`
where `attributes`.`id` = `attribute_product`.`attribute_id`
and EXISTS
(select * from `categories` inner join `category_product` on `categories`.`id` = `category_product`.`category_id`
where `products`.`id` = `category_product`.`product_id` and `category_product`.`category_id` = 9))
Please, someone, assist me in getting attributes with associated product count in the laravel way.
Check out the
withCount('relation_name')
method in eloquent Ex:
$posts = App\Post::withCount([
'comments',
'comments as pending_comments_count' => function (Builder $query) {
$query->where('approved', false);
}
])->get();
I managed to get all my results in a single request with the below query. Thanks! #athul for showing the direction.
Attribute::where('filterable', '=', 1)->whereHas('products.categories', function (Builder $query) use($category) {
$query->where('categories.id', '=', $category->id);
})
->withCount(['products' => function ($query) use($category) {
$query->whereHas('categories', function (Builder $query) use ($category) {
$query->where('categories.id', '=', $category->id);
});
}])->get();

How to get post which have multiple table relationship?

my database scheema
Table POST
| id | title | content |
Table SharedGroup
|id | title | slug
Table Post_SharedGroup
|id| post_id | shared_group_id|
i want to make a query in laravel that i give slug of sharedgroup and get post of it
$data = Post::whereHas('sharedGroup',function($query) use($slug){
$query->whereIn('slug',$slug);
})->get();
where $slug is your slug array given by you
Model Post
public function sharedGroup(){
return $this->belongsToMany('App\SharedGroup');
}
Model SharedGroup
public function post(){
return $this->belongsToMany('App\Post');
}
You seem to just want a basic join between the three tables:
$posts = DB::table('POST p')
->join('Post_SharedGroup ps', 'p.id', '=', 'ps.post_id')
->join('SharedGroup s', 'ps.shared_group_id', '=', 's.id')
->whereIn('s.slug', array(1, 2, 3)) // match slug values (1, 2, 3)
->select('p.*')
->get();

2 id column after JOIN in Laravel. How to access to both IDs in Controller and Blade?

After join I got table with 2 ID column. Now I don't know how to access in Controller and Blade both of IDs.
In Blade when I try {{$value->id}} and it gets second ID.
$users = User::where('user_id', $user_id)
->join('tagged', 'tagged.taggable_id', '=', 'users.id')
->orderBy('users.id', 'asc')
->get();
Gives me:
-------------------------------------------------------
| id | name| phone | id | taggable_type | taggable_id |
-------------------------------------------------------
How can I get both IDs in Controller and Blade?
$users = DB::table('users')->where('user_id','=', $user_id)
->select('users.*','tagged.id as tagged_id') //add fields required from tagged table in this row
->join('tagged', 'tagged.taggable_id', '=', 'users.id')
->orderBy('users.id', 'asc')
->get();
Use $users->tagged_id and $users->id in view

Laravel: join Eloquent models

Question. How can I use Eloquent to produce this query:
SELECT campaigns.name, users.name FROM campaigns LEFT JOIN users on campaigns.gamemaster_id = users.id where campaigns.status = 1
Campaigns
id gamemaster_id name status
1 1 campaign1 1
2 2 campaign2 1
Users
id name
1 rick
2 bob
Result
id gamemaster_id name status gamemaster_name
1 1 campaign1 1 rick
2 2 campaign2 1 bob
Campaign model
class Campaign extends Model
{
public function gamemaster()
{
return $this->belongsTo('App\User', 'gamemaster_id');
}
}
My try to make Eloquent, but that fails:
$result = Campaign::where('status', '=', 1)->with('gamemaster')->select('name')->orderBy('users.updated_at', 'desc')->get();
You can do it in two ways, first using the query builder,
$campaigns = DB::table('campaigns')->leftJoin('users', 'campaigns.gamemaster_id', '=', 'users.id')
->select(['campaigns.name as name', 'users.name as gamemaster_name'])
->where('campaigns.status', '=', 1)
->orderBy('users.updated_at', 'desc')
->get();
And with eager loading, you can get the campaigns like below. However, to sort by relation property, you need an another layer which is not that easy to implement.
$campaigns = Campaign::where('status', '=', 1)->with(['gamemaster' => function($query){
$query->select(['id', 'name']);
}]->select('id', 'gamemaster_id', 'name')->get();
But you can use collection functions to easily sort it (However, it will take more execution time)
$campaigns = Campaign::where('status', '=', 1)->with(['gamemaster' => function($query){
$query->select(['id', 'gamemaster_id', 'name', 'updated_at']);
}]->select('id', 'name')->get()->sortByDesc(function ($campaign) {
return $campaign->gamemaster->updated_at;
})
The following query should work:
Campaign::whereStatus(1)
->join('users', 'campaigns.gamemaster_id', '=', 'users.id')
->select('campaigns.name', 'users.name')
->orderBy('users.updated_at', 'desc')
->get()

laravel eloquent query group by last id

Hi I'm trying to get the last register in DB for each equipment
I got like
id | id_equip
-----+----------
1 | 3
2 | 3
3 | 3
4 | 2
5 | 2
I want to query like the last id of each equip like:
id | id_equip
-----+----------
3 | 3
5 | 2
I tried this:
$calibracao = $this->calibracao->orderBy('id', 'DESC')->groupBy('id_equip')->get();
thanks for the help!
A simple way, without join, using max:
$query = DB::table('equip')
->select(DB::raw('*, max(id) as id'))
->groupBy('id_equip')
->orderBy('id', 'asc')
->get();
(Assuming, of course, that you can count on your id to be in date order.)
You can also do this with Eloquent, using a self-referencing one-to-one relationship. The query takes longer, but it's much more Laravel-like:
Define the relationship in your model:
class myModel extends Eloquent {
public function latestEquipment()
{
return $this->hasOne('myModel', 'id_equip', 'id_equip')->latest();
}
}
(Note that in this case, we're using latest() so that we don't rely on the order of ids to determine the most recent entry, but rather on the created_at date of each record. This is more accurate.)
To retrieve all the records, with their latest equipment entry:
$latest = myModel::with('latestEquipment')->groupBy('id_equip')->get();
// loop over the results
foreach ($latest as $l) {
if ($l->equipment) {
echo('ID: ' . $l->id . 'ID_EQUIP: ' . $l->id->id_equip . '<br>');
}
}
I'm not sure if there's an easier way and this is kind of convoluted because of the join, but it should give the result you want:
DB::table('equip as e')
->select('e.*')
->join(DB::raw("(SELECT id_equip, MAX(id) id FROM equip GROUP BY id_equip) as _e"), function ($join) {
$join->on('e.id', '=', '_e.id')->on('e.id_equip', '=', '_e.id_equip');
})
->orderBy('id', 'asc')
->get();
public function latest($equipamentos)
{
foreach ($equipamentos as $equip)
{
$latest[$equip->cod] = DB::table('tb_calibracao')
->where('cod_equipamento', $equip->cod)
->where('parecer', '1')
->orderBy('cod', 'Desc')
->first();
}
return $latest;
}
That worked, thx for the help!

Resources