Property does not exist on this collection instance. (Laravel 6) - laravel

I have a for-loop that adds <td> rows on my table. Problem is, I cannot access the attributes of my Schedule model and it keeps giving me
Property [date_of_shift] does not exist on this collection instance.
<table class="table table-bordered table-responsive">
<thead>
<th>Employee</th>
<!-- Format of date_of_shift field: format('Y-m-d') -->
#for ($i = 0; $i < 7; $i++)
<th>
{{ \Carbon\Carbon::today()->addDays($i)->format('F j, Y') }}<br />
{{ \Carbon\Carbon::today()->addDays($i)->format('D') }}
</th>
#endfor
</thead>
<tbody>
#foreach ($employees as $employee)
<tr>
<td>{{ $employee->user->last_name }}, {{ $employee->user->first_name }} {{ $employee->user->maiden_name }} </td>
#for ($j = 0; $j < 7; $j++)
#if ( $employee->schedule->date_of_shift == \Carbon\Carbon::today()->addDays($j)->format('Y-m-d') )
<td>{{ $employee->schedule->time_of_shift }}</td>
#else
<td><strong>REST DAY</strong></td>
#endif
#endfor
</tr>
#endforeach
</tbody>
</table>
Employee.php
public function schedule () {
return $this->hasMany('App\Schedule');
}
Schedule.php
public function employee () {
return $this->belongsTo('App\Employee');
}
What is a workaround for this?

Since your relationship is HasMany the $employee->schedule returns an instance of collection so in your case the easiest thing you can do is to get ->first() result of the collection...
#if ( $employee->schedule->first()->date_of_shift == \Carbon\Carbon::today()->addDays($j)->format('Y-m-d') )
<td>{{ $employee->schedule->first()->time_of_shift }}</td>
#else
<td><strong>REST DAY</strong></td>
#endif
OR
Or don't change any code in your blade instead change your relation from HasMany to HasOne
public function schedule () {
return $this->hasOne('App\Schedule');
}

Employee.php
public function schedules () {
return $this->hasMany('App\Schedule');
}
Schedule.php
public function employees () {
return $this->belongsTo('App\Employee');
}
And According to this employee can have many schedule so you cant do like
#if ( $employee->schedules->date_of_shift == \Carbon\Carbon::today()->addDays($j)->format('Y-m-d') )
<td>{{ $employee->schedules->time_of_shift }}</td>
#else
You have to use #foreach if u want to check many schedules
You can try this
#foreach($employee->schedules as $schedule)
#if ( $schedule->date_of_shift == \Carbon\Carbon::today()->addDays($j)
>format('Y-m-d') )
<td>{{ $schedule->time_of_shift }}</td>
#else
#endforeach
But if u want the latest one you can just utilize first() method like this
#if ( $employee->schedule->first()->date_of_shift == \Carbon\Carbon::today()->addDays($j)
>format('Y-m-d') )
<td>{{ $employee->schedule->first()->time_of_shift }}</td>
#else
But in case of schedule . It belongs to one employee so you dont have to use foreach
Thanks . Let me know if it helps

Related

Value correlation from multiple tables in laravel

I have two tables. One employees and one timesheets
I would like to have correct name at the result but different ID. If you see the result I have the same name everywhere.
How can make the code to fixed my challenge?
Thank you.
In controller I have this code
$profile = ['no' => Auth::user()->no];
$timesheets = Timesheet::where($profile)->select('*')->orderBy('created_at','DESC')->get();
foreach ($timesheets as $employee) {
$emp = ['identification' => $employee->identification];
$oneemployee = Employees::where($emp)->select('*')->orderBy('created_at','DESC')->get();
}
return view('contractor.employees.timesheets', compact('timesheets', 'oneemployee'));
and in blade I have
#foreach ($timesheets as $row1)
<tr>
<td>#</td>
#foreach ($oneemployee as $row2)
<td>{{ $row2->fname}}</td>
<td>{{ $row2->lname}}</td>
#endforeach
<td>{{ $row1->identification}}</td>
<td>{{ $row1->week}}</td>
<td>{{ $row1->year}}</td>
</tr>
#endforeach
According to your commit, I suggest the following solution
If you want dispay timesheet with employees you can use eager loading.
For example:
In your controller:
$profile = ['no' => Auth::user()->no];
$timesheets = Timesheet::where($profile)->with("employees")->select('*')->orderBy('created_at','DESC')->get();
return view('contractor.employees.timesheets', compact('timesheets'));
In your Timesheet model add hasOne relation to Employee:
public function employee(){
return $this->hasOne(Employee::class,'identification','identification')
}
And your view:
#foreach ($timesheets as $timesheet)
<tr>
<td>#</td>
<td>{{ $timesheet->employee->fname}}</td>
<td>{{ $timesheet->employee->lname}}</td>
<td>{{ $timesheet->identification}}</td>
<td>{{ $timesheet->week}}</td>
<td>{{ $timesheet->year}}</td>
</tr>
#endforeach

How to calculate using data from get() in controller

I have some data from a table and I'm doing an eloquent get for it. So far from what I know is when using get(), I need to loop it first using foreach to get the data.
My question is how to move my logic code to controller? so I just need to pass it to view. Because I'm doing it on blade directly
Bellow is my controller, I'm just simply get a data from database:
$attendances = Attendance::where('company_id', Auth::user()->company_id)->get();
#foreach ($attendances as $attendance)
// How to move this php code to my controller?
#php
$work_hour_start = $attendance->work_hour_start;
$attendance_time = \Carbon\Carbon::parse($attendance->attendance_time)->format('H:i:s');
$tolerance = \Carbon\Carbon::parse($attendance_time)->addMinutes($attendance->late_tolerance);
if ($tolerance > $work_hour_start) {
$is_late = 'Late';
} else {
$is_late = 'On Time';
}
#endphp
<tr>
<td>{{ $attendance->employee->name }}</td>
<td>{{ Carbon\Carbon::parse($attendance->attendance_time)->format('H:i:s') }}</td>
<td>{{ $attendance->location_library->location_name }}</td>
<td>{{ $is_late }}</td>
</tr>
#endforeach
I want my blade to be clean, but I don't know how to do that.
You could add attendance_time to the $casts property and make tolerance/is_late accessors in the Attendance Model
# Attendance.php
class Attendance extends Model
{
...
protected $casts = [
'attendance_time' => 'datetime',
];
...
public function getToleranceAttribute()
{
return $this->attendance_time->addMinutes($this->late_tolerance);
}
public function getIsLateAttribute()
{
return $this->tolerance > $this->work_hour_start
? 'Late'
: 'On time';
}
...
}
#foreach ($attendances as $attendance)
<tr>
<td>{{ $attendance->employee->name }}</td>
<td>{{ $attendance->attendance_time->format('H:i:s') }}</td>
<td>{{ $attendance->location_library->location_name }}</td>
<td>{{ $attendance->is_late }}</td>
</tr>
#endforeach
Just do it, move the logic to your controller and set it up in your $attendances collection. Something like this:
$attendances = Attendance::where('company_id', Auth::user()->company_id)->get();
foreach ($attendances as $key => $attendance){
$attendances[$key]->attendance_time = \Carbon\Carbon::parse($attendance->attendance_time)->format('H:i:s');
if (\Carbon\Carbon::parse($attendances[$key]->attendance_time)->addMinutes($attendance->late_tolerance > $attendance->work_hour_start) {
$attendances[$key]->setAttribute('is_late', 'Late');
} else {
$attendances[$key]->setAttribute('is_late', 'On Time');
}
}
return view('your-view', ['attendances' => $attendances]);
Now it will be able to iterate on your template:
#foreach ($attendances as $attendance)
<tr>
<td>{{ $attendance->employee->name }}</td>
<td>{{ $attendance->attendance_time }}</td>
<td>{{ $attendance->location_library->location_name }}</td>
<td>{{ $attendance->is_late }}</td>
</tr>
#endforeach

Laravel need data from two different collections in for each

I have a for each loop to iterate over the collection of records. It has the user_id, but not the other user credentials. I created another collection of user. How do I include this in my iteration?
Controller
public function index(Request $request, $id)
{
$thoughts = Thought::where('id', $id)->orderBy('created_at', 'desc')->paginate(100)->get();
$user = User::where('id', $thoughts->user_id);
return view('backend.pages.thought_list', compact('thoughts, user'));
}
View
#foreach ($thoughts as $thought)
<tr>
<td class="col-md-1">{{ $user->username}} <span class="user_id_thought">ID - {{ $user->user_id}}</span></td>
<td class="col-md-1">{{ $thought->response }}</td>
<td>{{ $thought->thought_type }}</td>
<td>{{ $thought->id }}</td>
</tr>
#endforeach
How do I display my users variable in the loop. Or is there a better way of doing this.
Eager Loading is the perfect use case for your requirement in my opinion.
e.g.
$thoughts = Thought::with('user')->get();
foreach ($thoughts as $thought) {
echo $thought->user->name;
}
For more details see: https://laravel.com/docs/5.6/eloquent-relationships#eager-loading

Accessing and displaying pivot table data

Theory:
Users can attend many events and many events can be attended by many users. Therefore, I have two many-to-many relationships within my models, linking to a pivot table (event_user). On attending each event, I want to be able to access the pivot table data (event_user) to see if they're already attending.
event_user:
--id
--event_id
--user_id
For example, my seed data is:
user 1 attending both event 2 and 3. I want to be able to show this within a view.
The closest I have got is (logically):
public function index()
{
$id = Auth::user()->id;
$attending = myApp\Event::find($id)->event;
var_dump($attending); **But this var_dump returns NULL, but $id returns the correct ID.**
$events = myApp\Event::all();
$this->layout->content = View::make('events.index')->with('events', $events);
}
My aim is to disable the 'attend' button, on any event where they are already attending, only leaving the attend-able events available!
Any help would be hugely appreciated. Thank you in advance.
Any additional code which you may find necessary:
Events Model:
<?php
namespace myApp;
use Eloquent;
class Event extends Eloquent {
public function consultant()
{
return $this->belongsToMany('myApp\Consultant');
}
public function location()
{
return $this->belongsToMany('myApp\Location');
}
public function user()
{
return $this->belongsToMany('myApp\User');
}
}
User Model:
<?php
namespace myApp;
use Eloquent;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface {
public function event()
{
return $this->belongsToMany('Event');
}
public function practice()
{
return $this->belongToMany('Practice');
}
index.blade.php (showing the event list)
<div class="panel panel-success">
<!-- Default panel contents -->
<div class="panel-heading"><strong>Events</strong></div>
<!-- <div class="panel-body">
</div> -->
<!-- Table -->
<table class="table">
<thead>
<tr>
<th>Title</th>
<th>Date</th>
<th>Presenter</th>
<th>Location</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach($events as $event)
<tr>
<td>{{ $event->title }}</td>
<td>{{ date("j F Y", strtotime($event->date)) }}</td>
<td>{{ $event->consultant()->first()->title }} {{ $event->consultant()->first()->surname }}</td>
<td>{{ $event->location()->first()->address_1 }}</td>
<td><button type="button" class="btn btn-info">Attend</button></td>
</tr>
#endforeach
</tbody>
</table>
</div>
</table>
I think you're going about this the wrong way, that or I have misunderstood.
Firstly, you're trying to find an event with the same primary key as the currently authenticated user, which isn't correct, although it's an easy hole to fall down.
$id = Auth::user()->id;
$attending = myApp\Event::find($id)->event;
// equivalent of: SELECT * FROM `events` WHERE `id` = ?
Instead you'll want to do this
$id = Auth::user()->id;
$attending = myApp\Event::where('user_id', $id)->get();
// equivalent of: SELECT * FROM `events` WHERE `user_id` = ? (user_id insted of events.id)
That being said, surely the user events can be accessed by just calling the event property on the auth user?
$user = Auth::user();
$attending = $user->event;
To take this one step further, and make it so that you can check inside the foreach loop, you could advanced the above code to look like the following
$user = Auth::user();
$attending = $user->event->lists('id');
This will make an array of ids from the returned events that you need to assign to the view
$this->layout->content = View::make('events.index', array('events' => $events, 'attending' => $attending));
Now you can freely access it in your foreach
#foreach($events as $event)
<tr>
<td>{{ $event->title }}</td>
<td>{{ date("j F Y", strtotime($event->date)) }}</td>
<td>{{ $event->consultant()->first()->title }} {{ $event->consultant()->first()->surname }}</td>
<td>{{ $event->location()->first()->address_1 }}</td>
<td>
#if (!in_array($event->id, $attending))
<button type="button" class="btn btn-info">Attend</button>
#endif
</td>
</tr>
#endforeach
Also, seeing as Event is a reserved Alias (unless you've modified the config, which I wouldn't recommend), you'll want to specify the namespace in the relationship declaration within User
public function event()
{
return $this->belongsToMany('myApp\Event');
}
As a final point, it's not an issue as such, but in my own code I try to name relationships that have the potential to return multiple objects in the plural, so it would be public function events();.

increment row number with laravel pagination

How to make increment row number with laravel pagination ? When i use pagination and i go to page 2 and above it will back to beginning. for example i will paginate(3)
<thead>
<tr>
<th>No</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<?php $i = 1; ?>
#foreach ($telephone->results as $telp)
<tr>
<td>
{{$i++}}
</td>
<td>{{ $telp->name }}</td>
</tr>
#endforeach
</tbody>
when i go to page 2 the number will start from 1 again.
i need to make it when i go to page 2 it will start from 4
In Laravel 5.3 you can use firstItem():
#foreach ($items as $key => $value)
{{ $items->firstItem() + $key }}
#endforeach
The below works with laravel 5.4
<?php $i = ($telephone->currentpage()-1)* $telephone-
>perpage() + 1;?>
#foreach($telephone as $whatever)
<td> {{ $i++ }}</td>
#endforeach
Edited
The below works for laravel 5.7 above
#foreach ($telephone as $key=> $whatever)
<td>{{ $key+ $telephone->firstItem() }}</td>
#endforeach
You should be able to use the getFrom method to get the starting number of the current pages results. So instead of setting $i = 1; you should be able to do this.
<?php $i = $telephone->getFrom(); ?>
In Laravel 3 there is no getFrom method so you need to calculate it manually.
<?php $i = ($telephone->page - 1) * $telephone->per_page + 1; ?>
Laravel 5.3
#foreach ($products as $key=>$val)
{{ ($products->currentpage()-1) * $products->perpage() + $key + 1 }}
#endforeach
For Laravel 6.2:
$loop - just in case, is a built-in instance in Blade
#foreach($array as $item)
<tr class="table-row">
<td class="site-id">
{{($array->currentPage() - 1) * $array->perPage() + $loop->iteration}}
</td>
</tr>
#endforeach
</table>
You can simply add the following line
$i = ($telephone->currentpage()-1)* $telephone->perpage();
in place of
$i = 1;
#php($sl = ($yourVariable->perPage() * $yourVariable->currentPage()) - ($yourVariable->perPage() - 1))
#foreach($yourVariable as $item)
<td>{{ $item->key_name }}</td>
.....
#php($sl++)
#endforeach
In Laravel 6
#php $i = ($data->currentpage()-1)* $data->perpage() + 1;#endphp
#foreach($data as $banner)
<tr>
<td>{{$i}}</td>
<td><img src="{{ URL::to('/') }}/dist/img/{{$banner->name}}" height="250" width="600"></td>
</tr>
#php $i += 1; #endphp
#endforeach
If you are using Laravel Pagination. It works very well
The backend
public function index()
{
return view('your.telephone.index', [
'telephone' => Telephone::paginate(15)
]);
}
Blade front end
<td>{{ (($telephone->currentPage() * 10) - 10) + $loop->iteration }}</td>
And don't forget embed the page
{{ $telephone->links() }}
For $loop->iteration
See the doc here: https://laravel.com/docs/7.x/blade#the-loop-variable
For $telephone->currentPage()
See the doc here: https://laravel.com/docs/7.x/pagination#paginator-instance-methods
Or avoid php tags completely by
#foreach ($users as $key => $user)
{{ (Input::get('page', 1) - 1) * $users->getPerPage() + $key + 1 }}
#endforeach
You can use it in your controller. example given below
$records = Table::paginate(20);
return view('yourview',compact('records')->with('i', ($request->input('page', 1) - 1) * 20);
Note: paginate value must be equal to with() function vlaue
after that you can use $i variable in you blade file. controller calculate value according to page number and return to blade
In blade file. use inside the loop
{{ ++$i }}
Hopefully this will help you
Laravel 8++
$loop->iteration is available out of the box inside loop.
{{ ($barangs->currentPage() - 1) * $barangs->count() + $loop->iteration }}
I'm using this, in Laravel 8, accessing $loop, and links()->paginator:
#foreach ($users as $user)
<tr>
<td class="text-center">{{ ($users->currentPage() - 1) * $users->links()->paginator->perPage() + $loop->iteration }}</td>
<td class="text-center">{{$user->name}}</td>
</tr>
#endforeach
Which works properly even when the final page is only partially filled.
Could also use $users->perPage() in place of $users->links()->paginator->perPage()

Resources