Laravel 5 – querying items by many-to-many related model - php

I've got a following many-to-many relation:
attendees - attendee_tag - tag
Now I want to filter attendees based on some tag value, so I've created this solution, which works well:
$attendees = Attendee::whereHas('tags', function ($q) {
$q->where([
['attendee_tag.tag_id', '=', '6'],
['attendee_tag.value_string', '=', 'Summer ticket']
})->with(['tags' => function($q) {
$q->select('tags.id', 'value_type', 'attendee_tag.value_string', 'attendee_tag.value_int');
}])->paginate($pagination);
But I can't figure out, how to filter attendees based on more than 1 tag ... I've tried this, but it doesn't work:
$attendees = Attendee::whereHas('tags', function ($q) {
$q->where([
['attendee_tag.tag_id', '=', '6'],
['attendee_tag.value_string', '=', 'Summer ticket']
])->where([
['attendee_tag.tag_id', '=', '13'],
['attendee_tag.value_string', '=', 5]
]);
})->with(['tags' => function($q) {
$q->select('tags.id', 'value_type', 'attendee_tag.value_string', 'attendee_tag.value_int');
}])->paginate($pagination);
Any help would be highly appreciated! :)

Maybe with separating the whereHas :
$attendees = Attendee::whereHas('tags', function ($q0) {
$q0->where([
['attendee_tag.tag_id', '=', '6'],
['attendee_tag.value_string', '=', 'Summer ticket']
]);
})->whereHas('tags', function ($q1) {
$q1->where([
['attendee_tag.tag_id', '=', '13'],
['attendee_tag.value_string', '=', 5]
]);
})->with(['tags' => function($q) {
$q->select('tags.id', 'value_type', 'attendee_tag.value_string', 'attendee_tag.value_int');
}])->paginate($pagination);

Related

Laravel Database Eloquent Left Join Table

Hi I would like to ask is there any way to refer the 2 foreign key to 1 primary table id?
This is my code.
$job_postings = JobPosting::select(
'job_postings.id as job_posting_id',
'job_postings.qualifications',
'job_postings.created_at',
'job_postings.updated_at',
'job_postings.created_by',
'job_postings.approved_by',
'dealerships.dealership_name',
'departments.department_name',
'positions.position_name',
'users.name as created_by_name', (**This is the issue please help**)
'users.name as approved_by_name', (**This is the issue please help**)
DB::raw("case when job_postings.status = 0 then 'Pending' else 'Approved' end status"),
)
->leftJoin('dealerships', 'job_postings.dealership_id', '=', 'dealerships.id')
->leftJoin('departments', 'job_postings.department_id', '=', 'departments.id')
->leftJoin('positions', 'job_postings.position_id', '=', 'positions.id')
->leftJoin('users', 'job_postings.created_by', '=', 'users.id', 'job_postings.approved_by', '=', 'users.id')
->where('job_postings.id', $jp_id)
->get();
$data = [];
foreach($job_postings as $j => $job_posting){
$data[] = [
'job_posting_id' => $job_posting->job_posting_id,
'dealership_name' => $job_posting->dealership_name,
'department_name' => $job_posting->department_name,
'position_name' => $job_posting->position_name,
'qualifications' => $job_posting->qualifications,
'status' => $job_posting->status,
'created_by' => $job_posting->created_by_name,
'approved_by' => $job_posting->approved_by_name,
'created_at' => $job_posting->created_at->format('D, d M Y').date(' | h:i A', strtotime($job_posting->created_at)),
'updated_at' => $job_posting->updated_at->format('D, d M Y').date(' | h:i A', strtotime($job_posting->updated_at)),
];
}
Under the last leftJoin
->leftJoin('users', 'job_postings.created_by', '=', 'users.id', 'job_postings.approved_by', '=', 'users.id')
the approved_by is a foreign key pointing to users id and created_by is also a foreign key pointing to users id.
What I am aiming at is to get the name of the user but in separate reference.
Somewhat similar to this analogy .
'users.name = created_by as created_by_name',
'users.name = approved_by as approved_by_name',
approved_by = user.id => user.name
created_by = users.id => user.name
Thanks.
leftJoin('users','job_postings.created_by','=','users.id', 'job_postings.approved_by', '=', 'users.id')
Try this,
->leftJoin('users', function($join){ $join->on('users.id', '=', 'job_postings.created_by'); $join->on('users.id', '=', 'job_postings.approved_by'); })

Combine two queries into one query Laravel

I need to combine two queries into one so i can call it one time on my foreach inside a table in my blade view. I tried using merge() but it displays two separate queries. CountofPatents are all the patents that were submitted by a user and CountofApprovedPatents are the patents which has the status of "2". Here's how it looks now:
array 0 [person_id : 1
CountofApprovedPatents: 4
status: 2]
array 1 [person_id : 2
CountofApprovedPatents: 2
status: 2]
array 2 [person_id : 1
CountofPatents: 5]
array 3 [person_id : 2
CountofPatents: 4]
Here's how it's supposed to look like
array 0 [person_id : 1
CountofApprovedPatents: 4
CountofPatents: 5]
array 1 [person_id : 2
CountofApprovedPatents: 2
CountofPatents: 4]
Here's my code so far
AdminController
$start = $request->input('start');
$end = $request->input('end');
$approvedPatents = DB::table('patents')
->select('person_id', DB::raw('count(*) as CountofApprovedPatents'))
->where([
['status', '=', 2],
['date_approved', '>=', $start],
['date_approved', '<=', $end],
])
->groupBy('person_id')
->orderBy('status', 'desc')
->get();
$totalPatents = DB::table('patents')
->select('person_id', DB::raw('count(*) as CountofPatents'))
->where([
['date_approved', '>=', $start],
['date_approved', '<=', $end],
])
->groupBy('person_id')
->orderBy('status', 'desc')
->get();
$patents = $approvedPatents->merge($totalPatents);
$results = $patents->all();
return view('admin.patents.showPatents', compact('results',
'start', 'end'));
Is it possible to combine these two queries?
$results = DB::table('patents')
->union($approvedPatents)
->union($totalPatents)
->get();
What I think you are looking for is Unions.
It'll allow you to specify a query and then join it with the final query.
Eg.
$first = DB::table('users')
->whereNull('first_name');
$users = DB::table('users')
->whereNull('last_name')
->union($first)
->get();
Try:
$approvedPatents = DB::table('patents')
->select('person_id', DB::raw('count(*) as CountofApprovedPatents, status'))
->where([
['status', '=', 2],
['date_approved', '>=', $start],
['date_approved', '<=', $end],
])
->groupBy('person_id')
->orderBy('status', 'desc')
$totalPatents = DB::table('patents')
->select('person_id', DB::raw('count(*) as CountofPatents'))
->where([
['date_approved', '>=', $start],
['date_approved', '<=', $end],
])
->groupBy('person_id')
->orderBy('status', 'desc')
->union($approvedPatents)
->get();
Otherwise you could be looking for Joins - worth a look at the docs :)
Unions: https://laravel.com/docs/5.8/queries#unions
Joins: https://laravel.com/docs/5.8/queries#joins
You can use MySQL's IF condition in your raw selection of columns.
$results = DB::table('patents')
->select('person_id',
DB::raw('sum(IF(status = 2,1,0)) as CountofApprovedPatents'),
DB::raw('count(*) as CountofPatents')
->where([
['date_approved', '>=', $start],
['date_approved', '<=', $end],
])
->groupBy('person_id')
->orderBy('status', 'desc')
->get();
The above IF condition in sum() adds 1 to the result if current row's status is 2, else it adds 0 which effectively doesn't break the sum.

How to filter by month and year on updateOrCreate in laravel?

How to filter created_at with month and year in Laravel's updateOrCreate()?
$statistik = Statistik::updateOrCreate(
[
'kode_kantor' => $map->kode_kantor,
'created_at' => whereYear('created_at', '=', date('Y-m-d')),
'created_at' => whereMonth('created_at', '=', date('Y-m-d'))
]
)->increment('poin_kunjungan');
What you are looking for cannot be done by updateOrCreate(). You would have to do a manual check. For example:
$statistik = Statistik::where('kode_kantor', $map->kode_kantor)
->whereYear('created_at', '=', date('Y-m-d'))
->whereMonth('created_at', '=', date('Y-m-d'))
->first();
if(! $statistik) {
$statistik = Statistik::create([
'kode_kantor' => $map->kode_kantor
]);
}
$statistik->increment('poin_kunjungan');

Laravel Query Builder Where OR whereIn array

I am having some trouble in Laravel using the query builder to select users based on two where clauses.
The first where clause would contain multiple where statements to select a user based on some conditions. If this fails in the OR part I would like to check simply if the user ID is in the array.
Would be grateful for some advice on how I could achieve this.
Thanks.
$rs = DB::table('tblUser')
->select('name')
->where(function($q) {
$q->where(function($q){
$q->where('fid', '=', $this->argument('fid'))
->where('type', '<', 10)
})
->orWhereIn('id', $userIdSArray);
})
->get();
$userIdSArray = [ '2', '4', '5' ];
$rs = DB::table( 'Users' )
->select( 'name' )
->where( function ( $q ) use ( $userIdSArray ) {
$q->where( function ( $q ) {
$q->where( 'fid', '=', $this->argument( 'fid' ) )
->where( 'type', '<', 10 );
})
->orWhereIn( 'id', $userIdSArray );
})
->get();
I think you need to pass $userIdSArray in Query builder . And You also forgot (;) after [->where( 'type', '<', 10 )]

Multiple Joins Same name Laravel

I have a question i have 4 tables
Deals
Lists
Lists_Galleries
List_has_deals
Lists_has_gallery
I need to obtain the img_src_list what is in the List_Galleries but from deals.
I have this var in this time
$query = ListsDeals::where( $matchDeals )
->where('stock', '>', 0)
->orwhere( $matchOtherDeals )
->whereDate('end_date', '>', date('Y-m-d'))
->limit( 4 )
->offset( 0 )
->orderBy( 'start_date' );
$deals = $query->join( 'list_has_deals', 'deals.id', '=', 'list_has_deals.deal_id' )
->join( 'lists', 'list_has_deals.list_id', '=', 'lists.id' )
->join( 'list_has_gallery', 'lists.id', '=', 'list_has_gallery.list_id' )
->join( 'lists_galleries', 'list_has_gallery.gallery_id', '=', 'lists_galleries.id' )->get();
This Give me the results but how i have the same name in all tables for example title for deals and lists that overwrite the names and dont get the values correct, how i can obtain certain columns without overwrite the others? regards.
UPDATE
This give me always the same deal for all results.
$deals = $query->join( 'list_has_deals', 'deals.id', '=', 'list_has_deals.deal_id' )
->join( 'lists', 'list_has_deals.list_id', '=', 'lists.id' )
->join( 'list_has_gallery', 'lists.id', '=', 'list_has_gallery.list_id' )
->join( 'lists_galleries', 'list_has_gallery.gallery_id', '=', 'lists_galleries.id' )
->select([ 'deals.id as deal_id', 'deals.stock as stock', 'deals.price as price', 'deals.price_reduced as price_reduced', 'deals.img_src as img_src', 'deals.title_deal as deal_title' ])->get();
UPDATE
$deals = $query->join( 'list_has_deals', 'deals.id', '=', 'list_has_deals.deal_id' )
->join( 'lists', 'list_has_deals.list_id', '=', 'lists.id' );
$other = $deals->join( 'list_has_gallery', 'lists.id', '=', 'list_has_gallery.list_id' )
->join( 'lists_galleries', 'list_has_gallery.gallery_id', '=', 'lists_galleries.id' )
->select([ 'deals.id', 'deals.stock', 'deals.price', 'deals.price_reduced', 'deals.img_src', 'deals.title_deal', 'lists_galleries.img_src_list' ])
->addSelect([ 'lists_galleries.img_src_list' ])
->get();
You can use select() to choose only those columns you want, and use aliases to rename any that clash:
$query->select(['lists.title AS title', 'lists_galleries.name AS name', 'lists.id AS id'])->get();
That way you can cherry-pick only those columns you need and deal with clashes easily.

Categories