Laravel: Load only pivot additional columns without relation - laravel

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 }}

Related

How to implement a mutli-foreign key in laravel 8

I am working on a project where am required to implement a database relationship between tables(Trip, Truck, Fuel) . Below is the idea :
A truck has many trips
Each trip has many trucks
Each truck has got a fuel associated with a trip.
Now I was hoping to use Eloquent relationships to solve this but am stuck . How do I get a Fuel transaction and map it to a truck and trip ?
Thanks in advance !
you can use pivot table.
"pivot table is used to build a relationship between two tables where there is a Many to Many relationship."
in your case you can use Many to Many relationship between truck and trip then use fuel like a column in pivot table. it's easier
Eloquent does not support ternary relationships out of the box. This is because typically ternary relationships are incorrectly used when normal binary relationships would be more appropriate. For example I could argue that the Fuel entity is actually metadata on the Truck-Trip relationship and should be placed on the pivot table instead.
If you are completely 100% certain that your ternary relationship is correctly required then I think your best bet is to make a separate model TruckTrip i.e.:
class TruckTrip extends Model {
public function truck() {
return $this->belongsTo(Truck::class);
}
public function trip() {
return $this->belongsTo(Trip::class);
}
public function fuel() {
return $this->belongsTo(Fuel::class);
}
}
Then instead of relating Truck, Trip and Fuel directly you could use: hasManyThrough e.g.
class Trip extends Model {
public function trucks() {
return $this->hasManyThrough(Truck::class, TruckTrip::class);
}
public function fuel() {
return $this->hasManyThrough(Fuel::class, TruckTrip::class);
}
}
Similarly you can relate trucks to trips and fuel requirements and fuel requirements to trucks and trips
Laravel is offering many to many relationship but i prefer if you divided by tow relation.
make a table for this relation have the ID of truck and the ID of trips, then make a relation one to many between truck and this new table and another relation one to many between trip and this new table.
is will be easy for you

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 Many Records to One single record....but how?

I have two tables, one is Users and the other is Loans. These have one to many relationship between them. One user can have many loans and one loan belongs to one User.
Now I want to get the user from the list of loans.
Loan::where('user_id', $user)->get()
This give me repeated array of sample user associated to the multiple loans. But I want to get only a single record, like many loans associate to one user.
I assume you already set up relationships between User & Loan Models
// App\User
public function loans() {
return $this->hasMany('App\Loan');
}
// App\Loan
public function user() {
return $this->belongsTo('App\User');
}
Get user from the list of loans
$user = Loan::where('user_id', $id)->first()->user;
// eager loading version
$loansWithUsers = Loan::with('user')->where('user_id', $id)->get();
Loans associate to one user
$loans = User::findOrFail($id)->loans;
// eager loading version
$userWithLoans = User::with('loans')->findOrFail($id);
For what I understand in your question, you want to get the user together with it's loan right ? Your query should like this.
$user_loans = User::with('loans')->where('id', $user_id)->get();
Get the user informations from loan table
Loan::where('user_id', $user_id)->with('user')->get()
Ge the users from loans table depends on brach id
Loan::where('branch_id', $branch_id)->with('user')->get();

Laravel Relationship that returns just one of a belongsToMany

I have a two Models: a Deal is started on one system by customers, and a Sale is started on another system by a salesman. I have an intermediate table dms_matches that forms a many-to-many relationship between those models, and includes a confidence score.
Customers can start many deals, the confidence score measures how likely the customer Deal is the exact one that initiated the final Sale transaction. (e.g., one system says first name is "Joe" and the other says "Joseph", or customer got upsold so Sale contains a related but different product than Deal)
I have a working many-to-many relationship on Sale to return all matched Deals:
public function deals()
{
return $this->belongsToMany('App\Models\Deal', 'dms_matches', 'dms_sale_id')
->orderBy('dms_matches.confidence', 'DESC')
->withPivot('confidence');
}
Now I would like a relationship that returns the exactly one Deal with the highest confidence score. (I want a relationship so I can get eager loading and caching.)
This works, but returns a collection of length one:
public function best_deal()
{
return $this->deals()->limit(1);
}
This works, but isn't a relationship, so it doesn't work with eager loading.
public function getBestDealAttribute()
{
return $this->deals()->first();
}
How can I build something that behaves like a hasOne or belongsTo relationship, but uses an intermediate table?

Eloquent relation with two keys

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');

Resources