Laravel 8.x, 3 models and many to many relationship - laravel

I am new to laravel and trying the following:
I have these tables:
disciplines: id | name
specialties: id | name
categories: id | name
discipline_specialty (pivot table): id | discipline_id | specialties_id
Discipline model:
public function specialties()
{
return $this->belongsToMany(Specialty::class);
}
Specialty model:
public function disciplines()
{
return $this->belongsToMany(Discipline::class);
}
My question is:
how can I relate (many to many) the categories to the pivot table discipline_specialty in order to access the category name with the discipline and specialty ids?
I had thought of an additional pivot table that linked category id and discipline_specialty id but I don't know if it's the best solution and how to do it. Do you have any suggestions? Any help is appreciated.

You can introduce a junction/pivot model that will relate these 3 relations as many-to-one/belongsTo and one-to-many/hasMany from Discipline/Speciality/Category.
Discipline Speciality Category
\\ || //
\\ || //
DisciplineSpecialityCategory
This DisciplineSpecialityCategory model will have following attributes or FKs
Table: discipline_speciality_category
discipline_id
speciality_id
category_id
Now you model definitions will be like
class Discipline extends Model
{
public function disciplineSpecialityCategory()
{
return $this->hasMany(DisciplineSpecialityCategory::class, 'id', 'discipline_id');
}
}
class Speciality extends Model
{
public function disciplineSpecialityCategory()
{
return $this->hasMany(DisciplineSpecialityCategory::class, 'id', 'speciality_id');
}
}
class Category extends Model
{
public function disciplineSpecialityCategory()
{
return $this->hasMany(DisciplineSpecialityCategory::class, 'id', 'category_id');
}
}
class DisciplineSpecialityCategory extends Model
{
public function discipline()
{
return $this->belongsTo(Discipline::class, 'id', 'discipline_id');
}
public function speciality()
{
return $this->belongsTo(Speciality::class, 'id', 'speciality_id');
}
public function category()
{
return $this->belongsTo(Category::class, 'id', 'category_id');
}
}

Related

Laravel Eloquent HasManyThrough through 3 tables with pivot tables

I need to make a list of scopes from my positions->areas->scopes on my Booking Model.
My tables look like that:
Booking
id
...
Position
id
booking_id
...
Area
id
..
Position_areas
id
area_id
position_id
Scope
id
...
Area_Scopes
id
area_id
scope_id
And this are my relations:
class Booking extends Model
{
...
public function positions()
{
return $this->hasMany(BookingPosition::class);
}
public function areas()
{
return $this->hasManyThrough(Area::class, PositionsAreas::class, 'area_id', 'id', 'position_id', 'area_id');
}
...
}
class BookingPosition extends Model
{
...
public function booking()
{
return $this->belongsTo(Booking::class);
}
public function areas()
{
return $this->belongsToMany(Area::class, 'position_areas', 'position_id', 'area_id')
->using(PositionsAreas::class);
}
...
}
class PositionsAreas extends Pivot
{
...
protected $table = 'position_areas';
public function positions(){
return $this->belongsTo(BookingPosition::class);
}
public function areas(){
return $this->belongsTo(Area::class);
}
...
}
class Area extends Model
{
...
public function bookingPositions()
{
return $this->belongsToMany(
BookingPosition::class
)->using(PositionsAreas::class);
}
public function scopes()
{
return $this->belongsToMany(Scope::class, table: 'scope_areas');
}
...
}
class Scope extends Model
{
...
public function areas(){
return $this->belongsToMany(Area::class, table: 'scope_areas');
}
...
}
And I want to have a list of all areas on my booking model, but I don't know how to achieve that.
So that I can do something like that
...
$booking->load('scopes');
[
id
date
...
scopes => [
{...},
{...}
]
]
I tried to create pivot models for position_areas but i cant even get a list of areas on my booking model.
I couldn't figure out how to solve this with a relation like hasManyThrough but as workaround I make all scopes available in my $bookings like that.
$booking = Booking::find($booking->id);
$booking->scopes = $booking->positions
->pluck('areas')
->flatten()
->pluck('scopes')
->flatten()
->pluck('name')
->unique()
->values()
->all();

Laravel Eloquent Relationship with 4 tables (3 model + 1 table)

Hi I have this 4 tables
Employee:
EmployeeID,
EmployeeName,
EmployeeEmail,
EmployeePassword
Department:
DepartmentID,
DepartmentName
Position:
PositionID,
PositionType
employee_deployment:
EmployeeDeploymentID,
EmployeeID,
DepartmentID,
PositionID
I created a migration for a Pivot table employee_deployment
public function up()
{
// Set schema to create field of table
Schema::create('employee_deployment', function (Blueprint $table) {
$table->bigIncrements('EmployeeDeploymentID');
$table->bigInteger('EmployeeID')->unsigned();
$table->bigInteger('DepartmentID')->unsigned();
$table->bigInteger('PositionID')->unsigned();
});
Schema::table('employee_deployment', function ($table) {
$table->foreign('EmployeeID')->references('EmployeeID')->on('tbl_employees')->onDelete('cascade');
$table->foreign('DepartmentID')->references('DepartmentID')->on('tbl_departments')->onDelete('cascade');
$table->foreign('PositionID')->references('PositionID')->on('positions')->onDelete('cascade');
});
}
Can someone help me to create a relationship for each model? And save the data into pivot table (employee_deployment table).
A pivot table cannot be used in this way to define 2 relationships at once, instead I would recommend having a Deployment model which has a one to one relationship with the other three models.
class Deployment extends Model
{
public function employee()
{
return $this->hasOne('App\Employee');
}
public function department()
{
return $this->hasOne('App\Department');
}
public function position()
{
return $this->hasOne('App\Position');
}
}
class Employee extends Model
{
public function deployment()
{
return $this->belongsTo('App\Deployment');
}
}
class Position extends Model
{
public function deployment()
{
return $this->belongsTo('App\Deployment');
}
}
class Department extends Model
{
public function deployment()
{
return $this->belongsTo('App\Deployment');
}
}
If you want to be able to access the relationships between Employee and Position or Position and Department or Employee and Department directly you can also add hasOneThrough relationships to the other 3 models
public function employee()
{
return $this->hasOneThrough('App\Employee', 'App\Deployment');
}
public function department()
{
return $this->hasOneThrough('App\Department', 'App\Deployment');
}
public function position()
{
return $this->hasOneThrough('App\Position', 'App\Deployment');
}
I think this should get you the relationships you're looking for
If any of these relationships aren't 1 to 1 then you'll need pivot tables between Deployment and the other 3 models but you should be able to just switch hasOneThrough to hasManyThrough to keep the direct relationships
For your migrations, if you don't use regular id columns on the employee, department, and position models you'll have to add a custom foreign key definition to the relationships. As an example the one for Deployment->Employee would be
public function employee()
{
return $this->hasOne('App\Employee', 'EmployeeID', 'EmployeeID');
}

Laravel Nova: Pivot Table with 3 relationships

in my Laravel Nova project I have this Models:
- Ricetta
-id
- Ingrediente
-id
- UnitaMisura
-id
- RicettaHasIngrediente (many to many, pivot table)
-ricetta_id
-ingrediente_id
-qta
-unita_misura_id
Code:
class Ricetta extends Model
{
public function ingrediente()
{
return $this->belongsToMany('\App\Models\Ingrediente', 'ricetta_has_ingrediente', 'ricetta_id', 'ingrediente_id')->withPivot('qta', 'unita_misura_id');
}
}
class Ingrediente extends Model
{
public function ricetta()
{
return $this->belongsToMany('\App\Models\Ricetta', 'ricetta_has_ingrediente', 'ingrediente_id', 'ricetta_id')->withPivot('qta', 'unita_misura_id');
}
}
class UnitaMisura extends Model
{
public function ricettaHasIngrediente()
{
return $this->belongsTo('\App\Models\ricettaHasIngrediente', 'unita_misura_id', 'id');
}
}
class RicettaHasIngrediente extends Model
{
public function unitaMisura()
{
return $this->belongsTo('\App\Models\UnitaMisura', 'unita_misura_id', 'id');
}
}
I think this structure is correct.
With Laravel Nova, I have defined all the fields and the attributes of the pivot table, but I can't use the unita_misura_id:
...
BelongsToMany::make('Ingrediente')->fields(function () {
return [
Number::make('Quantità', 'qta'),
HasMany::make('unitaMisura', 'unitaMisura')
];
}),
...
When I open the form qta value; unita_misura is not displayed.
Can you help me?
thanks!

I many-to-many relationship, get ID of pivot table

I have the following models in a many-to-many relationship:
class Event extends Model
{
public function positions() {
return $this->belongsToMany(Position::class, 'position_events');
}
}
class Position extends Model
{
public function events() {
return $this->belongsToMany(Event::class, 'position_events');
}
}
class PositionEvent extends Model
{
public function position() {
return $this->hasOne(Position::class, 'id', 'position_id');
}
public function event() {
return $this->hasOne(Event::class, 'id', 'event_id');
}
}
The position_events table looks like:
id | event_id | position_id
If $event is an instance of Event, I can get the related positions as:
$event->positions;
This gives me something like the following for each related Position:
{"id":4,"name":"Striker","created_at":"2019-04-02 16:19:57","updated_at":"2019-04-02 16:19:57","pivot":{"event_id":27,"position_id":4}}
Notice the pivot element. It only has event_id and position_id as properties, these are columns from the position_events table. How do I get it to have the id column from that table as well?
Have you tried using withPivot(), for example:
$this->belongsToMany(Position::class, 'position_events')->withPivot('id');

Laravel BelongsToMany with two pivot table

I have the following table structure:
products
id
product_formats
id
product_id
product_prices
id
product_format_id
market_id
markets
id
A product can have multiple formats, with each having their own price which belongs in a different market. How can I retrieve the list of Markets from the Product model?
I used to have a single pivot table, however now I have two pivot.
class Product extends Model
{
public function markets()
{
return $this->belongsToMany(Market::class);
}
}
Update
To get the result I want, I did the following:
public function markets()
{
return Market::whereIn('id', $this->prices()->distinct()->pluck('market_id')->toArray());
}
However, I'm wondering if there's a way to accomplish this via a relationship.
You need to build relationships in models.
ProductModel:
public function productFormats()
{
return $this->belongTo(ProductFormatsModel::class);
}
ProductFormatsModel:
public function productPrices()
{
return $this->belongTo(ProductPricesModel::class);
}
ProductPricesModel:
public function markets()
{
return $this->hasOne(MarketsModel::class);
}
in Controller:
foreach($product->productFormats as $productFormat)
{
foreach($productFormat->productPrices as $productPrice)
{
var_dump($productPrice->markets);
}
}
For unique markets
in ProductModel:
public function productPrices()
{
return $this->hasManyThrough(
'App\ProductPricesModel',
'App\ProductFormatsModel',
'product_id',
'product_format_id'
'id',
'id'
);
}
in Controller
foreach($product->productPrices as $productPrice)
{
var_dump($productPrice->markets)
}

Resources