Laravel table relationship for getting user list - php

I'm working on a laravel 5 application.
I have 3 tables:
table A: 'users'
id | name
————————————————
1 | Dave
2 | Robet
3 | Jimmy
4 | Daniel
and Table B classroom_users
user_id | classroom_id
1 | 5
4 | 5
3 | 6
4 | 5
I need to return all users 'name' for classroom 5
Please let me know what is the best way to do that. Trough model or Database join
Any help appreciated.

Assuming you have models and its relationships will be defined as below:
Classroom Model:
public function users(){
return $this->belongsToMany(User::class,'classroom_users','classroom_id','user_id');
}
User Model:
public function classrooms(){
return $this->belongsToMany(UserClassrooms::class,'classroom_users','user_id','classroom_id');
}
Now, in controller you can retrieve the users belonging to the classroom id 5 as below:
$classroom_id = 5 ;//change this to the id you want
$users = Classroom::find($classroom_id)->users()->get();

Laravel has introduced Pivot tables, which works like this
return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');
You can read more pivot on Official Docs

Related

Multiple relationships on same table with two column Laravel

If the bookstore does not have any books in stock, this bookstore can purchase books from the other bookstore it is contracted with.
book_transfers table is as follows.
ID | sender_bookstore_id | delivery_bookstore_id
1 | 2 | 3
2 | 1 | 2
3 | 3 | 1
books table
ID | store_name
1 | London Garden Book Store
2 | Englaland Cafe Book
3 | Domesday Book Store
Two-column sender_bookstore_id and delivery_bookstore_id belong to the same table. The name of this table books.
My Controller code is below:
$data = BookTransfer::join('books', 'books.id', '=', 'book_transfers.sender_bookstore_id')
->select(
'book_transfers.*',
'book_transfers.sender_bookstore_id as sender_id',
'book_transfers.delivery_bookstore_id as delivery_id',
'books.store_name as sender_store_name'
)
->groupBy('book_transfers.id')
->get();
return $data;
I can only get sender_store_name here. I need to add extra code for delivery_store_name in the above controller But I don't know how to get delivery_store_name.
Best Regards,
Using relation would be much more simpler.
// BookTransfer Model
public function sender(){
return $this->belongsTo(Book::class, 'sender_bookstore_id');
}
public function delivery(){
return $this->belongsTo(Book::class, 'delivery_bookstore_id ');
}
Your controller would look like this
$data = BookTransfer::with(['sender', 'delivery'])->get();
If you want to get the datas by join, you can join the same books table again, and alias it another name:
BookTransfer::join('books AS sender_books', 'sender_books.id', '=', 'book_transfers.sender_bookstore_id')
->join('books AS delivery_books', 'deliery_books.id', '=', 'book_transfers.delivery_bookstore_id')
->select(
'book_transfers.*',
'book_transfers.sender_bookstore_id AS sender_id',
'book_transfers.delivery_bookstore_id AS delivery_id',
'sender_books.store_name AS sender_store_name',
'delivery_books.store_name AS delivery_store_name'
)

Problem when getting records from database with relationship table

I'm having trouble relating photos to tags using an intermediate table.
In the example below, how can I select all photos that belong to tag 1 with an Eloquent relationship method in Laravel?
I have these tables:
-Photos Table
| id | name | description |
1 photo1.png ....
2 photo2.png ....
3 photo3.png ....
-Tags Table
| id | name |
1 Aesthetic
2 Dark
-Tags Relations
| id | tag_id | photo_id |
1 1 3
2 1 2
3 2 1
First of, you need to ensure that both Photos and Tags table have the relationship defined.
Under the Photos model you should have the following function:
public function tags() {
return $this->belongsToMany(
Tag::class,
"photos_tags", // the name of the pivot table
"photo_id",
"tag_id"
);
}
Under the Tags model you should have the following function:
public function photos() {
return $this->belongsToMany(
Photo::class,
"tags_photos", // the name of the pivot table
"tag_id",
"photo_id"
);
}
Now to access all the tags that are related to the Photo of id 1, you can call the following:
Photo::findOrFail(1)->tags()->get();
And the same you can do for a specific tag to get all it's photos.
Tag::findOrFail(1)->photos()->get();
Hope this will lead you to what you wish.

Laravel 5.6 - How to fetch last X guest names for room deal?

I can't figure out how to structure an efficient Eloquent query for the following scenario.
Users can stay in many locations like rooms, apartments, homes, so we have a polymorphic stayable_locations table, but we're only focusing on the room stayable_type of this table. When the staff clicks a room, we want to display all available room deals (if any are available from the room_deals table) and also the last 3 guests for each room deal (if any).
Trying to get this output from the following tables via eloquent:
Room 111 (desired output for room deals and guests below)
- Room Deal #1 -> Able, Kane, Eve
- Room Deal #2 -> Eve, Adam
------------------------------------------
$room = Room::where('id',111)->first(); // room 111
// Eloquent query, not sure how to setup model relations correctly
// To get last 3 guest names per room deal [if any] in an efficient query
$room->roomDeals()->withSpecificRoomDealLast3RoomGuestNamesIfAny()->get();
Here is the table structure:
stayable_locations table [polymorphic]:
id | stayable_id | stayable_type | room_deal_id | room_guest_id
----------------------------------------------------------------
1 | 111 | room | 0 | 3 (Steve no room deal)
2 | 111 | room | 1 | 1 (Adam room deal)
3 | 111 | room | 1 | 2 (Eve room deal)
4 | 111 | room | 1 | 4 (Kane room deal)
5 | 111 | room | 1 | 5 (Able room deal)
6 | 111 | room | 2 | 1 (Adam room deal)
7 | 111 | room | 2 | 2 (Eve room deal)
room_deals table:
id | room_id | room_deal
-----------------------
1 | 111 | Deal A
2 | 111 | Deal B
users table:
id | name
------------
1 | Adam
2 | Eve
3 | Steve
4 | Kane
5 | Able
UPDATE: Showing respective models
User Model:
class User extends Authenticatable {
public function stayableLocations() {
return $this->morphMany('App\StayableLocation', 'stayable');
}
}
RoomDeal Model:
class RoomDeal extends Model {
public function room() {
return $this->belongsTo('App\Room');
}
public function guests() {
return $this->belongsToMany('App\User', 'stayable_locations', 'room_deal_id', 'room_guest_id');
}
}
StayableLocation Model:
class StayableLocation extends Model {
public function stayable() {
return $this->morphTo();
}
public function room() {
return $this->belongsTo('App\Room', 'stayable_id');
}
}
Room Model:
class Room extends Model {
public function stayableLocations() {
return $this->morphMany('App\StayableLocation', 'stayable');
}
public function roomDeals() {
return $this->hasMany('App\RoomDeal');
}
}
Any idea how to get the desired output via an efficient eloquent query?
I figured it out from the helping comments in my question. Here we go:
Laravel does not have this out of the box (see here) so we'll have to use a third party package.
Install the staudenmeir/eloquent-eager-limit package per link directions and follow usage example.
This is what needed to change above [still used same defined relationship above for below ...], just added the use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;:
class User extends Authenticatable {
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
...
}
class RoomDeal extends Model {
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
...
}
Working query with nested limit via eloquent, thanks to the commenters and package help:
$room = Room::find(111);
$deals3Guests = $room->roomDeals() // query deals
->with(['guests' => function($query) { // eager load guests
$query->orderBy('stayable_locations.id', 'desc') // get latest guests
->limit(3); // limit to 3
}])
->get();

Laravel (5.3) Eloquent - Relationship issue

I have the following 3 tables which are normalised:
`Table: TheMovies`
id | MovieName
---------------------
1 | Zootopia
2 | Moana
3 | Toy Story
`Table: TheGenres`
id | GenreName
---------------------
21 | Action
22 | Animation
23 | Adventure
`Table: mMoviesGenres`
movieID | genreID
---------------------
1 | 21
1 | 23
2 | 22
2 | 21
3 | 23
3 | 21
As you can see in the 3rd table a movie has multiple genres, and a genre has multiple movies.
I've created TheMovies and TheGenres models in laravel.
I made sure that the relationship is made inside the models using the following code:
class TheMovies extends Model
{
public function TheGenres() {
return $this->belongsToMany('App\TheGenres', 'mMoviesGenres', 'seriesID', 'genreID');
}
}
class TheGenres extends Model
{
public function TheGenres() {
return $this->belongsToMany('App\TheMovies', 'mMoviesGenres', 'genreID', 'seriesID');
}
}
I've tested everything, and I succeeded displaying a list of genres for a particular movie, and I also succeeded displaying a list of movies for a particular genre.
The actual problem is that I want to display related movies for a particular movie based on genre.
Let's take TheMovies.id = 1 which is similar with TheMovies.id = 3, they are both Action and Adventure as you can see in the third table.
I've found out the query which is needed based on the following post:
SQL Query based on other table.
SELECT m2.movieId
FROM mMoviesGenres m1
INNER JOIN mMoviesGenres m2
ON m1.genreID = m2.genreID
WHERE m1.movieId = 1 AND
m2.movieId <> 1
GROUP BY m2.movieId
HAVING COUNT(*) >= 2
But I don't know how to transform this query in Eloquent style, and yes I can make a raw query in Eloquent, but I want to make use of the relationship created.
Please give me some advice.
You can try as:
// returns array of genre_ids associate with the TheMovies.id => 1
$genre_ids = TheGenres::whereHas('TheMovies', function($q) {
$q->where('id', 1);
})->pluck('id')->toArray();
Then use those $genre_ids to fetch the related movies as:
TheMovies::whereHas('TheGenres', function($q) use($genre_ids) {
$q->whereIn('id', $genre_ids);
})->get();
Update
Assuming you have:
$genre_ids = [21, 23];
then your query can be as:
TheMovies::whereHas('TheGenres', function($q) use($genre_ids) {
$q->whereIn('genreID', $genre_ids)
->groupBy('movieID')
->havingRaw('COUNT(DISTINCT genreID) = 2');
})->get();
Note - I have not tested it but you can give it a try.

Laravel Has Many Returns a Row even it has a value in relations table

Hi I'm using laravel eloquent for my database query. My Problem is that I can't show the data I wanted to show. I have three tables. Say Users Table, Roles Table and User_Roles table.
Users
id | Name |
1 | John |
2 | Doe |
Roles
id | Name |
1 | Admin |
2 | Employee |
3 | Manager |
User_Roles
id | user_id | role_id
1 | 1 | 2
2 | 1 | 3
3 | 2 | 3
Users has Many Roles that is saved in User_Roles table. My query is "I want to show list of Users that has no Employee roles. In the table I want to show only Doe. How can I make it laravel eloquent.
Hope someone can help!
Define roles relation in User model
public function roles() {
retrun $this->belongsToMany(\Namespace\Role::class);
}
Retrive the role
$role = \Namespace\Role::where('name', 'Employee')->first();
Get the users
$user = \Namespace\User::whereHas('roles', function($query) use ($role) {
$query->where('role_id', '!=', $role->id);
})->get();

Categories