i am unable to find best suited relations for creating a courier website.
my requirements are
a branch can have many users
a franchise can be associated with only one user
a branch can have many franchise
branch user can access through franchise models
Note:- branch and franchise have different profiles
I want to avoid directly jumping to the answer and convert the statements you have given into more easier relationship descriptions :
- 1 branch has many franchises
- 1 user has 1 franchise
This will then help you to understand :
- branch <> franchises is one to many relationship
- franchise <> user is one to one relationship
Models :
Branch Model :
public function franchises()
{
return $this->hasMany(Franchise::class);
}
Franchise Model :
public function branch()
{
return $this->belongsTo(Branch::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
User Model :
public function franchise()
{
return $this->hasOne(User::class);
}
To make these relationships work, you need to have proper foreign keys in your database schema. To know more please check documentation
Related
In a project, let's say that we have Customers, and each customer can have one Voucher. The voucher, though, may be for a different thing for different customers - maybe for a Hote, a Car or a Flight.
We have a table of flight voucher codes, a table of hotel voucher codes and a table of car voucher codes.
When a customer is allocated a voucher, therefore, we allocated them the next code for the relevant thing that they're getting a voucher for. But rather than have multiple tables (customer_car_voucher, customer_hotel_voucher, and so on) I would rather have a Voucher table which is, in turn, linked to the relevant voucher type.
What I want to be able to do is just go $customer->voucher->code to get the relevant code, whether that be a flight, a hotel or a car. Other vouchers may be added at a later date, you see, for different things.
I think I can do this using morphable relationships - the voucher morphsTo car, hotel and flight, so within the the voucher table there is a "voucherable_type" and a "voucherable_id". But damned if I can get it to work.
Any help, please? Am I going about it wrong?
you arte right. and for a hint use:
public function customer()
{
return $this->belongsTo(Customer::class):
}
public function voucherable()
{
return $this->morphTo();
}
in voucher model.
and for each flight,car,hotel include:
public function voucher(){
return $this->morphOne(Voucher::class,'voucherable');
}
you can see Laravel morph relationship too for more help.
In Laravel's Eloquent ORM is used for morphable relationships.
First, create two Models AirVoucher and Voucher.
First, the AirVoucher model uses the following relationship.
public function voucher()
{
return $this->morphOne(Voucher::class, 'voucherable');
}
Second, the Voucher model uses the following relationship.
public function voucherable()
{
return $this->morphTo();
}
You can use the following Laravel official relationship document for more help.
Laravel Morph Relationships.
you must use laravel Polymorphic Relationships.
in Voucher model set this model as polymorph model(function name = modelname+"able"):
public function voucherable() \Illuminate\Database\Eloquent\Relations\MorphTo
{
return $this->morphTo();
}
then in Car model (or hotel/fight) set realation(function name= polymorph name):
if each car has one voucher, use morphOne:
public function files(): \Illuminate\Database\Eloquent\Relations\MorphOne
{
return $this->morphOne(Voucher::class, 'voucherable');
}
if each car has many voucher, use morphMany:
public function files(): \Illuminate\Database\Eloquent\Relations\MorphMany
{
return $this->morphMany(Voucher::class, 'voucherable');
}
Retrieving The Relationship
$car = Car::find(1);
$vocher = $car->voucher;
laravel docs
I want to put all my different users (teachers, students, admins) in the same table but how can I differentiate between them.
When I add the relationships in this table, for example : the teachers belongs to a departement table:
public function departement()
{
return $this->belongsTo(Departement::class);
}
And the students belongs to another table which is faculty table:
public function faculty()
{
return $this->belongsTo(Faculty::class);
}
The problem is when I add those relationships to the users table it will add automatically to all types of users (teachers, students, admins...).
use where
public function departement()
{
return $this->belongsTo(Departement::class)->where('users.type','=','student');
}
public function faculty()
{
return $this->belongsTo(Faculty::class)->where('users.type','=','admin');
}
Problem
I have two classes, Users & Posts. A user "hasMany" posts and a post "belongTo" a user. But when I call "User::all()" it doesn't automatically pull the users posts for obvious reasons, because if my user had relations to 100 different tables pulling all users would start to become pretty chunky.
Question
Is there a way to pull all users and all user->posts in one or few lines of code without going through a foreach loop?
I know i can use a mutator but the problem I have is my field is called user_id and i have tested it with this code:
public function getUserIdAttribute($id)
{
return User::find($id);
}
But it will replace "user_id" field value with a user object, Id rather have it set to its own "temporary user" field within the result. I'm trying to find best practice!
Thank you in advance.
What you're looking for is called Eager Loading
Inside your post model :
class Post extends Model
{
protected $table='posts';
public $primaryKey='id';
public function user(){
return $this->belongsTo('App\User','user_id');
}
}
now you want to get post with user use below code :
$posts=Post::with('user')->get();
inside your user model :
class User extends Model
{
public function posts(){
return $this->hasMany('App\Model\Post');
}
}
now you want to get a user with all posts :
$user=User::where('id',$id)->first();
$user_posts=$user->posts;
I'm learning Laravel and Laravel eloquent at the moment and now I try to solve a problem using relations in Laravel.
This is what I want to archive:
The database holds many sport clubs. A sport club has a lot of teams. Each team has games. The teams table has a column named club_id. Now I want to create Eloquent relations to get all games of a club.
Here is what I got so far:
Club model
id => PRIMARY
public function games()
{
return $this->hasMany('App\Models\Games')->whereHas('homeTeam')->orWhereHas('guestTeam');
}
Game model
home_id => FOREIGN KEY of team ; guest_id => FOREIGN KEY of team
public function homeTeam()
{
return $this->belongsTo('App\Models\Team','home_id')->where('club_id','=', $club_id);
}
public function guestTeam()
{
return $this->belongsTo('App\Models\Team','guest_id')->where('club_id','=', $club_id);
}
Team model
id => PRIMARY ; club_id => FOREIGN
In my controller all I want to do is Club::findOrFail($id)->games()
Executing the code above returns a SQL error that the games table does not have a column named club_id.
What is the correct way to create this kind of relation?
Thanks!
EDIT
Thanks to Nikola Gavric I've found a way to get all Games - but only where club teams are the home or away team.
Here is the relation:
public function games()
{
return $this->hasManyThrough('App\Models\Game','App\Models\Team','club_id','home_id');
}
How is it possible to get the games where the home_id OR the guest_id matches a team of the club? The last parameter in this function does not allow an array.
There is method to retrieve a "distant relationship with an intermediary" and it is called Has Many Through.
There is also a concrete example on how to use it which includes Post, Country and User, but I think it will be sufficient to give you a hint on how to create games relationship inside of a Club model. Here is a link, but when you open it, search for hasManyThrough keyword and you will see an example.
P.S: With right keys naming you could achieve it with:
public function games()
{
return $this->hasManyThrough('App\Models\Games', 'App\Models\Teams');
}
EDIT #01
Since you have 2 types of teams, you can create 2 different relationships where each relationship will get you one of the type you need. Like this:
public function gamesAsHome()
{
return $this
->hasManyThrough('App\Models\Games', 'App\Models\Teams', 'club_id', 'home_id');
}
public function gamesAsGuests()
{
return $this
->hasManyThrough('App\Models\Games', 'App\Models\Teams', 'club_id', 'guest_id');
}
EDIT #02
Merging Relationships: To merge these 2 relationships, you can use merge() method on the Collection instance, what it will do is, it will append all the records from second collection into the first one.
$gamesHome = $model->gamesAsHome;
$gamesGuests = $model->gamesAsGuests;
$games = $gamesHome->merge($gamesGuests);
return $games->unique()->all();
Thanks to #HCK for pointing out that you might have duplicates after the merge and that unique() is required to get the unique games after the merge.
EDIT #03
sortBy also offers a callable instead of a attribute name in cases where Collection contains numerical indexing. You can sort your Collection like this:
$merged->sortBy(function($game, $key) {
return $game->created_at;
});
When you define that Club hasMany games you are indicating that game has a foreign key called club_id pointing to Club. belongsTo is the same but in the other way. These need to be coherent with what you have on your database, that means that you need to have defined those keys as foreign keys on your tables.
Try this...
Club model
public function games()
{
return $this->hasMany('App\Models\Games');
}
Game model
public function homeTeam()
{
return $this->belongsTo('App\Models\Team','home_id');
}
public function guestTeam()
{
return $this->belongsTo('App\Models\Team','guest_id');
}
Your Query like
Club::where('id',$id)->has('games.guestTeam')->get();
I have a user_managers pivot table that gets both keys from the users table:
employer_user_id
employee_user_id
I believe users would have a many to many relationship as a user can be managed by more than 1 manager there will be users who manage 1 or more users, while other users (excluding those under them) would manage them while there will be users who don't manage at all and a User can have only 1 manager.
My first try at defining this was to build another model named Manager representing the user_managers pivot table, so in User model I wrote the following 2 functions:
public function managedBy()
{
return $this->belongsToMany('Manager', 'employer_user_id');
}
public function manages()
{
return $this->hasMany('Manager', 'employee_user_id', 'employer_user_id');
}
Does this make sense or do you know of a better way to implement this kind of structure?
If a user can have only 1 manager then you can define you relationship as one to many like
//User model
public function managedBy()
{
return $this->belongsTo(User::class, 'manager_id');
}
public function managees()
{
return $this->hasMany(User::class, 'manager_id');
}
you don't need to pass $id to your relationship definition.
For multiple managers, Yes you would need a many to many relationship by adding a junction/pivot table which i guess you already have user_managers, Now you need to define your relationships using belongsToMany for managers and mangees like
public function managers()
{
$this->belongsToMany(User::class, 'user_managers', 'employer_user_id')
}
public function managees()
{
$this->belongsToMany(User::class, 'user_managers', 'employee_user_id')
}