Laravel 8 - How to relationship from 3 tables - laravel

I have 3 tables:
structurals
id
name
indicators
id
name
groupings
id
structural_id
indicator_id
And Result:
#structural name
indicator name
indicator name
#structuralname
indicator name
I've used method hasMany & hasManyThrough but errors.

In this case, an indicator may belong to one or more structural. And a structural can have one or more indicators.
What this describes is a many-to-many relationship where groupings is only a pivot table. So you should be using the belongsToMany instead:
class Indicator extends Model
{
public function structurals()
{
return $this->belongsToMany(Structural::class, 'groupings');
}
}
class Structural extends Model
{
public function indicators()
{
return $this->belongsToMany(Indicator::class, 'groupings');
}
}
Docs: https://laravel.com/docs/eloquent-relationships#many-to-many
You can also remove the id column from the groupings table, as it is unnecessary.

Related

Struggling with Laravel's morphable relationships

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

Eloquent custom relationship hasMany (foreign field contains text concatenated by foreign key)

I have this database structure. 2 tables: shipment_out, stock_move.
shipment_out has the typical primary key integer id field.
stock_move has a field named shipment which is string type. This field can have these values:
"stock_shipment_out,1512",
"stock_shipment_in,65400",
"sale.line,358",
(...)
The thing is the table stock_move is related to a multiple tables based on the same field, so it has this text before.
In this case I want to define the relationship: shipment_out hasMany stock_move.
So I need to join by stock_move.shipment has this value: 'stock_shipment_out,{id}'.
So how can I define this relationship? Would be something like:
public function stockMoves()
{
return $this->hasMany(StockMove::class, 'shipment', 'stock.shipment.out,id');
}
I can achieve this relationship with query builder:
$shipments = ShipmentOut
::join('public.stock_move', DB::raw('CONCAT(\'stock.shipment.out,\',public.stock_shipment_out.id)'), '=', 'stock_move.shipment')
->where('stock_shipment_out.id', '=', $shipmentOut);
But I need on a relationship too...
To solve this problem I had to define a custom attribute, and then I can define the relationship with this field.
public function getStockMoveShipmentAttribute()
{
return "stock.shipment.out,{$this->id}";
}
public function stockMoves()
{
return $this->hasMany(StockMove::class, 'shipment', 'stock_move_shipment')
}
Now I can use this relationship, but it's only one-direction...
If I want to define the same relationship as the inverse it doesn't work.
I opened another question explaining it: Laravel relationship based on custom attribute not working both directions

Laravel eager loading a BelongsTo relation doesn't work

This seems extremely simple and yet it doesn't work:
// Reservations
class Reservation extends Model
{
public function service()
{
return $this->belongsTo('App\Landing');
}
}
// Service
class Landing extends Model
{
public function reservation()
{
return $this->hasMany('App\Reservation');
}
}
And then in my controller I have:
$x = Reservation::with('service')->get();
$y = Reservation::all()->load('service');
None of these work. I've tried several ways of loading it and none of them work. It always returns an empty result for the service.
Any other result works fine with eager loading (even with nesting) except te BelongsTo - this one.
The eager loading works.
The problem is your relationship
When you define a BelongsTo relationship you need to specify a foreign key if the name of your property does not correspond to the entity being referenced
For example: if you call the relationship "landing", you will be fine, because under-the-hood, Laravel passes the foreign key landing_id based on the name of the property
class Reservation extends Model
{ //landing correspond to the lowercase (singular) name of the Landing class
//in that case Laravel knows how to set the relationship by assuming
//that you want to match landing_id to the id of the landings table
public function landing()
{
return $this->belongsTo(Landing::class);
}
}
If you chose to name the relationship differently, such as "service", then you need to specify the foreign key ex: landing_id since service and landing are two different words, and landing correspond to the lowercase version of the actual class Landing. Otherwise Laravel would think your foreign key is "service_id" instead of landing_id
class Reservation extends Model
{
//service is a custom name to refer to landing
//in that case Laravel needs you to specify the foreign key
public function service()
{
return $this->belongsTo(Landing::class, 'landing_id');
}
}
Read more here: https://laravel.com/docs/5.8/eloquent-relationships#updating-belongs-to-relationships

Join 3 tables using Laravel Eloquent

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/

Correct relationship in Laravel

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.

Resources