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

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();

Related

Using whereRelation with a subquery

I have wrote a zip_code query that I am wanting to add to another query. The problem is I am not exactly sure how to combine these via whereRelation().
$zip_code = ZipCode::where('office', '=', function ($query) {
$query->selectRaw('office')->from('zip_codes')->where('zip_code', session()->get('zip_code'));
})->get();
$appointment = Appointment::with('customer', 'blocks', 'status', 'services.service')->whereRelation('customer', 'zip_code', $zip_code)->get();
The output of $appointment is:
select * from appointments where exists (select * from customers where appointments.customer_id = customers.id and zip_code = {"id":1,"zip_code":00000,"city":"City","office":"LOCATION"})
$zip_code is returning this query. I am just wanting those results to be called in the whereRelation() so all the zip_codes for that office are returned:
SELECT * FROM zip_codes
where office = (
select office
from zip_codes
where zip_code = '00000'
)
You can pluck the zip_code values from the $zip_code collection like so.
$zip_code = ZipCode::select('zip_code')
->where(
'office',
function($query) {
$query->select('office')
->from('zip_codes')
->where(
'zip_code',
session()->get('zip_code')
);
}
)->get();
$zip_code = $zip_code->pluck('zip_code')->all();
Then use that in the next query for filtering the relation.
$appointment = Appointment::with('customer', 'blocks', 'status', 'services.service')
->whereRelation(
'customer',
function($query) {
$query->whereIn('zip_code', $zip_code);
}
)->get();
Otherwise, you could query for the office with the given zip code, carry out a join of the customer and the zip codes table then filter out customers with zip codes pertaining to the office.
$offices = ZipCode::select('office')
->where('zip_code', session()->get('zip_code'))
->get();
$offices = $offices->pluck('office')->all();
$appointment = Appointment::with(
'customer',
'blocks',
'status',
'services.service'
)->whereHas('customer', function ($query) {
$query->join('zip_codes', function ($join) {
$join->on('zip_codes.zip_code', 'customers.zip_code');
$join->whereIn('zip_codes.office', $office);
});
});

Laravel BelongsToMany relationship with WhereHas condition

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

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();

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');
}

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