How to load just the active relationships in laravel? - php

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.

Related

Laravel: How to count data in database?

I want to make a list of students to know how many products each student buys. I have two tables : Member and Orders. In Orders table have column member_id and product_id. I want to count how many products each student buys. I can get list of student but i can't count how many products each student buys.
public function index()
{
$students = Member::getStudents();
$order = Order::where('member_id', $students->id)->count();
return view('admin.student.index', compact('students'));
}
But it appears an error:
Property [id] does not exist on this collection instance.
function getStudents()
public static function getStudents()
{
$members = Member::where('member_type_id', BaseModel::$student)->get();
for ($idxMember = 0; $idxMember < count($members); $idxMember++) {
if ( $members[$idxMember]->user_id ) {
$members[$idxMember]->username = User::find($members[$idxMember]->user_id)->username;
}
}
return $members;
}
I think it is because you get a collection on id.
so you should foreach your collection and get specific ids.
public function index() {
$students = Member::getStudents();
foreach($students as $student ) {
$order = Order::where('member_id', $student->id)->count();
}
return view('admin.student.index', compact('students'));
}
I suggest to use relationships in Database. It would be more easy and simple.
In orders table, there is a column called member_id which reference to id column in members table. (Keep attention to singular plural usage)
Refer Laravel Documentation for foreign key design and implementation.
You need 2 models, Member and Order. You should define the relationship as below.
Since this is One To Many Relationship,
In Member Model,
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Member extends Model
{
/**
* Get the orders for the member.
*/
public function orders()
{
return $this->hasMany('App\Order');
}
}
?>
In Order Model,
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
/**
* Get the member that owns the order.
*/
public function member()
{
return $this->belongsTo('App\Member');
}
}
?>
Now you can get order count per user using this code.
Member::find(MEMBER_ID)->orders->count();
This will return order count of the selected member.
Please refer the Laravel Documentation here.
Relationships | One To Many | One To Many (Inverse)
You can achieve this by simply using laravel relationship
In order to do this please follow below steps
First, create two relation in members model
public function orders()
{
return $this->hasMany('App\Models\Order', 'member_id', 'id);
}
Then retrieve the students details with orders
public function getStudents()
{
return Member::where('member_type_id', BaseModel::$student)->withCount('orders)->get();
}
Hope this helps
Thank you.
Sharing solution with explanation.
Objects are
Member (Student is also a member. But the Type is different)
Order (One order can have multiple products)
Product (Product will allocate with Orders and Members can place Orders)
Now If you are using Laravel. So the best way is to use Eloquent Relationships.
Model Member :
1 Define Query Scope
public function scopeStudents($query)
{
return $query->where('member_type_id', 1);
}
2 Define One to Many relation between Order and Member (One Student can have multiple orders. And I hope that other members can also have orders. So i am going to relate direct Member to Order)
public function orders()
{
return $this->hasMany('App\Order');
}
and
public function products()
{
return $this->hasManyThrough('App\Product', 'App\Order');
}
Model Order :
1 Define relation with Member Model for One to Many
public function member()
{
return $this->belongsTo('App\Member');
}
2 Define one to many between Order and Product
public function products()
{
return $this->hasMany('App\Product');
}
Model Product :
1 Define Order Product Relation
public function order()
{
return $this->belongsTo('App\Order');
}
Now the Model work is done. Only data fetching is remaining. Tell me in comments if you think below code is less and useful and easy to understand.
Controller Member :
1 Index Function :
// this will fetch all students with their orders and products
$data = Member::students()->with('orders', 'products')->get();
// this will fetch all students with their orders and order's products
$data = Member::students()->with('orders.products')->get();
// this will fetch all students with their orders count and products count
$data = Member::students()->withCount('orders', 'products')->get();

Converting Query Builder to Eloquent in Laravel

I have a user table, and a review table.
In my review table, there's a "star_rating" column.
I can get the average "star_rating" score for a user with the following query:
$star_rating = Review::where('artist_id', $user->id)->avg('star_rating');
However, this doesn't work too well when I'm printing out a bunch of users in blade (I want to show their average star_rating next to their names).
That's why I'd like to have a function in my User.php model that I can call to get a user's average star rating.
public function getAvgStarRating() {
return $this-> // logic goes here //;
}
Add this relation in your User model:
public function reviews()
{
return $this->hasMany(Review::class, 'artist_id', 'id');
}
Then add this method to get average of star ratings
public function getAvgStarRating()
{
return $this->reivews->avg('star_rating');
}
And if you need to display a group of user's rating, first eager load their reviews (it is more efficient)
$users = User::with('reviews')->get();
Then
foreach($users as $user) {
$user->getAvgStarRating();
}

Insert in many to many relation laravel 5

I have 2 models:
class Order extends Model
{
protected $fillable = ['user_id','name','surname','fathers_name','phone_number','city','post_office','comment'];
public function user()
{
return $this->belongsTo('App\User');
}
public function products()
{
return $this->belongsToMany('App\Product', 'order_product');
}
}
class Product extends Model
{
public function order()
{
return $this->belongsToMany('App\Order', 'order_product');
}
public function category()
{
return $this->belongsTo('App\Category');
}
}
3 tables:
product:
id
name
...
order_product:
id
order_id
prod_id
qty
...
order
id
city
phone
...
and 2 arrays of data:
$data = $request->except('_token','submit'); - information about client
$order_content - array with info about products in cart
So, the question is how to insert all this data in DB? I tried to read about many to many insertion: sync, attach, etc.. but understood nothing :c
Imagine you have a product with id 1. And an order with id 1. The product is part of the order, so you have to attach them. You do
$product = Product::find(1);
$order = Order::find(1);
$order->products()->attach($order->id);
However, in your case, your pivot table has more data, like 'qty'. Then you do,
$order->product()->attach($order->id, ['qty' => 2]);
So far, we were only attaching a single product to an order. If you want to attach many products simultaneously, you do:
$order->products()->sync([
$product->id => ['qty' => 1],
$product2->id => ['qty' => 3]
]);
I hope this helps understand better. I recommend you read the doc again and again until it makes sense.

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

save many to many relation in Laravel elequent 5?

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

Categories