I'm having a hard time understanding on how to model a triple relation in Laravel.
I have 3 models: User, Tour and Photo
Each tour has users associated with it and all users can post photos. Which means the database looks something like this:
id , tour_id, user_id, photo_id
This way I know which user posted which photo for which tour. My question is, how do I model this in Eloquent?
Update Based on your last comment.
The simplest answer to your question is by using relations belongsToMany and hasMany.
Let me explain.
You need 4 table users, tours, tour_user and photos.
users table contain id,name
tours table contain id,name,
tour_user table contain id,tour_id,user_id
photos table contain id,name,user_id,tour_id
Why belongsToMany ? because each user has more than one tour and each tour has more than one users. So we link both tables by using a third table tour_user. It also helps in normalization.
Now that we have examined the table structure for the relationship, let's define it on the User model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function tours()
{
return $this->belongsToMany('App\Tour');
}
/* To retrieve photos of a user */
public function photos()
{
return $this->hasMany('App\Photo');
}
}
Tour model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Tour extends Model
{
public function users()
{
return $this->belongsToMany('App\User');
}
/* To retrieve photos of a tour*/
public function photos()
{
return $this->hasMany('App\Photo');
}
}
Now Photo model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Photo extends Model
{
public function users()
{
return $this->belongsTo('App\User');
}
public function tours()
{
return $this->belongsTo('App\Tour');
}
}
Now let find all tour of a specific user by using
public function show($id)
{
$user = User::find($id);
return view('show')->withUser($user) ;
}
Now in show view, page lets extract all tours of that user and his photos
#foreach($user->tours as $tour)
{{ $tour->name }}
#foreach($tour->photos as $photo)
#if($user->id == $photo->user_id)
{{ $photo->name }}
#endif
#endforeach
#endforeach
You should have: one to many Tour > user and
one to many User > Photo
include this function in your Tour model.
public function allusers()
{
return $this->hasMany(User::class);
}
and this in your User model.
public function allphotos()
{
return $this->hasMany(Photos::class);
}
Then you can get a tour $tour = Tour::find(1);
and just use the function to get the users with this:
$usersOnTour = $tour->allusers();
First make sure you have a user_id foriegn key field in your tour model and 'photo_id' foriegn key field in your user moel
the trick is to have user model with a hasOne/hasMany relationship with photo model and then have tour model with a hasOne/hasMany relationship with the user model.
1 - first in your user model define a relationship like this
public function photo()
{
return $this->hasOne('App\Photo');
}
2 - In your tour model define a hasMany relationship like this
public function users()
{
return $this->hasMany('App\User');
}
so when you fetch a tour model like
$a = tour::All();
you can do
$a->users->'field_in_user_table'
or
$a->users->photo; // to get the photo field value from photo table
Related
I want to have two tables one for Employees and one for Companies, both Employees & Companies should be registered within the site, thus they should have records in the users table provided with Laravel. How should I structure the relationships between the models, should I go for polymorphic relationships or use one to one?
The answer is to add two columns to the "users" table: userable_id and userable_type. userable_id will be used to store the id of the row for the entity (Employee or Company), and the userable_type will hold the class path for the Eloquent model.
in create_users_table migration file add these two lines:
// ...
$table->integer('userable_id')->unsigned();
$table->string('userable_type');
// ...
in User.php model:
class User extends Model {
// Add this declaration.
public function userable()
{
return $this->morphTo();
}
}
in your Company.php model:
class Company extends Model
{
// Add this method.
public function user()
{
return $this->morphMany(User::class, 'userable');
}
}
in the Employee.php model do the same as above:
class Employee extends Model
{
// Add this method.
public function user()
{
return $this->morphMany(User::class, 'userable');
}
}
Now you should be able to access the user by running:
App\Company::all()->get(1)->user;
// or
App\Employee::all()->get(1)->user;
And access the entity with this one-liner:
App\User::all()->get(1)->userable;
Basically I have three models , Wedding , invites , and users. Weddings has invites and invites has users ( keeping in mind that user can belong to multiple invites ). I want to access $wedding->users directly.
Wedding.php
class Wedding extends Model
{
public function invites()
{
return $this->hasMany(Invite::class);
}
...
Invites.php
class Invite extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
...
Tables:
Wedding
- id
- name
Invite
- invite_date
- wedding_id
- user_id
User
- id
- name
- email
And i want to access retrieve users directly , using $wedding->users
What's the relationship between Wedding and users?
It's a BelongsToMany relationship:
public function users() {
return $this->belongsToMany(User::class, 'invites');
}
Add this method to your Widding class
public function users()
{
return $this->hasManyThrough('App\User', 'App\Invite');
}
for more about hasManyThrough see the documentation.
I am not much familiar with eloquent orm in laravel
I have 3 tables they are
-- leads
|
Lead_appointments
and users table
since lead_appointments belongs to leads references id on leads by lead_id
the leads_appointments has a column called created_by with user's id in it
I am trying to query user's name and email along with the result as another column when query using eloquent
Lead Model
class Leads extends Model
{
public function appointments()
{
return $this->hasMany('App\Models\LeadsAppointments', 'lead_id');
}
}
My eloquent query in controller
return $this->lead->with('appointments')->find($id);
the result is like this
In under appointments i also want user email and name along with created by in it
But I couldn't figure it out
Add a relation to LeadAppointment model like this:
class LeadAppointment extends Model
{
public function users()
{
return $this->belongsTo('App\Models\User', 'created_by');
}
}
and change leads model like this:
class Leads extends Model
{
public function appointments()
{
return $this->hasMany('App\Models\LeadsAppointments', 'lead_id')->with('users');
}
}
i got pivot table that consist of
account_id
article_id
created_at
updated_at
how to retrieve all of them in View. I have 2 model account and article
class Account extends Model
{
public function articles()
{
return $this->belongsToMany('App\Article','accountsarticles')->withPivot('account_id','article_id')->withTimestamps();
}
}
class Article extends Model
{
public function accounts()
{
return $this->belongsToMany('App\Account','accountsarticles')->withPivot('account_id','article_id')->withTimestamps();
}
}
And also i have controller like this
class AccountsArticlesController extends Controller
{
public function index()
{
/*If i use this 1 i can get all of column data*/
$accountsarticles=DB::table('accountsarticles')->get();
/*If i use this 1 i only get created_at and updated_at*/
$acc = Account::all();
return view('accountsarticles.index',['accountsarticles'=>$accountsarticles]);
}
}
For now i retrieve it like this without using MVC
#foreach($accountsarticles as $article)
<tr>
<td>{{$article->created_at}}</td>
<td>{{$article->updated_at}}</td>
<td>{{$article->account_id}}</td>
<td>{{$article->article_id}}</td>
</tr>
#endforeach
I wondering how to retrieve all column in that pivot so i can show all data in that column when the view returned.
Using the following syntax $model->pivot->field_name
In your case, it'll be:
//to fetch account id
$article->pivot->account_id
//to fetch article id
$article->pivot->article_id
I have two tables like below:
users table:
id - fname - lname
users_projects table:
id - user_id - title
my models are inside a directory called Models:
Users model :
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Users extends Model
{
//
public function usersProjects()
{
return $this->belongsTo(UsersProjects::class);
}
}
UsersProjects model:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class UsersProjects extends Model
{
protected $table = 'users_projects';
//
public function users()
{
return $this->hasOne(Users::class);
}
}
now, I want to show last projects :
$projects = UsersProjects::limit(10)->offset(0)->get();
var_dump($projects);
return;
but my var_dump shows last projects ! I want to have fname and lname ! where is my wrong ?
I think you may have your relationships set up a little wrong. If a user can have more than one project, in your user model ...
public function usersProjects()
{
return $this->hasMany(UsersProjects::class);
}
You might want to use a little simpler naming too ...
public function Projects()
{
return $this->hasMany(UserProject::class);
}
(or simply Project if you don't have any other "Project" models)
The in your "Project" class ...
public function User()
{
return $this->belongsTo(User::class);
}
(assuming you rename your model to User instead of "Users". Your table name should be "users" but a model is by nature a singular object. So it's appropriate to call it "User" - and your UsersProjects model should just be UserProject or just Project)
Now if you call the method something other than "User" you will have to add the foreign key name ...
public function SomeOtherName()
{
return $this->belongsTo(User::class, 'user_id');
}
Then ...
$projects = Project::with('User')->limit(10)->offset(0)->get();
Will return a collection of projects with the User eager-loaded. (assuming you have renamed your UsersProjects model to "Project")
#foreach($projects as $project)
...
First Name: {{ $project->User->fname }}
...
#endforeach
Could you specify the relationships between the tables? (one to one, one to many) at first sight, I think that the relations are wrong