I have 2 controllers & Models:
User Controller: (Model Relationship: $this->hasMany(Hero::Class);)
Hero Controller: Each hero has his own attributes, such as name, strength and life.
Model Relationship: ($this->belongsTo(User::class);)
Each user can own multiple heroes.
that means that USER ID: 1 may have 3 heroes: HERO ID 5, 20, 26..
My question: How to define the relationships like that and make laravel knows how to handle my user_heroes table?
The relationship i'm talking about is described in the following image:
How to I setup such kind of relationship in my laravel API?
If a User can have many heroes, and a Hero can also belong to many users, it is a many to many relationship. In Laravel the inverse of a many to many relationship is also a many to many relationship, and they are both described by belongsToMany().
https://laravel.com/docs/5.2/eloquent-relationships#many-to-many
So in your User model:
public function heros() {
return $this->belongsToMany(Hero::class);
}
And in your Hero model:
public function users() {
return $this->belongsToMany(User::class);
}
Laravel will assume the joining table is named hero_user, the 2 model names, singular, joined in alphabetical order. If you want to use user_heroes as you have in your image, you need to specify it:
return $this->belongsToMany(Hero::class, 'user_heroes');
(in both model methods).
Related
I have two models. Business and City.
Business:
id
title
-some columns--
city_id
City:
id
name
How to display the city name, when I get business data to view
I was able to display cities using the laravel voyager lessons
When I want to get it like $business->city_id
If you are using models, you can create a relationship by adding hasOne or hasMany to your model codes.
When you call it from your controller, you can call the relationship you wrote in your model with the 'with' query.
Model
public function city()
{
return $this->hasOne(City::class,'id','cityid');
}
Controller
$business=Business::with('city')->first();
$cityname=$business->city->name;
If you don't use model, you can connect with 'join'
You have 2 options. First, you can get city details on the controller:
Business::with('city')...;
On the blade
$business->city->name;
Other option fetching it on the blade directly. I don't recommend this because of extra database queries.
$business->city()->name;
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 just started my first laravel project today and stumbled upon this confusing situation,
I intended to use eloquent relationship instead of manually joining tables on query. So here it goes...
I have 3 tables which are users , tbl_instruments_taught , tbl_instruments
users table does not hold any of the table's ID,
tbl_instruments_taught - holds the id of user and intruments
Note: user can teach multiple instruments
Now, I implemented a hasOne on my other result set but I dont think hasOne works on this one. I read about belongsToMany but as I try implement it, it seems like every minute, it gets confusing.
Any idea?
I think you are looking for pivot table and relation many to many.
You have users table, instruments table (user has many instruments and one instrument could belong to many users) and user_instruments pivot table. Here db model:
And then add belongsToMany relationship in User and Instrument model (with specified pivot table). Like so:
//IN USER MODEL
public function instruments()
{
return $this->belongsToMany('App\Models\Instruments', 'users_instruments', 'user_id', 'instrument_id');
}
//IN INSTRUMENT MODEL
public function users()
{
return $this->belongsToMany('App\Models\Users', 'users_instruments', 'insrument_id', 'user_id');
}
Now you can reach instruments/users data through laravel relations/eager loading.
I am working on a team sports statistics project in Laravel.
Here is a sketch of the main models regarding this question:
class Team
// belongsToMany matches
// belongsToMany people
class Match
// belongsToMany teams
// belongsToMany people
class Person
// belongsToMany matches
// belongsToMany teams
I have also made models for the pivot tables to work directly with them. I have some stuff like goals_scored, number, position etc. stored there and it's too clumsy to use methods for updating pivot.
class MatchTeam // Participation of a team in the match
// belongsTo match
// belongsTo team
class MatchPerson // Participation of a person in the match
// belongsTo match
// belongsTo team
// belongsTo person
Is there an Eloquent way to relate MatchTeam to MatchPerson? I don't want to introduce a direct match_team_id foreign key, I want to do this using the existing match_id and team_id fields on both of the tables.
Currently I have this in my MatchTeam model:
public function matchPeople() // the roster
{
return $this->hasMany('App\Stats\MatchPerson', 'team_id', 'team_id')->where('match_id', $this->match_id);
}
It works fine. However, I am very concerned that this code is not fair to the nature of the relation - they are not related based on team_id, they are related based on both fields. I could have also written it like this:
public function matchPeople() // the roster
{
return $this->hasMany('App\Stats\MatchPerson', 'match_id', 'match_id')->where('team_id', $this->team_id);
}
Is there a fair way in which I could specify relation based on two columns in Eloquent?
Of course, this question is more out of curiosity as the actual problem of making the method is conquered.
A usage example for the curious:
$teamA->goals_for = $teamA->matchPeople->sum('goals');
I have a class Report which has a belongsToMany relation to Metric. Report also additionally has a belongsTo relation to Metric.
Normally, the model returned by the belongsTo relation is the same as one of the models in the belongsToMany relation. When this is true I'd like it to be the case that each of the two relations actually looks at the same object instance (this also saves an extra trip to the db).
So, in basic terms - is there a way to get one relation to check another first, to see if a model has already been loaded, and if so, point to that object rather than creating a new one.
I tried putting some code in the belongsTo relation method for Metric but I can't get round the fact it needs to return an instance of belongsTo, which needs various things passed as constructor arguments (ie. a query object), which aren't relevant in that case that the model has already been loaded in the belongsToMany relation.
I thought of ditching the belongsTo relation and adding data horizontally in the pivot table for the belongsToMany relation, but it isn't a many-to-many relation required so that seems a bit wrong.
Thanks!
Geoff
The idea here is to write a function which would check if a relationship is loaded and return that relationship, otherwise it will return the belongsToMany. This would go in your Report class. This is also for Laravel 5. If you have 4, just remove the namespaces from the model names.
public function metric()
{
return $this->belongsTo('App\Metric');
}
public function metrics()
{
return $this->belongsToMany('App\Metric');
}
public function getMetric()
{
if(array_key_exists('metric', $this->getRelations())) {
return $this->metric;
}
return $this->metrics()->first();
}
If you do decide to just go with a belongsToMany only, I'd suggest putting a unique key on your pivot table for both ID's to keep from getting any duplicates in the pivot table.