DB::raw convert to query builder - laravel

Can you help me to convert the Raw part of my query to use query builder?
I am stuck at joining it all together:
$profile = UserProfiles::select('id')->where('alias', $profileAlias)->first();
$dbRawMessagesCount = '
(SELECT COUNT(pm.id)
FROM profile_messages pm
WHERE pm.to_profile_id='.$profile->id.'
AND pm.from_profile_id=profile_friend.id
AND pm.is_read=0) AS messages_count
';
$friends = ProfileFriend::select('profile_friend.*', DB::raw($dbRawMessagesCount))
->with('friendProfile')
->whereHas('ownerProfile', function ($query) use ($profile) {
return $query->where('id', $profile->id);
})
->orderBy('messages_count')
->paginate();

You can rewrite this into one query if ProfileFriend has a relation already set up to ProfileMessages using withCount() in the query.
$friends = ProfileFriend::with('friendProfile')
->withCount(['profileMessages' => function($q) use($profile){
$q->where('to_profile_id', $profile->id)->where('is_read', 0);
// No longer need 'from_profile_id' as it is already querying the relationship
}])
->whereHas('ownerProfile', function ($query) use ($profile) {
return $query->where('id', $profile->id);
})
->paginate();
Now if you dd($friends->first()) you will notice it has a field called profileMessages_count that gives you a count of what I'm assuming is unread messages.

Related

how to use whereHas in laravel

I am new to laravel,
I need to create a query for the db,
$query = Deal::query();
I want to use the wherehas operator.
this is my code that is worked.
else if ($group_by == 'precedence') {
if($get_deals_for == 'noprecedence'){
$get_deals_for = 0;
}
$precedenceStatus = $get_deals_for;
$query-> where('precedence', '=', $precedenceStatus);
// \Log::info('The request precedence: '.$precedenceStatus);
}
I want to add this code also to the query
if($person) {
$query->whereHas('personnel', function ($subQuery) use ($person) {
$subQuery->where('id', '=', $person);
});
}
So I need to change the first code?
how I can convert the first code to wherehas?
the first code is from table called deal, the second section is from realtionship called personnel.
the second section worked in other places in the code, I just need to fix the first section and not understand what to write in the use
I try this and get error on the last }
else if ($group_by == 'precedence') {
if($get_deals_for == 'noprecedence'){
$get_deals_for = 0;
}
$precedenceStatus = $get_deals_for;
$query-> where('precedence', '=', $precedenceStatus)
-> when ($person, function($query) use($person) {
$query->whereHas('personnel', function ($query) use ($person) {
$query->where('id', '=', $person);
});
})
}
There is a method you can use called when(, so that you can have cleaner code. The first parameter if true will execute your conditional statement.
https://laravel.com/docs/9.x/queries#conditional-clauses
$result = $query
->where('precedence', '=', $precedenceStatus)
->when($person, function ($query) use ($person) {
$query->whereHas('personnel', fn ($q) => $q->where('id', '=', $person));
})
->get();
You should also be able to clean up your precedence code prior to that using when( to make the entire thing a bit cleaner.
Querying to DB is so easy in laravel you just need to what you want what query you want execute after that you just have to replace it with laravel helpers.Or you can write the raw query if you cant understand which function to use.
using,DB::raw('write your sql query').
Now Most of the time whereHad is used to filter the data of the particular model.
Prefer this link,[Laravel official doc for queries][1] like if you have 1 to m relation ship so u can retrive many object from one part or one part from many object.like i want to filter many comments done by a user,then i will right like this.
$comments = Comment::whereHas('user', function (Builder $query) {
$query->where('content', 'like', 'title%');
})->get();
$comments = Here will be the model which you want to retrive::whereHas('relationship name', function (Builder $query) {
$query->where('content', 'like', 'title%');
})->get();
you can also write whereHas inside whereHas.
[1]: https://laravel.com/docs/9.x/eloquent-relationships#querying-relationship-existence

Laravel Query Builder relationship plus no relationship

I currently have this which works for querying a relationship:
$users = User::query();
$post_id = $request->input('post_id');
$users->whereHas('posts', function ($query) use ($post_id) {
$query->where('id', $post_id);
});
return $users->get();
But in the results of this query I would also like to include Users that do not have any posts connected to them. So the result becomes: users without posts + users with a specific post (code above). Is this possible?
Use doesntHave():
$users->whereHas('posts', function ($query) use ($post_id) {
$query->where('id', $post_id);
})->orDoesntHave('posts');

Convert SQL query into Laravel query builder

I need to convert this query into laravel query builder
select * from employee where(( age = 25 and salary = 20000) or (age =30 and salary = 30000))
If you want to group where clauses you can nest them inside closures:
DB::table('employee')
->where(function ($query) {
$query->where('age', 25)->where('salary', 20000);
})
->orWHere(function ($query) {
$query->where('age', 30)->where('salary', 30000);
})
->get();
For more information have a look at Parameter Grouping in the documentation.
Can you try this,
$data = Model::where([["age", "25"],["salary", "20000"]])
->orWhere([["age", "30"],["salary", "30000"]])
->get();

Union using With in Laravel / Lumen

I'm trying to make an union, for example:
$first = Content::selectRaw("id, title, channel_id, description")
->with('trailer')
->where('description', 'asdadadadaid');
$second = OtherTypeOfContent::selectRaw("id, title, channel_id, description")
->with('trailer')
->where('description', 'asdadadadaid');
$data = $first->union($second)->get();
For Content, trailer is associated to the table contents_trailers. For OtherTypeOfContent, trailer is associated to the table othertypeofcontent_trailers.
When I try to make the union between this two queries I get always the values of contents_trailers for the with->('trailer'), also for results of the second query. It seems that is taking relations only from the first query.
How can I solve this? Thank you!
I think the issue is that Eloquent doesn't run any attached with() instructions with the core query, but instead selects the rows desired, and then runs a query for each with() instruction to get any additional data you needed. That explains why calling toSQL() on a query builder with with() instructions returns no joins - it won't run them in that query.
So while I fear using with() for your union won't work, you can manually build joins into your query. This is what I've done in the past with unions and it's why I thought at first that toSql() would return the joins.
Here's an example of a union with joins that I have been using in one of my platforms for a while and it's working well:
<?php
namespace App\Models;
use DB;
use Illuminate\Database\Eloquent\Model;
class Example extends Model
{
/**
* Unions the query contained within with the query returned from
* buildGloballyScopedCampaignsQuery
*/
public static function findScopedToChannelId($channel_id)
{
$first = static::buildGloballyScopedCampaignsQuery();
return static::select('ac.*')
->from('ad_campaigns AS ac')
->join('ad_campaign_scopes AS acs', function ($join) use ($channel_id) {
$join->on('ac.id', '=', 'acs.campaign_id')
->where('acs.channel_id', '=', $channel_id);
})
->where(function ($query) {
$query->whereNull('ac.start_date')
->orWhere('ac.start_date', '<', DB::raw('NOW()'));
})
->where(function ($query) {
$query->whereNull('ac.end_date')
->orWhere('ac.end_date', '>', DB::raw('NOW()'));
})
->union($first)
->orderBy('rank', 'DESC')
->get();
}
public static function buildGloballyScopedCampaignsQuery()
{
return static::select('ac.*')
->from('ad_campaigns AS ac')
->leftJoin('ad_campaign_scopes AS acs', 'ac.id', '=', 'acs.campaign_id')
->whereNull('acs.id')
->where(function ($query) {
$query->whereNull('ac.start_date')
->orWhere('ac.start_date', '<', DB::raw('NOW()'));
})
->where(function ($query) {
$query->whereNull('ac.end_date')
->orWhere('ac.end_date', '>', DB::raw('NOW()'));
});
}
}

Eloquent / Laravel - Putting a WHERE Clause on a Reference Table With Chained Relationships

I have the following relationship functions in my Job model:
public function resourceTypes(){
return $this->belongsToMany('ResourceType', 'job_requests');
}
public function resources(){
return $this->belongsToMany('Resource', 'jobs_resources')->withPivot('flow_type', 'resource_type_id');
}
I am able to get an object with data from both of the above relationships using:
$job = Job::findorfail($projectId);
$result = $job->with('resources.resourceTypes')->get();
I would like to put a where clause on the jobs_resources pivot table - specifically on the column flow_type.
How would I do this?
Try something like this:
$job = Job::with('resources' => function($q) {
$q->with('resourceTypes')->where('flow_type',2);
})->findorfail($projectId);
In above you will get only those resources with flow_type = 2
I ended up using the following statement:
Job::with(['resources' => function ($query){
$query->wherePivot('flow_type', '=', '1' );
}, 'resources.resourceTypes'])->where('id', $projectId)->firstOrFail();
$result = DB::table('job')
->join('job_resources', 'job.id', '=', 'job_resources.job_id')
->join('job_requests', 'job_resources.request_id', '=', 'job_requests.id')
->where('job_resources.flow_type', '=', CONDITION)
->get();
Your table data is not clear from your input, but this method (query builder) should work

Resources