Join table with its model's default scope in Laravel - laravel-5

Currently, we can join 2 tables like
ModelA::join('table_b', 'table_a.id', '=', 'table_b.a_id');
With this approach the default scopes on model for table_b (ie: ModelB) are not applied on query. Suppose the ModelB has SoftDeletes enabled now the above join won't include whereRaw('table_b.deleted_at IS NULL'). I know i can manualy add this using following code.
ModelA::join('table_b', function($join) {
$join->on('table_a.id', '=', 'table_b.a_id')
->whereRaw('table_b.deleted_at IS NULL');
});
I want to know if there is any method to join so that it automatically apply default scope(s) in ModeB. Something like:
ModelA::joinModel(ModelB::Class, 'table_a.id', '=', 'table_b.a_id');

I used the joinSub() function to join on a subquery. So following code worked for me:
ModelA::joinSub(ModelB::select('*'), 'table_b', function($join) {
$join->on('table_a.id', '=', 'table_b.a_id');
});
By using joinSub() I can also call other scopes on ModelB like:
ModelA::joinSub(ModelB::filterThis()->filterThat(), 'table_b', function($join) {
$join->on('table_a.id', '=', 'table_b.a_id');
});

Filter out the records on related Model, the Eloquent way -
ModelA::with('modelb')->whereHas('modelb', function($query){
$query->filterThis()->filterThat();
})->get();

Laravel QueryBuilder doesn't consider Eloquent scopes while running queries.
You can simple use Eloquent instead of Query Builder. With Eloquent it can be achieved like so:
ModelA::with('modelb')->get();
Where modelb is a HasMany relationship defined in ModelA.
The above statement will produce the following query:
select * from `modela` where `modelb`.`modela_id` in (1) and `modelb`.`deleted_at` is null

Related

Laravel Query Builder in Model

I would like to know if is it possible to work in a model using query builder to make a join between 4 tables, I don't know how to use eloquent with 4 tables
this is in controller
$kurikulum = DB::table('siakad.tb_01')
->select('siakad.tb_01.*', 'siakad.krs_jadwal_aktiv.*', 'siakad.mata_kuliah.*', 'siakad.kurikulum_item.*', )
->join('siakad.krs_jadwal_aktiv', 'siakad.tb_01.staf_id', '=', 'siakad.krs_jadwal_aktiv.kdds')
->join('siakad.mata_kuliah', 'siakad.krs_jadwal_aktiv.kdmk', '=', 'siakad.mata_kuliah.kode')
->join('siakad.kurikulum_item', 'siakad.mata_kuliah.id', '=', 'siakad.kurikulum_item.mata_kuliah_id')
->get();
Please try this:
$kurikulum = DB::table('tb_01')
->select('tb_01.*', 'krs_jadwal_aktiv.*', 'mata_kuliah.*', 'kurikulum_item.*')
->join('krs_jadwal_aktiv', 'tb_01.staf_id','krs_jadwal_aktiv.kdds')
->join('mata_kuliah', 'krs_jadwal_aktiv.kdmk','mata_kuliah.kode')
->join('kurikulum_item', 'mata_kuliah.id','kurikulum_item.mata_kuliah_id')
->get();

Laravel eloquent filter on hasMany relationship

I am trying to filter on the field which has many relationships.
This is how my query looks:
Order::with(['fullOrderItems' => function($query) use ($branch) {
$query
->where('branch', $branch->key);
}])
->orderBy('dateCreated')
->toSql();
The query looks like this once outputted:
select * from `Order` where `stage` <> ? order by `dateCreated` asc
And it seems like the query doesn't even consider the nested query for filtering the branch.
My relationship in Order class is defined like this:
/*
*
* #return HasMany|null
*/
public function fullOrderItemss() : ?HasMany
{
return $this->hasMany(OrderItems::class, 'order', 'key');
}
Do you see what am I doing wrong here? How can I get the full query (including nested condition)?
To filter the Entity order with a relation you need to use whereHas
Order::whereHas('fullOrderItems', function($query) use ($branch) {
$query
->where('branch', $branch->key);
})
->with(['fullOrderItems' => function($query) use ($branch) {
$query
->where('branch', $branch->key);
}])
->orderBy('dateCreated')
->get();
You can for example get the order filtered by branch id but get all the fullOrderItems (ingore the branch id) of those fullOrderItems like this
Order::whereHas('fullOrderItems', function($query) use ($branch) {
$query
->where('branch', $branch->key);
})
->with('fullOrderItems')
->orderBy('dateCreated')
->get();
This last example will make it simpler to understand the difference between the two filters.
For why the with condition doesnt show on the query:
it is used on a second unique query that fetchs the relation using the ids of orders retrieved in the first query. that way you get the orders, each with their respective fullOrderItems with only two queries.

How i will inner join with condition in eager loading by laravel eloquent

enter code here
$wo=Warehouse_other_receive_detail::with('item_info','item_info.product_sub_group')
->where('item_info.product_sub_group->sub_group_id', 2)
->get();
$wo = Warehouse_other_receive_detail::with(['item_info'=>function( $q){
$q->getQuery()->has('product_sub_group')->where('sub_group_id', 2);
}])
->get();
//but second code is not inner join i want to first one solve
//How i will access in with function model specific column in main model ----solve this ->>
Use whereHas instead of where.You can accomplish what you want with the whereHas method which will perform a query on the relation:
$wo = Warehouse_other_receive_detail::with('item_info')->whereHas('item_info', function ($query){
$query->where('sub_group_id',2);
})->get();

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

Can I create this query with Eloquent or do I need Query Builder?

Can I use Eloquents active record to create this query or do I need to use the query builder?
SELECT
*
FROM
chat
inner join chat_member as member1
on member1.chat_id = chat.chat_id
inner join chat_member as member2
on member2.chat_id = chat.chat_id
WHERE
member1.chat_member_id = $member1ID
and member2.chat_member_id = $member2ID
WhereHas() function is to filter from relationship queries.
Make sure you have Chat and Member Models.
And Chat Model has members() relationship.
Then you can achieve your mysql query as follow.
Chat::whereHas('members', function ($query) {
$query->where('chat_member_id', $member1ID);
})
->whereHas('members', function($query) {
$query->where('chat_member_id', $member2ID);
})
->get();
Update, I fixed a syntax issue

Resources