Laravel eloquent model - get rows using intermediate table - php

I have 3 tables users, posts and photos.
post table has one - one relation to photos & users like, post.user_id=users.id and post_photo_id=photos._id.
I use
public function posts(){
return $this->hasMany('Post');
}
and I get all the posts by user using $user->posts().
What I need is to get all the photos by user, something like $user->photos.
SELECT photos.*
FROM photos
JOIN posts ON posts.photo_id=photos.id
JOIN users ON users.id=posts.user_id
WHERE user_id=1
Note: photos table has just 2 fields, id & photo.

In your User model, create a relationship like
Class User Extends Model
{
...
public function photos()
{
return $this->hasManyThrough('Photos','Posts','photo_id','id');
// Params (all strings): Final Model, Intermediate Model, Intermediate Model Key (posts), final Model Key (your photos)
}
public function Posts()
{
return $this->hasMany('Posts');
}
...
}// end class
Then in your controller, you'll just call your data with the relationships. This assumes you're hinting, but you get the idea...
$picturesByUser = $this->user->with(['posts','photos'])->find($id);
finally, in your blade, just eager load them...
#foreach(...)
$user->photos->pathToPicture;
$user->posts->pictureTitle;
#endforeach
Straight out of the Laravel Docs

Related

Laravel table relationship to pivot table

I'm confused on how to get my model setup in laravel with a table that is connected to a pivot table.
Here's the problem
Say I have
Locations
id
name
area_types
id
name
area_type_location (Pivot table)
id
location_id
area_type_id
area_test
id
area_type_location_id
clean
headCount
Relationship between the tables are different areas type belongs to different locations.
i.e: beach, 25m pools, kids pools, bbq, etc
area_test is connected to the pivot table because the test has to be generated from area that exists, in this case it is area that is registered under different locations. Thus it has to be tested daily, measured, etc.
I understand the structure between area_types and locations for many to many relationship, however I can't get over my head of how do i structure my area_test model? How do I get the data from locations table -> where are my test?
Should I create a model for my pivot table? Is that a good practice in laravel?
Does anyone has the same use case?
I read about eloquent has many through
relationship but I understand that it does not mention about getting through pivot table. I don't quite get if my use case is the same.
Thanks
Finally, apparently there are a couple of way to get data from locations table to area_tests
Tried at tinker and it works,
First Option
I need to create a Pivot model for my Pivot table:
class LocationAreaType extends Pivot{
public function location(){
return $this->belongsTo(Location::class);
}
public function areaType(){
return $this->belongsTo(AreaType::class);
}
public function AreaTests(){
return $this->hasMany(AreaTest::class, 'area_type_location_id');
}
}
I can use hasManyThrough relation that I need to create in my Location table
public function areaTests()
{
return $this->hasManyThrough(
AreaTest::class,
LocationAreaType::class,
'location_id',
'area_type_location_id');
}
this way I can get the areaTests easily by $location->areaTests, My problem was not determining the area_type_location_id as foreign. You need to determine this, apparently when I extends pivot and use hasMany laravel does not auto recognise the Foreign key by itself.
Second option
Another way to access it is from the relation table, I can define withPivot in the areaTypes() relation then access it like this:
$location->areaType[0]->pivot->areaTests
Since laravel only recognise foreign key from both tables location_id and area_type_id, I have to include the id of the pivot table to get the AreaTest table data
So in the Location model I have to get the column
public function areaTypes()
{
// Get the ID of the pivot table to get the poolTests table (connected with ID column)
return $this->belongsToMany(AreaType::class)
->using(AreaTypeLocation::class)
->withPivot('id');
}
There is no need to create a new model for pivot table.
Just declare in Location model below code:
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function area_types()
{
return $this->belongsToMany('App\AreaType', 'area_type_location', 'location_id', 'area_type_id');
}
and declare below code in AreaType model:
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function locations()
{
return $this->belongsToMany('App\Location', 'area_type_location', 'area_type_id', 'location_id');
}
every time you need to get for example the locations of an area_type in every controller, you can call the function like this: $areatype->locations()->get();
Don't forget to create area_type_location table migration.

Laravel polymorphic relationship with pivot

Assume I have posts and videos that can be seen by multiple users.
- users
- id
- posts
- id
- videos
- id
- user_accessables (pivot)
- id
- user_id
- accessable_id
- accessable_type
In an example like that, I have set my User relationship like so but something feels wrong
class User extends Model {
public function posts() {
return $this->morphedByMany(
Post::class,
'accessable',
'user_accessables'
);
}
public function videos() {
return $this->morphedByMany(
Video::class,
'accessable',
'user_accessables'
);
}
public function allowedEntities() {
return ($this->posts)->merge($this->videos);
}
}
With the allowedEntities() I can get a collection of both models joined together.
However, I think the use of polymorphic relationship is returning a collection of entities through relationship rather than needing a combiner relationship, right?
I am having problems with understanding polymorphic with pivot table (the tag example in documentation doesn't seem like same scenario).
Because now I can't do:
$collection = collect(); // multiple models of Video & Post
$user->allowedEntities()->sync($collection);
As #Jonas Staudenmeir said is not possible to have a relationship that returns all related model, BUT you can define a method on the model that returns a query builder object with all entities you need (search with on the docs).

Get Table values using Eloquent Model in Laravel5

I want to find username from post_id using Post_Tag table using Eloquent model. Here are the tables.
User Table
user_id(pk)
username
Post Table
post_id(pk)
user_id(fk)
Post_Tag Table
post_id(fk)
Tag_id(fk)
How can I fetch username from User table using Post_Tag table. Here is what I have tried:
class Post extends Eloquent {
public function user() {
return $this->belongsTo('App\User');
}
}
class PostTag extends Eloquent {
public function post() {
return $this->hasMany('App\Post');
}
}
$posts = PostTag::with('post')->where('tag_id','=','20')->get();
One tag belongs to Multiple posts and each post will belong to an owner/User. Thank you in advance.
If your relations are working this would do it:
PostTag::find(20)->post()->first()
->user()->first()->username;
You say one Tag belongs to many posts, how do you choose which of the many posts you want to get the user's username?
Do you want to get all the users who have a post with some PostTag?
Edit: Try this:
PostTag::find(20)->with(['post', 'post.user'])->get();
Run this in artisan tinker or dd the result so you can see what is returned, I think this solves your problem. Just note that this may return a lot of data, you could use take instead of get to limit the results.

Laravel eager loading, loaded table fields

how can I choose which fields I want to get from the with ORM eloquent. For example
$tourTeams = Tournament::with('teams')->where('id', $tourId)->first();
From the teams relation I want only to get the name (without the id and timestamps).
I didn't it in the documentation. For the Tournament eloquent I can do it via the get function while passing it an array of fields names, like this: get(array('name', 'id')). But how do I do this on the Team eloquent?
Note: here is how Team related to Tournament, this code taken from the Tournament eloquent file:
public function teams()
{
return $this->belongsToMany('Team', 'Tournament_Team');
}
You can get specific columns from the relation like this:
$tourTeams = Tournament::with(['teams'=>function($q){
$q->select('id','name');
}])->where('id', $tourId)->first();

Laravel 4 - Pivot Tables

I understand how relationships in Laravel (Eloquent) work, but let's say I've got a many to many relationship between two models, call them Posts and Tags.
So our relationship is fine, from Posts I can access all the related Tags, and from Tags I can get all related Posts.
But... I have the ID of a row in the pivot table, and want to return both the Post and Tag relating to this row, how would I go about doing this?
EDIT:
Let's introduce a third Model, called Foo. This contains the ID of the row in the pivot table,
is there anyway I can create a relationship from this to the two other models?
A Model for your pivot:
<?php
class PostTagPivot
{
public function Post()
{
return $this->belongsTo('Post');
}
public function Tag()
{
return $this->belongsTo('Tag');
}
}
And retrieve Post and Tag via:
$Post = PostTagPivot::find($fooBarId)->Post;
$Tag = PostTagPivot::find($fooBarId)->Tag;

Categories