Foreach according to collection attribute - php

I have a existing laravel project on php 7.4.
It has users table, patient_appointmnets table.
In users table it contains both patient and doctor with role_id
And there is a doctor_details table which contain only basic info.
The patient_appointments table has
user_id, doctor_id, date, start_time and end_time
The problem is if do
PatientAppointment:whereDate('date', Carbon:now()->format('Y-m-d')->get() ;
And use foreach in blade
I get appointments wise column.
So e.g if a doctor has multiple appointments on that day. I got same doctor column multiple times.
But i want all appointments go in single column for particular dooctir id.
There is no direct doctor tablebwhich contains appointment. On patient_appointmnets table has doctor_id and user_id
So i want collection according to doctor where it contains all appintment
I could do join like:
$var = DoctorDetail:join('users.id', '=', 'doctor_derail.user_id')->select('doctor_detail.*')->get();
then,
for(i=0; i <= count($var) ; i++)
{
$var[$i->appointments] = PatientAppointment::whereDate('date', Carbon::now()->format('Y-m-d')->get();
}
return $var;
but not work. But in dd it show appointments inside doctor_detail collection. But if i do foreach in blade, it shows builder:get() expects 1 for very first get() query..
Any other solution to do same thing.

I believe the key to solve your problem is to use the groupBy method after retrieving all the appointments.
I assume you got the following relationships in the User and PatientAppointment table.
class User extends Model
{
public function doctorDetail()
{
return $this->hasOne(DoctorDetail::class);
}
}
class PatientAppointment extends Model
{
public function doctor()
{
$this->belongsTo(User::class, 'doctor_id');
}
public function patients()
{
$this->belongsTo(User::class, 'patient_id');
}
}
In the controller, you can retrieve all the appointments on that day and group by the doctor_id field, so you got all the appointments belonging to the same doctor:
public function index()
{
$appointmentsGroupedByDoctors = PatientAppointment:whereDate('date', Carbon:now()->format('Y-m-d'))
->get()
->groupBy('doctor_id');
return view(..., compact('appointmentsGroupedByDoctors'));
}
In the view, you can do something like:
#foreach($appointmentsGroupedByDoctors as $doctorId => $appointments)
<p>Doctor Name: {{$appointments->first()->doctor?->doctorDetail->name}}</p>
#foreach($appointments as $appointment)
// Listing the appointments belonging to the same doctor here.
#endforeach
#endforeach

Related

Laravel - Displaying fields with many to many relationship according field in pivot table

I have this database structure
table users table office_user table offices
----------- ----------------- -------------
id * id * id *
full_name user_id name
office_id
joined_at
So in my project every office has many users and user can be joined to many offices in date (joined_at)
User.php model
public function offices()
{
return $this->belongsToMany('App\Office)->withPivot('joined_at');
}
Office.php model
public function users()
{
return $this->belongsToMany('App\User)->withPivot('joined_at');
}
OfficeController.php
public function show(Office $office)
{
$users = User::with(array('phones', 'offices' , function($query)
{
$query->orderBy('joined_at', 'desc');
}))->get();
return view('dashboard.offices.show', compact(['office', 'users']));
}
I need two things :
1- Get current users list for every office
2- Count of current users in every office
I already achieve this:
<h3>{{ $office->name }}</h3><span>{{ $office->users->count() }}</span>
#foreach ($office->users as $user)
<li>{{ $user->full_name }}</li>
#endforeach
But the result is not as expected it gives me all users in certain office and count of them regardless there joined date
I want the list of last joined users to this office and count of them according joined_at field in pivot table
Thank you and Sorry for my english
But the result is not as expected it gives me all users in certain office and count of them regardless there joined date
When you do $office->users->count() that is the expected behavior because you are retrieve all the associated users of every office at any time, so given that you returned all this users, the count() executed in the collection will count all of them.
Your pivot attribute is just a timestamp, so how would you reduce the number of users returned? users that joined the office today/in the last hour/in the last 15 min maybe?
If so, you can add constrains to your count() method to get the results you want.
As an example, in the following lines we are gonna constraint the associated offices that has a joined_at that belongs to today:
public function show(Office $office)
{
$users = User::with([
'phones',
'offices' => function ($offices) {
$offices->whereDate('joined_at', '>', now()->startOfDay());
},
])->get();
return view('dashboard.offices.show', compact([office, 'users']));
}
Check this section of the documentation:
Constraining Eager Loads
Sometimes you may wish to eager load a relationship, but also specify
additional query conditions for the eager loading query. Here's an
example:
$users = App\User::with(['posts' => function ($query) {
$query->where('title', 'like', '%first%');
}])->get();
In this example, Eloquent will only eager load posts where the post's
title column contains the word first. You may call other query
builder methods to further customize the eager loading operation:
$users = App\User::with(['posts' => function ($query) {
$query->orderBy('created_at', 'desc');
}])->get();

Join three table by laravel eloquent model which has only one relation with each other

How to join the three table in Laravel Eloquent model. My table structure is like. It is easy with raw(mysql with left join) query to get the desired result, but it is possible to get via Eloquent.
Customer table
id
title
name
Order table(has customer id)
id
customer_id
Hour table (has order id)
id
order_id
From Hour model I want to get the Customer Details and Order Details. Now I am able to get the Order details like below.
public function order()
{
return $this->belongsTo('App\Models\Order', 'order_id', 'id');
}
How to get the Customer Details?
I tried like below, but not get success
1.return $this->hasManyThrough('App\Models\Customer','App\Models\Order','customer_id','id');
2. return $this->hasManyThrough('App\Models\Customer','App\Models\Order','customer_id','order_id');
Edit 1:
class HourLogging extends Model
{
public function order()
{
return $this->belongsTo('App\Models\Order', 'order_id', 'id');
}
$timeoverview = HourLogging::select('hour_logging.*')->whereRaw("hour_logging.date BETWEEN '".$start_date."' AND '".$end_date."'")->orderBy('date','asc');
$timeoverview->with('order.customer');
return $timeoverview->get();
}
class Order extends Model {
public function customer() {
return $this->belongsTo('App\Models\Customer');
}
}
hasManyThrough works the opposite way to what you're trying to achieve. It would let you get Hour models from your Customer model easily.
In order to get what you need you need to define the relations that go the other way - from Hour to Order to Customer. Add the following relations to your models:
class Hour extends Model {
public function order() {
return $this->belongsTo('App\Models\Order');
}
}
class Order extends Model {
public function customer() {
return $this->belongsTo('App\Models\Customer');
}
}
With those relations in place you should be able to access Order data with $hour->order and Customer data with $hour->order->customer.
One thing to remember: Eloquent offers possibility to eagerly load related data to avoid additional queries. It makes sense to do it when you fetch multiple Hour records at once. You an load all Hour records with related Order and Customer data with the following:
$hours = Hour::with('order.customer')->get();

Has many through

A Venue has many Subscriptions.
A Subscription has many Subscribers (User).
Theres a pivot table, containing the relation between user_id and subscription_id.
How can I get all Subscribers from a Venue?
I have tried with:
class Venue {
/**
* Members
*/
public function members() {
return $this->hasManyThrough('App\User', 'App\Subscription');
}
}
But it fails with MySQL error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'users.subscription_id' in 'on clause' (SQL: select `users`.*, `sub
scriptions`.`venue_id` from `users` inner join `subscriptions` on `subscriptions`.`id` = `users`.`subscription_id` where `
users`.`deleted_at` is null and `subscriptions`.`venue_id` = 1)
How my Subscription model look:
`Subscription`
class Subscription extends Model {
protected $table = 'subscriptions';
/**
* Subscripers
*/
public function subscribers() {
return $this->belongsToMany('App\User');
}
/**
* Venue
*/
public function venue() {
return $this->belongsTo('Venue');
}
}
Simple question: Why are you using a third model for Subscriptions? It sounds like a normal n:m relation between User and Venue, as already written in the comments above.
class User {
public function venues() {
return $this->belongsToMany('App\Venue');
}
}
class Venue {
public function users() {
return $this->belongsToMany('App\User');
}
}
This constellation actually needs three tables, which are (i gave each model a column name):
users
- id
- name
venues
- id
- name
user_venue
- user_id
- venue_id
But to access the relations, you can simply use the Eloquent magic:
// List of all venues (as Venue models) that are in relation with User with id $id
$venues = User::find($id)->venues()->get();
// Returns the alphabetically first user that has a relation with Venue with id $id
$user = Venue::find($id)->users()->orderBy('name', 'asc')->first();
If you need to store additional information in the pivot table (e.g. when the relation has been established), you can use additional pivot fields:
user_venue
- user_id
- venue_id
- created_at
class User {
public function venues() {
return $this->belongsToMany('App\Venue')->withPivot('created_at');
}
}
class Venue {
public function users() {
return $this->belongsToMany('App\User')->withPivot('created_at');
}
}
// Returns the date of the relations establishment for the alphabetically
// first Venue the User with id $id has a relation to
$created_at = User::find($id)->venues()->orderBy('name', 'asc')->first()->pivot->created_at;
I've never tried to do whatever you are trying to do there, because it seems (with the current information) conceptually wrong. I also don't know if it is possible to set up an own model for a pivot table, but I think it should work if the pivot table has an own primary id column. It could probably be helpful if you've a third model that needs to be connected with a connection of two others, but normally that doesn't happen. So try it with pivot tables, like shown above, first.
Alright, I still don't see a good use case for this, but I can provide you a query that works. Unfortunately I wasn't able to get an Eloquent query working, but the solution should be still fine though.
class Venue {
public function members($distinct = true) {
$query = User::select('users.*')
->join('subscription_user', 'subscription_user.user_id', '=', 'users.id')
->join('subscriptions', 'subscriptions.id', '=', 'subscription_user.subscription_id')
->where('subscriptions.venue_id', '=', $this->id);
if($distinct === true) {
$query->distinct();
}
return $query;
}
}
The relation can be queried just as normal:
Venue::find($id)->members()->get()
// or with duplicate members
Venue::find($id)->members(false)->get()

Eloquent many to many relationship access table column value from pivot table

I have two models:
class Order extends Eloquent
{
public function User()
{
return $this->belongsTo('User');
}
public function Product()
{
return $this->belongsToMany('Product');
}
}
and the second one is:
class Product extends Eloquent
{
public function Order()
{
return $this->belongsToMany('Order');
}
}
My question is how can i access a value of second table column using pivot table:
product table:
id
title
image
order table:
id
status
pivot table(order_product):
id
product_id
order_id
I need to access title column of products from orders. for example if a user orders many products in one order I can fetch all product title and show theme.
I don't like use join , instead I like to use Laravel functionality itself.
I found the answer:
$orders = Order::orderBy('created_at', 'DESC')->paginate($page_number);
foreach($orders as $item){
foreach($item->product as $item){
{{$item->title}}<br>
}
}
I can access products from order.

Eloquent order by one-to-one-related column

Good morning everyone!
I'm using Laravel 5.0 and Eloquent to build a displaying page for results of some replies on the database.
Replies are in reservations table, which "belongs" to users table since every reservation is linked to a person.
class Reservation extends Model {
public function user()
{
return $this->belongsTo('App\User');
}
}
I would like to display results, the reservations, ordered by the last name column of the user. So like:
$reservations = Reservation::orderBy( /*users.last_name*/ )->get();
But I dont'know how. Thank you in advance for your time.
You'll need to join the tables to order by a foreign column.
$reservations = Reservation::join('users', 'users.id', '=', 'users.reservation_id')
->orderBy('users.last_name', 'asc')->get();

Categories