Laravel many to many with column in pivot table - laravel

I have 3 tables:
Worker, payments and private
A private can pay one or more worker and the worker can receive payments from one or more privates.
The payments table contains the 2 foreign key and the amount.
How can I create the relations in the 3 tables with laravel to get all the informations in the db?
For example i want to have for every worker the payments he receives from every private with the amount.

This is how you define many to many relationship between Worker and Private
Worker Model
public function privates()
{
return $this->belongsToMany(Private::class, 'payments', 'worker_id', 'private_id')
->withPivot('amount');
}
Private Model
public function workers()
{
return $this->belongsToMany(Worker::class, 'payments', 'worker_id', 'private_id')
->withPivot('amount');
}
this is how you can retrieve all the privates of a worker
Controller Function
$privates = $worker->privates;
// this '$privates' contains the 'pivot' table values which contains the 'amount'.
this is how you save amount.
Controller Function
// first $private and $worker need to have saved.
// and then attach particular $worker as below.
$private->attach($worker_id, ['amount' => 1200.00]);

I'm assuming you already know laravel relationships.
Worker.php
public function privates()
{
return $this->belongsToMany('App\Private')->withPivot('amount');
}
Private.php
public function workers()
{
return $this->belongsToMany('App\Worker')->withPivot('amount');
}
then in your controller
$private = Private::create();
$worker = Worker::create();
$amount = 1000;
$private->workers()->attach($worker->id, ['amount' => '$amount']);
^^^-column in your payment table.

Related

Count data using Laravel eloquent query from multiple table

I have 3 table 'Admins', 'Agent', 'Books'
Admin can add multiple Agents, Agents can add multiple books.
Now I need to count the book for a single Admin. (Every table has the proper foreign key).
How can I achieve this?
My code
//In Controller
$data = Admin::latest()->withCount('datacount')->get();
//In Admin.php
public function datacount(){
return $this->hasMany(Agent::class, 'adminId', 'id');
}
//In Agents.php
public function datacount(){
return $this->hasMany(Books::class, 'AgentId', '???');
}
//In Book.php
public function datacount(){
return $this->belongsTo(???::class, 'AgentId', '???');
}
??? - I don't know which Id or class need to pass
Can anyone help to solve this issue, please?

Return a json file of only the latest records per each foreign key in laravel

I am new to laravel and working through my first project. I have 2 tables a payments table and tenants table
payments Table => id, amount, rent_from, rent_to, created_at, updated_at , tenant_id
tenants table => .......
The tenants table has a one to many relationship with the payments table.
I need to return a json file of only the latest payments per each tenant_id.
The code
public function getPaymentsList(Request $request)
{
$payments= DB::table("payments")
->where("tenant_id",$request->tenant_id)
->pluck("rent_to")
;
return response()->json($payments);
}
**Returns all the 'rent_to' records per tenant_id.
How can i return only the most recent 'rent_to' record for each tenant_id as json file?
You might consider using Eloquent instead of the Query Builder for the full Laravel experience. But you would probably want to set up a special relationship in your Tenant model to make things easier.
Tenant.php
public function latestPayment()
{
return $this->hasOne(Payment::class)->latest();
}
Then you can use the relationship to obtain the results.
YourController.php
public function getPaymentsList(Request $request)
{
$payments = Tenant::with('latestPayment')->get()->pluck('latestPayment.rent_to','id');
return response()->json($payments);
}
// "tenant_id": "rent_to"
//
// {
// "101": "rent_to value...",
// "102": "rent_to value...",
// ...
// }

Laravel merge Relationship

I have 2 tables bookings and eventDates.
bookings table has 2 fields checkIndate and checkOutDate which points to eventDates table.
I setup following relationships
public function eventCheckInDate() {
return $this->belongsTo( 'EventDate', 'checkInDate' );
}
public function eventCheckOutDate() {
return $this->belongsTo( 'EventDate', 'checkOutDate' );
}
How can I combine those relationship so that eloquent only runs single query and get the data?
What happens now is it run 2 queries even if checkInDate and checkOutDate are still the same.
Thank you
As I understand you need something like that. create another method for merging two relations.
public function getEventsInOutDateAttribute($value)
{
$eventCheckInDate = $this->eventCheckInDate;
$eventCheckOutDate = $this->eventCheckOutDate;
// Merge collections and return single collection.
return $eventCheckInDate->merge($eventCheckOutDate);
}

HasMany Relation through BelongsToMany Relation

Is it possible to make Laravel relation through belongsToMany relations?
I have 4 tables:
1)Restaurants (id , name) - uses hasManyRelation with Workers table
2)Directors (id , name)
3)Directors_Restaurants (id, director_id, restaurant_id) - pivot table for connecting belongsToMany Restaurants with Directors
3)Workers (id, name, restaurant_id)
With this function in Directors model i can get all connected restaurants
public function restaurants()
{
return $this->belongsToMany('App\Restaurant','director_restaurant');
}
With this function in my code i can get all workers of all restaurants of one director
$director = Director::find(1);
$director->load('restaurants.workers');
$workers = $director->restaurants->pluck('workers')->collapse();
So my question is : can i declare similar relation in my Director model to get all its workers of all its restaurants?
Of course you can have hasMany relationship method on Director model with Eager Loading
just like below
public function restaurants()
{
return $this->hasMany(Restaurant::class)->with('restaurants.workers');
}
i can suggest a solution like this:
Director Model OPTION 1
public function getAllRestaurants(){
return $this->hasMany(Restaurant::class)->with('restaurants.workers');
}
Director Model OPTION 2
public function getAllRestaurants(){
$this->load('restaurants.workers');
return $this->restaurants->pluck('workers')->collapse();
}
You can get all restaurants anywhere
$all_restaurants = Director::find(1)->getAllRestaurants();
You can define a direct relationship by "skipping" the restaurants table:
class Director extends Model
{
public function workers()
{
return $this->belongsToMany(
Worker::class,
'director_restaurant',
'director_id', 'restaurant_id', null, 'restaurant_id'
);
}
}
You can define an accessor method in your model to hide some of the logic
# App/Director.php
// You'll need this line if you want this attribute to appear when you call toArray() or toJson()
// If not, you can comment it
protected $appends = ['workers'];
public function getWorkersAttribute()
{
return $this->restaurants->pluck('workers')->collapse();
}
# Somewhere else
$director = Director::with('restaurants.workers')->find(1);
$workers = $director->workers;
But ultimately, you still have to load the nested relationship 'restaurants.workers' for it to work.
Given your table attributes you could also define a custom HasMany relationship that looks like this
# App/DirectorRestaurant.php
public function workers()
{
return $this->hasMany(Worker::class, 'restaurant_id', 'restaurant_id');
}
# Somewhere else
$director = Director::find(1);
$workers = DirectorRestaurant::where('director_id', $director->id)->get()->each(function($q) { $q->load('workers'); });
But I don't recommend it because it's not very readable.
Lastly, there's the staudenmeir/eloquent-has-many-deep package where you can define that sort of nested relationship.
https://github.com/staudenmeir/eloquent-has-many-deep

Insert into DB based on a Join -> Laravel

I am working on a roll format for a laravel project.
I have successfully created the roll, and can update the roll status in the roll table which looks like this
|id|roll_id|member_id|status|created_at|updated_at|
One of my status is "Present/Voucher" using funds off a Voucher
I have the Voucher Table
|id|member_id|voucher|date|balance|created_at|updated_at|
When a user clicks on the present/voucher icon in the roll, the following is called in the controller
public function voucher($id)
{
$r = Roll::find($id);
if ($r != null)
{
$r->status = "V";
$r->save();
return redirect(action('RollController#index'))->with ('success', 'Member Paid with Vocuher');
}
return redirect(action('RollController#index'));
}
This works perfect, what I would like to know is how to insert a record into my Voucher table, while I can find the id record in the roll table, I need to pull that member_id so I can add this into the voucher table
For example if the Roll Record looks like this
|id|roll_id|member_id|Status|
|20|2|13|V|
I need to grab 13 are the Member_ID from roll record 20, so I can insert in the vouchers table
|id|member_id|voucher|date|balance
|2|13|Weekly Fees|currdate|-10
Please note the 10 is also stored in a settings table, so if I can grab from that table that would be great
Settings Table:
|id|Setting|Value|
|1|weekly Subs|10|
Thanks
You could first define model relationship.
Member
class Member extends Model {
public function vouchers()
{
return $this->hasMany('App\Voucher');
}
}
Roll
class Roll extends Model {
public function member()
{
return $this->belongsTo('App\Member');
}
}
Voucher
class Voucher extends Model {
public function member()
{
return $this->belongsTo('App\Member');
}
public function setting()
{
return $this->belongsTo('App\Setting');
}
}
Then you can execute fluently in controller, you should also use lockForUpdate and DB::transaction
public function voucher($id)
{
DB::transaction(function () use ($id) {
$roll = Roll::lockForUpdate()->find($id);
if ($roll != null) {
$roll->status = "V";
$roll->save();
$voucher = new Voucher();
$voucher->member_id = $roll->member_id;
...
// Correct me if I am wrong, form your table structure it looks like you linked table voucher and setting with 'value'
// I strongly recommend you to have setting_id as foreign key in table voucher
// So you could do
// $setting = Setting::where('Setting', 'weekly Subs')->where('Value', 10)->first();
// $voucher->setting_id = $setting->id;
$voucher->save();
return redirect(action('RollController#index'))->with ('success', 'Member Paid with Vocuher');
}
}
return redirect(action('RollController#index'));
}

Resources