Laravel relations with composite foreign keys - laravel

Here's what I want to achieve, we have Staff and every staff can have one Position for a department, as well as one Designation for a department and multiple Additional Charges for multiple departments, one department per Additional Charge. And I want to store all the responsibilities in the staff_responsibilities table
I have a staff table with the following columns
id
name
email
Then I have staff_responsibilities table with the following columns:
staff_id
designation_id
department_id
responsibility_type_id
Responsibility types can be Position and Additional Charge and one staff can have multiple designations with Additional Charge responsibility.
Then I have a responsibility_types table with the following columns:
id
name
// I have no way to tell this relationship to look for a responsibility type 2 (2 is the id of the responsibility called `Designation`)
public function designation()
{
return $this->hasOne(StaffResponsibility::class);
}
// I have no way to tell this relationship to look for a responsibility type 2
public function position()
{
return $this->hasOne(StaffResponsibility::class);
}
// Gives error: Syntax error or access violation: 1066 Not unique table/alias: 'staff_responsibilities'
public function additionalCharges()
{
return $this->belongsToMany(StaffResponsibility::class, 'staff_responsibilities','designation_id');
}
Any help would really be appreciated.
staff_responsibilities table
responsibility_types table
designations table

Here's what I want to achieve, we have Staff and every staff can have one Position for a department, as well as one Designation for a department and multiple Additional Charges for multiple departments, one department per Additional Charge.
It sounds to me like it would be beneficial to create a model for Position, Designation and Additional Charges. It feels like you may need to normalize your database or to change staff_responsibilities as a pivot table.
But hard to say without knowing your application.
To answer your question, you could add some scopes in StaffResponsibility
class StaffResponsibility extends Model{
public function scopeDesignation($query)
{
return $query->where('responsibility_type_id','=',2);
}
}
and use it
public function designation()
{
return $this->hasOne(StaffResponsibility::class)->designation();
}
And the last one is a hasMany relation and not a manyToMany according to what you wrote:
public function additionalCharges()
{
return $this->belongsTo(StaffResponsibility::class, 'staff_responsibilities','designation_id')->additionalCharges();
}

Related

Laravel: Load only pivot additional columns without relation

I have the following structure:
Charge
id
amount
created_at
..
Payment
id
amount
created_at
..
and a pivot table charge_payment, since one charge can be covered partially by multiple payments.
charge_payment
charge_id
payment_id
amount
The amount column on the pivot table defines the amount that the given Payment covers for the Charge.
And I need to get only the "paid" amount for a Payment.
I have the following models:
// Charge.php
class Charge extends Model
{
public function payments()
{
return $this->belongsToMany('App\Payment')->withPivot('amount');
}
}
// Payment.php
class Payment extends Model
{
public function charges()
{
return $this->belongsToMany('App\Charge')->withPivot('amount');
}
}
I want to be able to get only the paid amount with:
$payment = Payment::find(..);
$paid_amount = $payment->charges->sum('pivot.amount');
However, with this approach the related models are loaded from the database and I won't be needing them.
Is there a way to load only the additional pivot column without the related models?
Thank you very much!
Firstly, if one Payment can be always related only to one Charge, I would advise you to change the relationship from many-to-many to one-to-many (it will be just more correct and simpler).
Than you can simple use aggregate function (in your case withSum) which will return you only resulting values without relationship Models.
$payment = Payment::withSum('payments', 'amount')->find(..);
{{ $payment->payments_sum_amount }}

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

Laravel relationship between two tables

I'd like your input on this.
I have a Customer_table with a field name. I have another table called Reservation_table with a Customer_name field.
How can I relate them in such a way that I'd see all the bookings by the specific customer?
In Reservation_table you should have a field(foreign key) userid in order ta have a user for each reservation.
You can using primary key - foreign key relationship to relate/join those two tables. Also, instead of having a 'Customer_name' field as your FK referring to 'name' field in 'Customer_table' table, it is better to have an id (unique) generated for each customer; This way you can have an efficient way of uniquely identifying and relating customer across tables; can save space on Database side as well. Hope this helps!
If you want to use eloquent you must first define a relationship.
One reservation belongs to a user. Here is how to define the relationships:
Inside the Reservation model:
public function user()
{
return $this->belongsTo('App/User'); //User model
}
To define the inverse you do the following:
Inside User model:
public function reservations()
{
return $this->hasMany('App/Reservation'); // Reservation Model
}
Now you can do the following in your controller:
$reservations = Auth::user()->reservations;
Now you have all reservations by the currently logged in user.
I am not sure if I got the question right so ask away.

Laravel Many To Many Polymorphic Relations

I have a quick question on how to define the below relationship
I have a USER that can belong to Many Councils, Many Schools and Many Businesses.
Now I know I can have a pivot table for all the above something like
council_user
school_user
business_user
This means I can pull out of the DB all councils a user belongs to, all businesses etc
To save me doing this is there a better approach that having 3 pivot tables, could I use Many To Many Polymorphic Relations and do it that way, if so does any one know how that would look as a table structure?
I feel it would be something like...
business
id - integer
name - string
council
id - integer
name - string
school
id - integer
name - string
userables
user_id - integer
userable_id - integer
userable_type - string
If so do I remove the userable_is and userable_type from my USER table and have this extra userables table?
Does any one know how this works, have I totally misunderstood what Polymorphic Relations does?
In Many to Many polymorphic relationship, you should have userables table along with users table. and userable_id and userable_type should be in userables table not in users table.
userables table:
user_id userable_id userable_type
1 1 App\Business
1 2 App\School
...
Business, School and Council Model:
public function users()
{
return $this->morphToMany('App\User', 'userable');
}
User Model:
public function businesses()
{
return $this->morphedByMany('App\User', 'userable');
}
public function schools()
{
return $this->morphedByMany('App\User', 'userable');
}
public function councils()
{
return $this->morphedByMany('App\User', 'userable');
}
then, this gives all the businesses of user with user_id 1.
$users=User::find(1);
foreach($user->businesses as $business)
{
print_r($business->name);
}
See Many to many polymorphic relation in doc.

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