I have a relation:
Class Championship extends Model{
public function fights()
{
return $this->hasManyThrough(Fight::class, Tree::class);
}
}
When I do :
$championship->fights,
I get the fight Collection I need.
But I would also need to group them by area, and area belongs to Tree ( $tree->area ).
Is it posible to get this relation with an extra field from Tree????
Or should I add area field in Fight table ( but it sounds like data duplication )
Related
A contract has a representative (which is a user).
Currently I get this relationship with an belongsTo directly like this in my Contract model:
class Contract extends Model
{
public function representative()
{
return $this->belongsTo(User::class);
}
I would like to be able to retrieve this relationship through the organization_user table and retrieve the "position" attribute.
I think I should use the hasOneThrough relationship but I can't get what I'm looking for.
class Contract extends Model
{
public function representative()
{
return $this->hasOneThrough(User::class, OrganizationUser::class);
}
Not sure if you're in a position to change your DB structure, but it seems to me that your table contracts and organization_user are duplicating each other, storing the same data.
Would it make sense to leave only one table organization_user as a pivot table with the position?
Then you wouldn't need to make the big loop over few relationship to get the needed data.
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
So I have 3 tables
size_sets - id, name
sizes - id, name
size_set_sizes - size_id, size_set_id
I want to define a relationship in size_set model that would retrieve all sizes available for that sizeset
Something like:
public function sizes()
{
//define relationship here
}
Method sizes should retrieve the names from the size table, through size_set_sizes table in the size_set model...
My application is very dynamic and thus I needed to go with this structure. I tried the hasManyThrough relationship, but couldn't get that to work.
100% use a pivot table
https://laravel.com/docs/5.4/eloquent-relationships
This link will give you all you need
Use belongsToMany() relations like:
class Size extends Model
{
public function sizeSets()
{
return $this->belongsToMany(SizeSet::class, 'size_set_sizes');
}
}
class SizeSet extends Model
{
public function sizes()
{
return $this->belongsToMany(Size::class, 'size_set_sizes');
}
}
Then you can do:
$sizeSet = SizeSet::with('sizes')->find($id);
Then $sizeSet->sizes will return a collection of sizes for that size set.
I Think I found what I was looking for The answer is a pivot-table
http://laraveldaily.com/pivot-tables-and-many-to-many-relationships/
TL:DR;
City model - Locations model - Offers model.
1 city hasMany locations, locations belongToMany offers
City::with('locations.offers')->where('slug','=', $city)->first();
shows 0 offers from relation even though there is an offer record connected to location (which is connected to the city).
Longer version:
I have 3 models which should be connected to each other. City, Location & Offer.
I have the given city, and want to retrieve all locations with offers which are connected to the city. In the output of:
City::with('locations.offers')->where('slug','=', $city)->first();
I see the city and all locations connected to the city. Each location has an empty offer relation.
Model City:
class City extends Model
{
public function locations()
{
return $this->hasMany('App\Location');
}
}
Model Location
class Location extends Model
{
public function city()
{
return $this->belongsTo('App\City');
}
public function offers()
{
return $this->belongsToMany('App\Offer','location_offer','offer_id','location_id');
}
}
Model Offer
class Offer extends Model
{
public function locations()
{
return $this->belongsToMany('App\Location','location_offer','offer_id','location_id');
}
}
Database is pretty basic:
city table holds the city information (id+title)
location table has city_id (and location title)
location_offer table has location_id & offer_id
offer has offer information.
Clearly I'm doing something wrong, but can't seem to figure it out. Any tips would be greatly appreciated.
Your code is perfect there is a small mistake in your relation
public function offers()
{
return $this->belongsToMany('App\Entities\Offers','location_offer','location_id','offer_id');
}
You need to check this link the third argument is wrong
The third argument is the foreign key name of the model on which you are defining the relationship, while the fourth argument is the foreign key name of the model that you are joining to:
Check the Queries
This is the one that will be executed by your code
select `offer`.*, `location_offer`.`offer_id` as `pivot_offer_id`, `location_offer`.`location_id` as `pivot_location_id` from `offer` inner join `location_offer` on `offer`.`id` = `location_offer`.`location_id` where `location_offer`.`offer_id` in ('1', '2')
See join is wrong :
join location_offer on offer.id = location_offer.location_id
This is the right one
select `offer`.*, `location_offer`.`location_id` as `pivot_location_id`, `location_offer`.`offer_id` as `pivot_offer_id` from `offer` inner join `location_offer` on `offer`.`id` = `location_offer`.`offer_id` where `location_offer`.`location_id` in ('1', '2')
join location_offer on offer.id = location_offer.offer_id
I have four tables in database: groups, specialties, lessons, group_lesson. It's structures:
groups
id
specialty_id
name
specialties
id
name
lessons
id
specialty_id
group_lesson (UNIQUE INDEX lesson_id, group_id)
lesson_id
group_id
date
My models look like that for now:
class Group extends Eloquent {
public function specialty() {
return $this->belongsTo('Specialty');
}
}
class Lesson extends Eloquent {
public function specialty() {
return $this->belongsTo('Specialty');
}
}
class Specialty extends Eloquent {
public function lessons() {
return $this->hasMany('Lesson');
}
public function groups() {
return $this->hasMany('Group');
}
}
I need get additional fields in Group model look like that
Group - Eloquent model
name - string
lessons - collection of Lesson models of Group Specialty
date - date from group_lesson table
I've tried different relationships and combinations, but it's doesn't work. Please help me to write correct relationships.
You can use eager-loading to access relational data through relationships, and can even chain relationships further. As a rule of thumb, if you can draw a path to from 1 model to another through a relationship, you can eagerload all the relevant and relational data for that with chained eager-loads.
Laravel Eager Loading
As an example
$speciality_group = Speciality::with('group','lessons')->find($id);
Even though you are only getting a single instance of the speciality model, the related data is hasMany, meaning multiple records. You need to loop through these records using a foreach loop to access the relevant data for them, or alternitavely add additional closures in your initial query to load only a single related model.
foreach($speciality_group->group as $group)
{
echo $group->name;
}
You will need to do this for both instances where you want to display related information.