how to use pivot value inside Eloquent in Laravel 5? - laravel

for example table1 and table2 and connected together by a pivot table
table1: {
pivot: {
pivot_value1: 1
},
table2: {
....
}
}
code:
table1::with(['table2' => function($q) {
$q->where('table2_property1', 'pivot_value1') // <= how to access pivot value?
}])

In your model where you are defining relationship , we need to use withPivot() function while making relationship e.g in your table1 Model we have;
class Table1 {
public function table2() {
return $this->belongsToMany('App\Table2')->withPivot('column1', 'column2');
}
}
Normally in pivot table there are three cloumns, in addition if we have added extra columns let's say column1 & column2, we can get the values of these extra cloumns. Here column1 & column2 are the extras columns in your pivot tables,
To access these columns values:
$table1 = Table1::find(1);
foreach ($table1->table2 as $table) {
echo $table->pivot->column1;
echo $table->pivot->column2;
}
Another Solution using query builder:
Table1::whereHas('table2', function($q) {
$q->where('table2_property1', 'pivot_value1');
})
->get();
The above code is just an example, you can do modify it that perfect your needs. Hope it helps.

Related

Laravel Pivot Table, Get Room belonging to users

The structure of my pivot table is
room_id - user_id
I have 2 users that exist in the same room.
How can I get the rooms they both have in common?
It would be nice to create a static class to have something like this.
Room::commonToUsers([1, 5]);
Potentially I could check more users so the logic must not restrict to a certain number of users.
Room::commonToUsers([1, 5, 6, 33, ...]);
I created a Laravel project and make users, 'rooms', 'room_users' tables and their models
and defined a static function in RoomUser Model as below :
public static function commonToUsers($ids)
{
$sql = 'SELECT room_id FROM room_users WHERE user_id IN (' . implode(',', $ids) . ') GROUP BY room_id HAVING COUNT(*) = ' . count($ids);
$roomsIds = DB::select($sql);
$roomsIds = array_map(function ($item){
return $item->room_id;
}, $roomsIds);
return Room::whereIn('id', $roomsIds)->get();
}
in this method, I use self join that the table is joined with itself, A and B are different table aliases for the same table, then I applied the where condition between these two tables (A and B) and work for me.
I hope be useful.
I don't know the names of your relations, but I guess you can do like this :
$usersIds = [1, 5];
$rooms = Room::whereHas('users', function($query) use ($usersIds) {
foreach ($usersIds as $userId) {
$query->where('users.id', $userId);
}
})->get();
It should work. whereHas allows you to query your relation. If you need to have a static method, you can add a method in your model.
There might be a more efficient way but laravel collection does have an intersect method. You could create a static function that retrieves and loop through each object and only retain all intersecting rooms. something like this
public static function commonToUsers($userArr){
$users = User::whereIn('id',$userArr)->get();
$rooms = null;
foreach($users as $user){
if($rooms === null){
$rooms = $user->rooms;
}else{
$rooms = $rooms->intersect($user->rooms);
}
}
return $rooms;
}
This code is untested but it should work.
Room has many users, user has many rooms, so you can find the room which have those two users.
If your pivot table's name is room_users, then you can easily get the common room like this:
public static function commonToUsers($user_ids) {
$room = new Room();
foreach($user_ids as $user_id) {
$room->whereHas('users', function($query) use ($user_id) {
$query->where('room_users.user_id', $user_id);
});
}
return $room->get();
}
This code will convert to raw sql:
select *
from `rooms`
where exists (
select * from `rooms` inner join `room_users` on `rooms`.`id` = `room_users`.`room_id` where `rooms`.`id` = `room_users`.`room_id` and `room_users`.`user_id` = 1
)
and exists
(
select * from `rooms` inner join `room_users` on `rooms`.`id` = `room_users`.`room_id` where `rooms`.`id` = `room_users`.`room_id` and `room_users`.`user_id` = 5
)

Seeding a pivot table in Laravel 5 using factory

public function run()
{
factory(App\ProjectProcurementManagementPlan::class, 5)->create()->each(function ($a) {
$a->paps()
->saveMany( factory(App\ProjectsProgramsActivities::class, 5)->make() )
->each(function ($b) {
$b->pap_schedules()->save(factory(App\PapSchedule::class)->make());
$b->procurement_modes()-> ????????;
});
});
}
I have this code here. I want to seed a pivot table after creation of each of the models indicated above. $b->procurement_modes()-> ???????? will be the part where I do the factory stuff to a pivot table.
the pivot table looks like this.
| id | pap_id | procurement_mode_id |
My plan is, to , for the sake of simplicity, I'll just attach a single procurement_mode_id to each ProjectsProgramsActivities created.
I have tried to use
$b->procurement_modes()->sync(factory(App\PAPProcurementMode::class)->make());
but it gives me a
SQLSTATE[HY000]: General error: 1366 In
correct integer value: '' for column 'procurement_mode_id' at row 1 (SQL: insert
into paps_procurement_modes (pap_i, procurement_mode_id) values (1, ))
The factory for that pivot table is this
$factory->define(App\PAPProcurementMode::class, function (Faker $faker) {
return [
'procurement_mode_id' => 1,
];
});
So what would be the best way to do this ?
For those who will encounter problems like this.
I simply
$ids = 1;
$b->procurement_modes()->sync($ids);

laravel join statement includes both rows instead of only one

My query selects the data for movies but I only want to have one row in the join statement I use skip and limit but if I use the word "first" the query fails so at the moment I'm getting duplicates of data mainly two of them are the same because I have two rows of data in my join statement how do I get it to only select one row I have tried using distinct but it's not doing anything.
Query:
Movie::select(['movies.id', 'images.small as poster', 'title', 'release_date',
'movies.created_at', 'movies.updated_at'])->leftJoin('images', function($join) {
$join->on('images.imageable_id', '=', 'movies.id')
->where('images.imageable_type', '=', 'App\Movie')->skip(1)->take(1);
})
Use
->groupBy('distintColumnName')
to select unique rows
Hey #ONYX have you thought about using Eloquent relationships rather than building the select statement like that?
if you had the correct relationship setup in your Movie model then you could just say ->with('poster')
Then you could just set this function on your Movie model
public function poster()
{
return $this->hasMany(Images::class)->first();
}
or
public function images()
{
return $this->hasMany(Images::class);
}
public function poster()
{
return $this->images()->first();
}

Laravel eloquent table joined to itself, how to get 1 array with all values

I am using a table employee that is joined to itself for the manager.
Employee
id
name
manager_id (FK to Employee)
I am using the following model for Employee:
public function my_employees()
{
return $this->hasMany('App\Employee', 'manager_id');
}
public function my_manager()
{
return $this->belongsTo('App\Employee', 'manager_id');
It is working fine because I can use the my_employees function on an employee and it will get me all the records linked to this employee.
Now I would like to get a table with all the employees where the column manager_id is replaced by manager_name. How can I achieve this with Eloquent?
Not using Eloquent, I do:
$employee = DB::table('employee')
->select('employee.id', 'employee.name', 'employee.manager_id','manager.name AS manager_name')
->join('employee AS manager', 'employee.manager_id','=','manager.id');
This gets me of course what I want but I would like to understand how to do it with Eloquent only.
Thanks.
Exactly the same way.
$employees = Employee::select('employee.id', 'employee.name', 'employee.manager_id', 'manager.name AS manager_name')
->join('employee AS manager', 'employee.manager_id', '=', 'manager.id')
->get();
You could also do this shown below. But then you need to access the manager name from the relationship object.
$employees = Employee::with('my_manager')->get();
foreach($employees as $employee) {
echo $employee->my_manager->name;
}
Edit
You can add any constraint to the eager loaded relationship.
$employees = Employee::with(['my_manager' => function($query) {
$query->select('manager_id', 'name');
}])->get();

How can I write the join query using eloquent ORM of Laravel

Currently I have three tables one is property table having following columns:
id
name
description
2nd is tags table having following colums:
id
tag_name
tag_status
3rd is the pivot table having following columns:
id
tag_id
property_id
Now in Property Model I have defined the relation with pivot table like this:
public function tags()
{
return $this->belongsToMany('Tag');
}
and in Tag Model I have defined the relation with pivot table like this:
public function properties()
{
return $this->belongsToMany('Property');
}
Now what I need to now is how can I write the following query on these three tables using eloquent ORM of Laravel:
$propertyTags=Property::join('property_tag', 'properties.id', '=', 'property_tag.property_id')
->join('tags', 'tags.id', '=', 'property_tag.tag_id')
->where('properties.id','=',$property_id)
->get(['tags.tag_name','tags.id']);
you can try
$property_obj = Property::find($property_id);
$property_tags = $property_obj->tags->all();
or using eager loading
$property_with_tags = Property::with('tags')->where('id','=',$property_id)->get();

Resources