Laravel nested whereIn from multiple tables - laravel

I'm using Laravel 5.7. How do i rewrite below code as a single nested query?
I'm currently fetching the result using 2 database queries. I go through some of the answers in stackoverflow, but i still have doubts in nesting multiple tables
$connectedParts = DB::table('part_connections as c')
->join('parts_master as p', 'p.id', '=', 'c.part_number_id')
->where('c.part_number_id', $partId)
->where('p.id', $partId)
->pluck('connected_to');
$connectedComponents = DB::table('part_connections as pc')
->join('parts_master as pm', 'pm.id', '=', 'pc.connected_to')
->where('part_number_id',$partId)
->where('pm.part_type','1')
->whereIn('connected_to', $connectedParts)
->pluck('connected_to');
Any help would be greatly appreciated.

Set your relationship properly in your model first then try this query:
//PartConnection model - add for eager loading
public function master() {
return $this->belongsTo('PartMaster::class', 'connected_to', 'id');
}
$query = PartConnection::whereHas(‘master’, function($qry)) use ($partId) {
$qry->where(‘parts_master.id’, $partId);
$qry->where(‘parts_master.part_type’, 1);
});
$query->where(‘part_number_id’, $partId);
$connectedComponents = $query->get();
update
Try this then:
$connectedComponents = DB::table('part_connections as pc')
->join('parts_master as pm', function($join) {
$join->on('pc.connected_to', '=', 'pm.id');
$join->on('pc.part_number_id', '=', 'pm.id');
}) //updated this - removed ;
->where('part_number_id',$partId)
->where('pm.part_type','1')
->get();

Related

Trouble converting an SQL query to Eloquent

Trying to get this query to work in eloquent
A user can be in multiple teams however I want to generate a list of users NOT in a specific team. The following SQL query works if executed directly but would like to make it cleaner by converting it to eloquent
SELECT * FROM users LEFT JOIN team_members ON team_members.member_id = users.id WHERE NOT EXISTS ( SELECT * FROM team_members WHERE team_members.member_id = users.id AND team_members.team_id = $team_id )
This should provide a list of all the users that are not members of team $team_id
This is a guess ad you do not give much info on your Eloqent models but here is a hint of where to go:
User::doesnthave('teamMembers', function($builder) use($team_id){
return $builder->where('team_members.team_id');
});
That is assuming you have a "User" model with a "teamMembers" relationship setup on it
You may have a closer look in the Laravel docs for doesntHave
Laravel 5.8
Let's assume you have model name "User.php"
& there is method name "teamMembers" in it.
Basic
$users = User::doesntHave('teamMembers')->get();
Advance
use Illuminate\Database\Eloquent\Builder;
$users = User::whereDoesntHave('teamMembers', function (Builder $query) {
$query->where('id', '=', {your_value});
})->get();
You can find details description in this link >>
https://laravel.com/docs/5.8/eloquent-relationships#querying-relationship-absence
Laravel 5.2
Example:
DB::table('users')
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('orders')
->whereRaw('orders.user_id = users.id');
})
->get();
Check this link for advance where clause:
https://laravel.com/docs/5.2/queries#advanced-where-clauses
You can use below example
$list = User::leftJoin('users', 'users.id', '=', 'team_members.member_id')
->whereNotExists(function ($query) use ($team_id) {
$query->from('team_members')
->whereRaw('team_members.member_id = users.id')
->where('team_members.team_id', '=', $team_id);
})
->get();

Join Laravel tables

I have got three tables Kudos, Kudoscategories, and specialpost. I need to get the data from those tables and check the post id using a where condition.
I have attached the database table screenshot here
I already tried this, but it's not getting any result.
$results = DB::table('kudos')
->select('kudos.description','kudoscategory.catname','kudoscategory.image','kudos.spid')
->join('kudoscategory', 'kudoscategory.id', '=', 'kudos.categoryid')
->where('kudos.spid', '=', $post_id)
->first();
return $results;
What I need to do is get the results using below where condition newsfeed_special_posts.main_post_id = kudos.spid
You must add another join with newsfeed_special_posts.
The query will be like,
$results = DB::table('kudos')
->select('kudos.description','kudoscategory.catname','kudoscategory.image','kudos.spid')
->join('kudoscategory', 'kudoscategory.id', '=', 'kudos.categoryid')
->join('newsfeed_special_posts', 'newsfeed_special_posts.main_post_id', '=', 'kudos.spid')
->where('kudos.spid', '=', $post_id)
->first();
return $results;
Though this is not a good practice for laravel. using laravel eloquent relationships will be more efficient for these results.
https://laravel.com/docs/5.8/eloquent-relationships
you can still do it this way. still efficient to avoid sql injection since you are getting all the record from the 3 tables. seeing your table above, its not properly normalised. anywaye try this.
$results = DB::table('kudos')
->leftjoin('kudoscategory', 'kudoscategory.id', '=', 'kudos.categoryid')
->leftjoin('newsfeed_special_posts', 'newsfeed_special_posts.id', '=', 'kudos.spid')
->where('kudos.spid', '=', $post_id)
->first();
return $results;
you can try this code
at first, create model Kudos,KudosCategory,NewsfeedSpecialPosts
Kudos Model
public function kudoscategory_dta()
{
return $this->belongsTo('App\Model\KudosCategory','categoryid');
}
public function newsfeed_special_posts_dta()
{
return $this->belongsTo('App\Model\NewsfeedSpecialPosts','spid','main_post_id ');
}
controller
Kudos::with('kudoscategory_dta','newsfeed_special_posts_dta')->first();

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

Eloquent Complex Joins

i have made a scope
public function scopeCollaborative($query){
return $query->leftJoin('collaborative', function($join){
$join->on('imms.phone2', '=', 'collaborative.phone')
->orOn('imms.phone', '=', 'collaborative.phone')
->where('collaborative.user_id', '=', App('CURUSER')->id);
});
}
in Query log this scope adds:
left join `cs_collaborative` on
`cs_imms`.`phone2` = `cs_collaborative`.`phone` or
`cs_imms`.`phone` = `cs_collaborative`.`phone` and
`cs_collaborative`.`user_id` = 3
but i need to have:
left join `cs_collaborative` on
(`cs_imms`.`phone2` = `cs_collaborative`.`phone` or
`cs_imms`.`phone` = `cs_collaborative`.`phone`) and
`cs_collaborative`.`user_id` = 3
i didn't found a good solution, JoinClause have functions: On, orOn, where, orWhere.
but non of all can take function as input and to group query...
someone ideals?
Laravel doesn't let you build such join clause, so you need this to make it work:
public function scopeCollaborative($query){
return $query->leftJoin('collaborative', function($join){
$join->on('imms.phone2', '=', 'collaborative.phone')
->where('collaborative.user_id', '=', App('CURUSER')->id)
->orOn('imms.phone', '=', 'collaborative.phone')
->where('collaborative.user_id', '=', App('CURUSER')->id);
});
}
you can consider to use Doctrine ORM is more powerfull, bur less easy in the beginning...

Laravel eloquent and relationship

I have a code:
$response = $this->posts
->where('author_id', '=', 1)
->with(array('postComments' => function($query) {
$query->where('comment_type', '=', 1);
}))
->orderBy('created_at', 'DESC')
->limit($itemno)
->get();
And when I logged this query with:
$queries = \DB::getQueryLog();
$last_query = end($queries);
\Log::info($last_query);
In log file I see follow:
"select * from `post_comments` where `post_comments`.`post_id` in (?, ?, ?, ?) and `comment_type` <> ?"
Why is the question mark for comment_type in the query?
Update #1:
I replaced current code with following and I get what I want. But I'm not sure it is OK. Maybe exists many better, nicer solution.
$response = $this->posts
->where('author_id', '=', 1)
->join('post_comments', 'post_comments.post_id', '=', 'posts.id')
->where('comment_type', '=', 1)
->orderBy('created_at', 'DESC')
->limit($itemno)
->get();
Behind the scene the PDO is being used and it's the way that PDO does as a prepared query, for example check this:
$title = 'Laravel%';
$author = 'John%';
$sql = "SELECT * FROM books WHERE title like ? AND author like ? ";
$q = $conn->prepare($sql);
$q->execute(array($title,$author));
In the run time during the execution of the query by execute() the ? marks will be replaced with value passed execute(array(...)). Laravel/Eloquent uses PDO and it's normal behavior in PDO (PHP Data Objects). There is another way that used in PDO, which is named parameter/placeholder like :totle is used instead of ?. Read more about it in the given link, it's another topic. Also check this answer.
Update: On the run time the ? marks will be replaced with value you supplied, so ? will be replaced with 1. Also this query is the relational query, the second part after the first query has done loading the ids from the posts table. To see all the query logs, try this instead:
$queries = \DB::getQueryLog();
dd($queries);
You may check the last two queries to debug the queries for the following call:
$response = $this->posts
->where('author_id', '=', 1)
->with(array('postComments' => function($query) {
$query->where('comment_type', '=', 1);
}))
->orderBy('created_at', 'DESC')
->limit($itemno)
->get();
Update after clarification:
You may use something like this if you have setup relation in your Posts model:
// $this->posts->with(...) is similar to Posts::with(...)
// if you are calling it directly without repository class
$this->posts->with(array('comments' =. function($q) {
$q->where('comment_type', 1);
}))
->orderBy('created_at', 'DESC')->limit($itemno)->get();
To make it working you need to declare the relationship in your Posts (Try to use singular name Post if possible) model:
public function comments()
{
return $this->hasmany('Comment');
}
Your Comment model should be like this:
class Comment extends Eloquent {
protected $table = 'post_comments';
}

Resources