save many to many relation in Laravel elequent 5? - php

I have three table,employees,allowances and emp_allowances
In employees
id
name
In allowances
id
title
amount
In emp_allowances
employees_id
allowances_id
amount
Model functions are, Employee
public function empAllowances() {
return $this->belongsToMany('App\Model\EmplAllowance', 'emp_allowances', 'employees_id', 'allowances_id');
}
Allowance
public function employees() {
return $this->belongsToMany('App\Model\Employee');
}
It is working here $emp->empAllowances()->sync([1]); but when I am following this method,I can not save amount.
How can I save employee allowance details with amount?

try
$emp->empAllowances()->sync([1 => ['amount' => 10]])
Search for Adding Pivot Data When Syncing here

Related

How to load just the active relationships in laravel?

I have a query and I am loading 3 relations as below:
$data = Hotel::with('rooms.discount')
->whereHas('rooms.discount')->paginate(10);
return DiscountResource::collection($data);
relations like below :
public function Rooms()
{
return $this->Hasmany(Room::class);
}
and the discount relation with room
public function discount()
{
return $this->belongsTo(Discount::class, 'id', 'room_id');
}
So now every hotel has 50 hotels for example and among them only 1 room has the discount I want just to show that 1 room this code now shows all rooms nether they have discount or not if not it shows null for them but I don't want to show the room without discount in my API because it can make it so heavy.
Now it looks like tablea are realted in such a way:
Hotel[id], Room[id, hotel_id], Discount[id, room_id]
That means that Rooms->Discount is not belongsTo() -> it is hasMany(), hence should be named as: Room->Discounts() - so one room has several discounts:
public function discounts()
{
return $this->hasMany(Discount::class, 'id', 'room_id');
}
And based on this - there could be placed one more relation in Hotel:
public function roomDiscounts()
{
return $this->hasManyThrough(Discount::class, Room::class, 'hotel_id', 'room_id', 'id', 'id');
}
So, you want to find all hotels where rooms have discounts:
$hotels = Hotel::whereHas('roomDiscounts')->get();
Hope it will help.

How to split orders between sellers and buyers Laravel?

I'm building a platform where a user can sign up and add products to sell. Also another user can buy products listed. When a buyer place an order, i want it to be seen by a seller(user) who listed the product. Right now all users can see all orders even if they are not sellers.
I have no idea how to proceed but here is my
order function in product controller
//Orders View Function
public function viewOrders(){
$orders = Order::with('orders')->orderBy('id','Desc')->get();
return view('orders')->with(compact('orders'));
}
Any help will be appreciated.
Your viewOrders action should be hidden behind authentication process (obviously, user has to first sign in before he can view his orders). Once you do that (using auth middleware for it's route), Laravel can resolve authenticated user for you - you can simply hint it as a parameter of your viewOrders action:
public function viewOrders(User $user)
{
$orders = $user->orders()->orderBy('id', 'desc')->get();
return view('orders')->with(compact('orders'));
}
As you notice, here I've modified your query a little bit. Instead of selecting all orders we are now selecting them through authenticated user's relation to it's orders. Orders obviously belong to user, but through products (as an intermediate) - one user can have many products, one product can have many orders, thus one user can have many orders. In Laravel this kind of relationship between eloquent models is called HasManyThrough. Therefore you should declare it in your User model:
class User extends Model {
...
public function orders()
{
return $this->hasManyThrough(Order::class, Product::class);
}
}
Note that your Product will probably also have orders() relation, but it will be of HasMany type instead since it's a direct one without any intermediates.
Filter your query base on your needs
Example:
Model Relationship
public function orders(){
return $this->hasMany(Order::class);
}
public function getMyOrders(User $user){
$orders = Order::with('orders')->orderBy('id','Desc')->where('user_id','=', $user->id)->get();
return view('orders')->with(compact('orders'));
}
To get sellers Orders
public function getSellerOrders(User $user){
$products = Product::where('user_id', '=', $user->id)->get();
$orders = [];
foreach($products as $product){
array_merge($orders, $product->order);
}
return view('orders')->with(compact('orders'));
}
In your DB table for orders you are suggested to have 2 IDs, one which denotes Buyer and Other which denotes Seller, i.e., Whenever a user places an order, then it must be a buyer then insert it's(buyer) ID into buyer_id in Order's table, similarly the product_id for denoting produc from Products' Table should be there and from Product's Table you can get seller_id which is suggested to be there for denoting which seller owns a particular product. Insert seller_id into Order's Table and use it to your query as:
$seller = Order::where('seller_id',$variable_for_product_id)->with('orders')->get();
Do this for all sellers in your Order's Table

How to organize this context? Two tables or just one?

I have a context of registrations at conferences. A registration has only one step if is a free registration. If is a paid registration there are two steps.
The first step of the registration consists of the user fill in a registration form and after click in the "Store Registration" button the info is stored in database and the column "status" of the registratins table is stored always with value "I" (incomplete).
If is a free registration there are no additional steps.
But if its a paid registration there is another step. In this step 2 the user needs to pay the registration before the conference start date. After the payment of the registration the column "status" of the registrations table stays with value "C" (complete).
Doubt:
If is a paid registration, after the step1 is necessary to issue a proforma invoice to the user and after the step2, that is, after the payment is necessary to issue a invoice/receipt to the user.
My doubt is how to organize the database for this context of issue proformas and invoices. In each paid registration is necessary to issue first a proforma after the user click in the "Store registration" button and all registration info is stored in db and then an issue an invoice after the payment. Is necessary to have two models/tables "Invoices" and "Proformas" and each one has a 1 to 1 relationship with Registration table. Or its just necessary 1 table related to the Registration table?
For now, I created two tables Proforma and Invoice and the relationships of these tables with the Registration table is like below 1 to 1, but I dont know if its correct.
Tables structure:
registration columns: id, status, conference_id, user_that_did_registration
proformas: id, proforma_number, registration_id
invoices: id, invoice_number, registration_id
Relevant models for the question:
Registration Model:
class Registration extends Model
{
public function customer(){
return $this->belongsTo(User::class, 'user_that_did_registration', 'id');
}
public function participants(){
return $this->hasMany('App\Participant');
}
public function registration_types(){
return $this->belongsToMany('App\RegistrationType', 'registration_registration_types');
}
public function conference(){
return $this->belongsTo('App\conference');
}
public function proforma()
{
return $this->hasOne('App\Proforma');
}
public function invoice()
{
return $this->hasOne('App\Invoice');
}
}
Proforma model:
class Proforma extends Model
{
public function registration()
{
return $this->belongsTo('App\Registration');
}
}
Invoice model:
class Invoice extends Model
{
public function registration()
{
return $this->belongsTo('App\Registration');
}
}
Based on your description, your design looks pretty close. Since not all Registrations have Proformas or Invoices, it makes sense to have Proformas and Invoices in a separate table. I would only make one change - if the relationship between Proformas and Invoices is truly 1 to 1, then you can put all the fields in a single record:
Proformas
ID
Registration_ID
Proforma_Number
Invoice_Number

Laravel Eloquent Relationship Filter by Column of Relationship

I have 3 Tables
Product:[Table]
Person:[Table]
Payment:[Table]
Many To Many Relationship Between Product and Person
One To Many Relationship Between Product and Payment (One Product Has Many Payments)
One To Many Relationship Between Person and Payment (One Person Has Many Payments)
Payment:[Table]
id
person_id
product_id
amount
The thing is that i am trying to get All persons with products and Product payments filtered by person_id.
Reason is that i dont want to have any other persons record in payments.
This is actually the query i am running yeah i know its wrong cuz i cant filter it by person_id.
$query = $person::with('product', 'payment')->where('is_active', 1);
I want to achieve something like this..
$query = $person::with(array('product', 'payment' => function ($query) {
$query->where('person_id', '=', 'person.id');
}))->where('is_active', 1);
If you setup your relations like:
class Person extends Model
{
public function payments()
{
return $this->hasMany(Payment::class);
}
}
class Payment extends Model
{
public function product()
{
return $this->belongsTo(Product::class);
}
}
Then you should be able to do:
$person = Person::with('payments.product')->where('id',$personId)->where('is_active',1)->first();
Which will return a Person with all the relations loaded and you can access those like:
#foreach($person->payments as $payment)
{{$person->name}} bought {{$payment->product->name}} for {{$payment->amount}}
#endforeach

Database relationship name & best practice for it, in my laravel app

I have a database schema in my laravel app. In that schema, there are three models - Boss, Employee & Review.
A Boss can have many employees. An Employee can have many bosses(we can consider bosses from previous jobs). An Employee can Review his/her Boss. Boss can't Review anyone, so only Employee can review.
Thus, there are these relationships -
Employee & Boss has many-to-many relationship
Employee & Review has one-to-many relationship ( one Employee can Review multiple Bosses, thus having multiple reviews from his/her side ).
As you can see there is no direct relationship between Boss & Review. But, the query is -
What are the reviews for Boss 'x'?
To answer this query in laravel, I first thought that it had 'hasManyThrough' relationship. But, 'hasManyThrough' works only when Boss & Employee have 'one-to-many' relationship. That is, when one Boss can have multiple Employee but not vice-versa.
So, my question is - Is there a relationship which is applicable in this scenario(like polymorphic etc.)? If yes, how to use it in laravel?
No need for that extra table with reviews.
Here's all you need - first the tables:
bosses: id, ...
employees: id, ...
boss_employee: id, boss_id, employee_id, review (nullable), ...
Then the models:
// Boss model
public function employees()
{
return $this->belongsToMany('Employee')->withPivot('review');
}
public function reviews()
{
return $this->hasMany('Review');
}
// Employee model
public function bosses()
{
return $this->belongsToMany('Boss')->withPivot('review');
}
public function reviews()
{
return $this->hasMany('Review');
}
// Review model
protected $table = 'boss_employee';
public function boss() // or eg. reviewed
{
return $this->belongsTo('Boss');
}
public function employee() // or eg. reviewer
{
return $this->belongsTo('Employee');
}
Now, with this setup you can do this:
// get boss and his review
$boss = $employee->bosses->first();
$review = $boss->pivot->review;
// get review for given boss of an employee
$review = $employee->reviews()->where('boss_id', $bossId)->first();
// get bosses with reviews
$bosses = Boss::whereHas('reviews', function ($q) {
$q->whereNotNull('review');
})->get();
// and so on and so forth
You can enhance your Review model by adding global scope so it returns only the rows from boss_employee table having not null review field. This would be pretty much the same as SoftDeletingScope, but the conditions need to be swapped - by default whereNotNull, instead of whereNull in the SoftDeletingScope.

Categories