Laravel BelongsToMany relationship with WhereHas condition - laravel

I have some relationship in my DB:
public function managers()
{
return $this->belongsToMany(User::class, 'manager_location', 'location_id', 'manager_id')
}
This relation works well - return all users which were synced with some location.
I'm using spatie/laravel-permissions and my users have different roles. When I'm trying to return users with some role (add the whereHas to the relation) it continues to returns all records:
public function managers()
{
return $this->belongsToMany(User::class, 'manager_location', 'location_id', 'manager_id')->whereHas('roles', function ($q) {
$q->where('name', '=','manager');
});
}
Where I went wrong?
P.S.
Mysql log query:
select * from `users` inner join `manager_location` on `users`.`id` = `manager_location`.`manager_id` where `manager_location`.`location_id` is null and exists (select * from `roles` inner join `model_has_roles` on `roles`.`id` = `model_has_roles`.`role_id` where `users`.`id` = `model_has_roles`.`model_id` and `model_has_roles`.`model_type` = ? and `name` = ?)
Dump of QueryBuilder: https://pastebin.com/j6ik35mK

Related

hasManyThrough query without laravel_through_key

With a Laravel hasManyThrough relationship how can I prevent extra keys added to the select? Is there a withoutPivot or simiar?
I'm trying to perform a union join and need to the columns to be the same.
SQLSTATE[21000]: Cardinality violation: 1222 The used SELECT statements have a different number of columns
SELECT
count(*) AS aggregate
FROM ((
SELECT
`order_payments`.`id`,
`order_payments`.*,
`orders`.`user_id` AS `laravel_through_key`
FROM
`order_payments`
INNER JOIN `orders` ON `orders`.`id` = `order_payments`.`order_id`
WHERE
`orders`.`user_id` = 1)
UNION (
SELECT
`orders`.`id`
FROM
`orders`
WHERE
`orders`.`user_id` = 1
AND `orders`.`user_id` IS NOT NULL)) AS `temp_table`
I'm unable to use the makeHidden as suggested in another question
$payments = auth()->user()->orderPayments()->select('order_payments.id');
$orders = auth()->user()->orders()->select('orders.id');
$payments->union($orders)->paginate(50);
I guess I could do it without Eloquent manually but just wondering if there was another way?
class User extends Authenticatable implements UserContract {
/**
* Orders for this User
*/
public function orders()
{
return $this->hasMany(Order::class);
}
/**
* Order Payments for this User
*/
public function orderPayments()
{
return $this->hasManyThrough(OrderPayment::class, Order::class);
}
}

Convert Raw SQL Query to Laravel Eloquent using eager loading

I'm having great difficulty in trying to convert the following query into an Eloquent one.
SELECT Sum(t.amount) AS amount,
m.name
FROM transactionsv2 t
JOIN channels c
ON t.entityid = c.uuid
JOIN merchants m
ON c.sender = m.uuid
WHERE t.paymenttype = 'DB'
AND t.status = 1
AND t.processing_time >= '2019-01-01'
AND t.processing_time < '2019-01-21'
GROUP BY m.name;
This is what I have but the result set is not right...
public function getTransactionsVolumeReport()
{
$report = Transaction::select(DB::raw('sum(amount) as amount, entityId'))
->where('paymentType', '=', 'DB')
->where('status', 1)
->where('processing_time', '>=', '2019-01-01 00:00:00')
->where('processing_time', '<=', '2019-01-21 23:59:59')
->with(['channel' => function ($q) {
$q->select('uuid', 'name', 'sender');
}])
->with(['channel.merchant' => function ($q) {
$q->select('uuid', 'name')
->groupBy('name');
}])
->get();
echo $report;
}
These are the queries that Laravel debugbar is showing...
Below are my Eloquent relationships...
Transaction Model
protected $with = ['channel', 'statusPayment'];
public function channel() {
return $this->hasOne(Channel::class, 'uuid', 'entityId');
}
-----
Channel Model
protected $with = ['merchant', 'attachedMerchantAccount'];
public function merchant() {
return $this->hasOne('App\Merchant', 'uuid', 'sender');
}

How to retrieve information through table?

I have SQL query that does that I need:
SELECT users.FirstName, users.Id FROM `orders`
INNER JOIN orderrecipients ON orderrecipients.Orders_Id = orders.Id
INNER JOIN users ON users.Id = orderrecipients.Users_Id;
I try to use Eloquent model to build query above using hasManyThrough:
public function OrderRecipients()
{
return $this->hasManyThrough('App\OrderRecipient', 'App\User', 'Id', 'Orders_Id');
}
And using is:
$recipients = OrderModel::with("OrderRecipients")->where("User_Id", $userId)->get();
dd($recipients->OrderRecipients()->count());
How to build this relation and get data through table?
HasManyThrough is not the best choice here. Use a BelongsToMany relationship instead:
public function OrderRecipients()
{
return $this->belongsToMany('App\User', 'orderrecipients', 'Orders_Id', 'Users_Id');
}

Laravel: multiple where clauses in a many-to-many relationship

I am not able to create this sql query on laravel:
select * from `events_theatre` where
event_id IN (
select id from events where (`events`.`id` = `events_theatre`.`event_id` and `user_id` = 1 and `event_type` ='theatre') and `events`.`deleted_at` is null
)
or event_id IN (
select id from events inner join events_managers on events.id = events_managers.event_id and events_managers.user_id = 1
)
and `events_theatre`.`deleted_at` is null
The Events_Theatre model has this relationship:
public function event()
{
return $this->hasOne('App\MyEvent', 'id');
}
While the MyEvent model has this relationship:
public function managers()
{
return $this->belongsToMany('App\User', 'events_managers', 'event_id', 'user_id');
}
Pratically an Events_Theatre model is an Event model, and an Event model may have many managers but just 1 admin.
I need to get that Events_Theatre (and their MyEvent) whose user is an admin or one of the managers.
I tried with this eloquent query:
$list = App\Events_Theatre::whereIn('event_id', function ($query) {
$query
->where(['user_id' => Auth::id(), 'event_type' => 'theatre'])
->orWhereHas('managers', function ($query) {
$query->where('user_id', Auth::id());
});
});
But I get this sql query:
select * from `events_theatre` where
exists (
select * from `events` where (
`events`.`id` = `events_theatre`.`event_id` and `user_id` = 1 and `event_type` = 'theatre'
) or exists (
select * from `users` inner join `events_managers` on `users`.`id` = `events_managers`.`user_id` where `events_managers`.`event_id` = `events`.`id` and `user_id` = 1
)
and `events`.`deleted_at` is null
) and `events_theatre`.`deleted_at` is null
But its wrong. How can I solve this?
Thanks
UPDATED
I got the answer. This is the eloquent code I used:
$list = Events_Theatre::whereHas('event', function ($query) {
$query
->where(['user_id' => Auth::id(), 'event_type' => 'theatre']);
})->orWhereHas('event', function ($query) {
$query
->whereHas('managers', function ($query) {
$query->where('user_id', Auth::id());
});
})->get();
You can try has method
App\Events_Theatre::has('event')->orhas('managers')->get();

query with Laravel Eloquent ORM

How can I make this query in Laravel, using Eloquent ORM?
select * from posts p order by ( select count(*) from likes where flag = 'c' and p.id = post_id ) Desc limit 3
I have this relationship in my models
Post.php
public function likes(){
return $this->hasMany('Like', 'post_id');
}
Like.php
public function post(){
return $this->belongsTo('Post', 'post_id');
}
Thanks! :)
You may try something like this:
$posts = Post::leftJoin('likes', function($join) {
$join->on('posts.id', '=', 'likes.post_id')->where('flag', '=', 'c');
})
->select('posts.*', 'likes.post_id', DB::raw('count(likes.post_id) as pCount'))
->groupBy('post_id')
->orderBy('pCount', 'desc')
->take(3)
->get();

Resources