How to have different view based on date in Laravel - php

I'm having a problem in having a different view by comparing today's date and expired date. Before I'm telling deeper about my problem, let me show you the code:
buyer table
id
name
address
phone_no
email
expired_at (date)
created_at
BuyerController.php
public function create(Request $request)
{
$buyers = Buyer::create([
'name' => $request->name,
'address' => $request->address,
'phone_no' => $request->phone_no,
'email' => $request->email,
'expired_at' => Carbon::today()->addDays(730),
]);
return response()->json($buyers);
}
buyers\index.blade.php
<div class="panel-body">
<table class="table table-hover" id="buyer-table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Address</th>
<th>Phone No</th>
<th>Email</th>
<th>Registered Date</th>
<th>Liability Period</th>
</tr>
</thead>
#foreach($buyers as $buyer)
<tr class="buyer{{$buyer->id}}">
<td>{{$buyer->buyer_id}}</td>
<td>{{$buyer->name}}</td>
<td>{{$buyer->address}}</td>
<td>{{$buyer->phone_no}}</td>
<td>{{$buyer->email}}</td>
<td>{{date('d/m/Y', strtotime($buyer->created_at))}}</td>
#if(now() < $buyer->expired_at)
<td class="text-success">Valid</td>
#else
<td class="text-danger">Expired</td>
#endif
</tr>
#endforeach
</table>
</div>
Until here, I manage to complete my code which I successfully compared the expired date and today's date in the table view.
web.php
Route::get('/report-form','ComplaintController#create');
ComplaintController.php
public function create()
{
return view('buyers.complaints.create');
}
However, before deciding to develop this new idea, buyer can just view the create.blade.php in order to make a new complaint. But now, if the expired_at is already passed today's date, buyer can not make any complaint which will return to view expired.blade.php.
buyers\complaints\create.blade.php
<div class="panel-heading">
<h3 class="panel-title"><strong>Make New Report</strong></h3>
</div>
//There is a form for the buyers to fill in the complaint
buyers\complaints\expired.blade.php
<div class="panel-heading">
<h3 class="panel-title"><strong>Sorry you can't make any report</strong></h3>
</div>
I only have an idea to make if else statement in function create() but I do not know what is the correct query. What I already tried:
public function create()
{
$expired = Buyer::select('id')->where('expired_at','>', now())->get();
$valid = Buyer::select('id')->where('expired_at','<', now())->get();
if ($expired) {
return view('buyers.complaints.create');
}
elseif ($valid) {
return view('buyers.complaints.expired');
}
}
I do not know what I'm trying to do because there is no difference. If the buyers liability period has end (expired date has passed today's date) also can view the buyers\complaints\create.blade.php and I'm still new in Laravel. So, I hope there is someone can help me in figuring this out. Thank you in advanced.

You only have 2 outcomes (unless a blank response was a 3rd) so one query to check the existence of a record should work:
if (Buyer::where('expired_at', '>=', now())->exists()) {
return view('buyers.complaints.create');
}
return view('buyers.complaints.expired');
This is assuming you are looking for any Buyer who still isn't expired.
If you want to restrict this to a certain buyer and pass the buyer to the view:
$buyer = Buyer::findOrFail($buyerId);
$view = ($buyer->expired_at >= now()) ? 'create' : 'expired';
return view('buyers.complaints.'. $view, ['buyer' => $buyer]);

Related

Data Pass from controller to view

I want to display the sum of column debit. When I pass data after sum value of the debit column and store it in a variable, I pass the data from controller to my view but laravel says it's undefined. Can anyone help me with this?
View.blade.php
<tr>
<th>Total Debit:</th>
<td>
#foreach ($totaldebit as $tdebit)
{{ $tdebit }}
#endforeach
</td>
</tr>
UserController.php
$tdebit = DB::table('debitemps')->sum('debit');
return view('pages/payments/debit/debit', [
'workerlists' => $data,
'debitid' => $id,
'Empdebitdata' => $dataEmp,
'totaldebit' => $tdebit
]);

Save date into database with Carbon

I'm still new in Laravel. Currently, I'm learning and working on Carbon. I already looking on every documentation and other solution but I still don't get it. I hope there is someone can teach and show me step by step how to correct or improve my code.
ComplaintController.php
public function store(Request $request)
{
if (count($request->defect_id) > 0) {
foreach($request->defect_id as $item=>$v) {
$data = array(
'defect_id' => $request->defect_id[$item],
'image' => $filename,
'description' => $request->description[$item],
'report_by' => Auth::user()->id,
'created_at' => Carbon::today()->toDateString(),
'updated_at' => Carbon::now()->toDateTimeString()
);
Complaint::insert($data);
I'm saving created_at field as date only, no time and it is in the format of (yy-mm-dd).
index.blade.php
<div class="panel-body">
<table class="table table-hover">
<thead>
<tr>
<th>Defect Name</th>
<th>Description</th>
<th>Image</th>
<th>Report Date</th>
<th>Due Date</th>
</tr>
</thead>
#foreach($complaint as $c)
<tr>
<td>{{$c->defect->name}}</td>
<td>{{$c->description}}</td>
<td><img src="{{ Storage::url('complaint/' . $c->image)}}" class="" alt="{{$c->image}}"></td>
<td>{{$c->created_at->toDateString()}}</td>
<td></td>
</tr>
#endforeach
</table>
</div>
My date is still showing finely in the table as (yy-mm-dd) but I want the date to be in format of (dd/mm/yy) so I try to use this kind of code {{$c->created_at->toDateString()->format("dd/mm/yy")}} and there is error appeared which is Call to a member function format() on string. Later on, I need to add another field for duedate and use this function addDays(30). So, what I need to do? I'm guessing that I need to put another function in my model but I can't figure out how to do it.
As mentioned by #Tim Lewis as well,
replace
{{ $c->created_at->toDateString()->format("dd/mm/yy") }}
to
{{ $c->created_at->format("dd/mm/yy") }}
As toDateString() converts it to string before changing the format.
You can also try using standard php format for datetime, instead of Carbon class,
{{ date("d/m/Y", strtotime($c->created_at)) }}
As for your second question of you want to add new table data column ,
<tr>
<td>{{ $c->defect->name }}</td>
<td>{{ $c->description }}</td>
<td><img src="{{ Storage::url('complaint/' . $c->image)}}" class="" alt="{{$c->image}}"></td>
<td>{{ $c->created_at->format("dd/mm/yy") }}</td>
<td>{{ $c->created_at->addDays(30) }}</td>
</tr>
This should work...
To save the date in the format dd/mm/yy, I would use the following:
date('d-m-Y', strtotime(Carbon\Carbon::now()))
To reformat the date in a view, I would use:
date('d-m-Y', strtotime($c->created_at))
I prefer to use the base php functions wherever possible to keep things simple.
If someone knows a reason not to, please let me know.
As for the adding of days,
date('d-m-Y', strtotime($c->created_at) + (60 * 60 * 24 * 30))
Should work.
Most date related problems can be solved with strtotime(), its very useful. Be sure to read up on it here: https://www.php.net/manual/en/function.strtotime.php
Casted date fields:
In Laravel the created_at and updated_at fields are casted as date fields already. So you don't have to transform this into date formats.
You can simply do
<td>{{ $c->created_at->format("d/m/y") }}</td>
Fields created_at and updated_at are also automatically filled
So you don't need to fill this fields
You can simply do
$data = array(
'defect_id' => $request->defect_id[$item],
'image' => $filename,
'description' => $request->description[$item],
'report_by' => Auth::user()->id,
);
Complaint::create($data);
Extra date field duedate
When you add custom date fields you need to cast them in the model to be date.
Add this in you model:
protected $dates = ['duedate'];

Laravel collection turns empty inside foreach loops

I have 3 collections on different items that I need to show and group by date, in the blade file I loop over the dates to show these collections, but for some reason whatever the first collection is, something wrong happens with it, it shouldn't change based on the date, let's say I have two dates (2019-03, 2019-01), I end up with two different instances of the same collection, one with the data, and one without(an empty collection), even though I am calling the same variable.
The controller method:
public function index()
{
//Retrieving the Models.
$invoices_egp = auth()->user()->invoices()->where('paid', 1)->where('currency', 'EGP');
$invoices_usd = auth()->user()->invoices()->where('paid', 1)->where('currency', 'USD');
$orders = \App\Order::where('vendor_id', auth()->user()->id)->where('paid', 1);
//Getting the different dates of these Models.
$egp_invoices_dates = $invoices_egp->get()->map(function ($invoice) {
return Carbon::parse($invoice->created_at)->format('Y-m');
});
$usd_invoices_dates = $invoices_usd->get()->map(function ($invoice) {
return Carbon::parse($invoice->created_at)->format('Y-m');
});
$orders_dates = $orders->get()->map(function ($order) {
return Carbon::parse($order->created_at)->format('Y-m');
});
//Getting the unique dates.
$dates = $orders_dates->merge($usd_invoices_dates)->merge($egp_invoices_dates)->unique();
return view('dashboard.vendor.reports.index', compact('invoices_egp', 'invoices_usd', 'orders', 'dates'));
}
The relevant part of the blade file:
<div class="col-lg-12">
#if ( count( $dates ) )
#foreach($dates as $date)
<div class="card-box">
<div class="table-responsive">
<table class="table table-actions-bar m-b-0">
<thead>
<tr>
<th>
Month
</th>
</tr>
<tr>
<td>
{{ $date }}
</td>
</tr>
</thead>
<tbody>
<tr>
<th colspan="100%">Type</th>
<th>Total</th>
</tr>
<tr>
#if(count($invoices_egp->get()))
<td colspan="100%">Invoice in EGP</td>
<td>{{ $invoices_egp->whereYear('paid_at', \Carbon\Carbon::parse($date)->year)->whereMonth('paid_at', \Carbon\Carbon::parse($date)->month)->sum('total') }}</td>
#endif
</tr>
<tr>
#if(count($invoices_usd->get()))
<td colspan="100%">Invoice in USD</td>
<td>{{ $invoices_usd->whereYear('paid_at', \Carbon\Carbon::parse($date)->year)->whereMonth('paid_at', \Carbon\Carbon::parse($date)->month)->sum('total') * \App\ConversionRate::dollarToEGP() }}</td>
#endif
</tr>
<tr>
#if(count($orders->get()))
<td colspan="100%">Orders</td>
<td>{{ $orders->whereYear('paid_at', \Carbon\Carbon::parse($date)->year)->whereMonth('paid_at', \Carbon\Carbon::parse($date)->month)->sum('total') }}</td>
#endif
</tr>
</tbody>
</table>
</div>
</div>
#endforeach
#else
<div class="card-box">
<h3>No Data</h3>
</div>
#endif
</div>
Here when I loop over the $dates variable, for some reason, the $invoices_egp variable changes based on the date, even though it has got nothing to do with it, if I tried to dump $invoices_egp (which has two records with the same date 2019-01) on each loop, I am expecting to get the two records twice regardless of the date, instead I get the two records on the first loop ($date = 2019-03), and on the second loop ($date = 2019-01) I get an empty collection.
I have tried different stuff, I replaced the dates variable with a hard coded array and removed the other dates queries, nothing changes in the blade file.
What's even weirder is that if I changed the place of $invoices_egp with $invoices_usd, I get $invoices_egp rendered correctly, and the bug instead happens to the $invoices_usd variable, so whatever the first variable is, it gets messed up.
Small Update
I don;t know what's wrong yet, but as soon as I comment out this line
<td>{{ $invoices_egp->whereYear('paid_at', \Carbon\Carbon::parse($date)->year)->whereMonth('paid_at', \Carbon\Carbon::parse($date)->month)->sum('total') }} EGP</td>
I get the variable rendering twice correctly per each instance of the loop, which is what should happen, and this line I am commenting should not have any impact over whether the collection should be retrieved successfully or not, I hope I am making sense.
If I dump the variable over each loop, this is what I get in the first loop
Collection {#522 ▼
#items: array:2 [▼
0 => Invoice {#526 ▶}
1 => Invoice {#519 ▶}
]
}
And this is what I get in the second loop (with the aforementioned line uncommented)
Collection {#516 ▼
#items: []
}
Same variable, different results over a loop.
So apparently since I was passing a query builder instance to the view, it was actually getting changed by the foreach loop, which is something I'd never thought would happen, anyway the fix was easy at that point, just had to change the code a little, starting from here:
public function index()
{
$invoices_egp = auth()->user()->invoices()->where(['paid' => 1, 'currency' => 'EGP'])->latest()->get();
$invoices_usd = auth()->user()->invoices()->where(['paid' => 1, 'currency' => 'USD'])->latest()->get();
$orders = \App\Order::where('vendor_id', auth()->user()->id)->where('paid', 1)->latest()->get();
$egp_invoices_dates = $invoices_egp->map(function($invoice) { return Carbon::parse($invoice->paid_at)->format('Y-m'); })->unique();
$usd_invoices_dates = $invoices_usd->map(function($invoice) { return Carbon::parse($invoice->paid_at)->format('Y-m'); })->unique();
$orders_dates = $orders->map(function($order) { return Carbon::parse($order->paid_at)->format('Y-m'); })->unique();
$dates = $orders_dates->merge($usd_invoices_dates)->merge($egp_invoices_dates)->unique();
return view('dashboard.vendor.reports.index', compact('invoices_egp', 'invoices_usd', 'orders', 'dates'));
}
And in the view I just had to change the filtering queries to be like this for all 3 queries:
<td>{{ $invoices_egp->filter(function($invoice) use ($date) { return $invoice->created_at->year == \Carbon\Carbon::parse($date)->year; })->filter(function($invoice) use ($date) { return $invoice->created_at->month == \Carbon\Carbon::parse($date)->month; })->sum('total') }} EGP</td>

Laravel 5.5: Send value of hidden form input to controller

In my view, I'm getting all the available slots so a user can click the book button to book that slot. However, I just can't seem to find a way to get the correct value (id of the input) so I can set the status of the specific booking in the database to booked.
index.blade.php
#if(count($slots) > 0)
<table class="table table-striped">
<tr>
<th>Date</th>
<th>Time</th>
<th></th>
</tr>
#foreach($slots as $slot)
<tr>
<td>{{$slot->date}}</td>
<td>{{$slot->time}}</td>
<td>
<input name="id" value="{{$slot->id}}" type="hidden"> THIS IS WHAT I WANT TO SEND
<button class="btn btn-primary pull-right" type="submit">Book</button>
</td>
</tr>
#endforeach
BookingsController.php
public function store(Request $request)
{
$booking = new Booking;
$booking->user_id = auth()->user()->id;
$booking->date_id = THIS IS WHAT I NEED;
DB::table('calendar')
->select('id','status')
->where('id', GET DATE ID)
->update(['status' => 1]);
$booking->save();
return redirect('/bookings')->with([
'success' => 'Booking successful!',
]);
}
Use the request object to retrieve the parameters you send :
$whatYouNeed = $request->id (or in general $request->WhateverYouNamedYourField)
Edit : This is not related to hidden fields only, it works with any kind of form fields.
Request docs
In store function you are Typehinting Request.
store(Request $request)
The first Request is referring to the request handler.
So if you'll put this after your.
$booking->date_id = $request->input('id')
Thats your answer.
You are requesting the input id from the request input
from the docs
$request->all();
or
$request->get('filedName');
or
$request->fieldName;
or
$request->input('fieldName');
These are the ways of getting inputs including hidden ones

How to work with a lot (thousands) of Eloquent records in Laravel 4

I need to get all data records from a clients table, there is more than 18000 records.
I use DataTables jQuery plugin to display data, so I do not want to use paginate Laravel method here.
I just want to retrieve data and pass to DataTable jQuery. This plugin does pagination.
This is my Controller code:
$data = Client::orderBy('created_at', 'desc')->get();
I got 500 error, because the result is too big.
I do not want to set higher memory limit, I want to use limitations or similar.
I tried this:
$data = Client::orderBy('created_at', 'desc')->take(10)->skip(1200)->get();
But it only gets 10 records and no more.
Any idea?
you can use Laravel Datatable package which is more effective and easy to use, here is my example that How I am doing it.
Note: I am using Yajra Datatable package for this, you all basic requirement will be cover in this.
My Controller method, where datatable Ajax request will come
public function getData()
{
$users = User::whereHas('roles',function($q){
$q->whereNotIn('roles.name',['user','memberstudent','educationmanager']);
})->select(array('users.id','users.firstname','users.lastname' ,'users.username','users.email',DB::raw("'roles'"), 'users.confirmed', 'users.created_at'));
return Datatables::of($users)
//->edit_column('created_at', '{{ $created_at->format("Y-m-d h:i:s") }}')
->edit_column('created_at', '{{ date("Y-m-d", strtotime($created_at))}}')
->edit_column('confirmed','#if($confirmed)
Yes
#else
No
#endif')
->add_column('roles','{{ implode(", ", User::find($id)->roles()->lists(\'name\')) }}')
->add_column('actions', '
#if(Auth::user()->hasRole("owner"))
<div class="btn-group">
<i class="fa fa-pencil"></i> {{{ Lang::get(\'button.edit\') }}}
<i class="fa fa-trash-o"></i> {{{ Lang::get(\'button.delete\') }}}
</div>
#elseif(Auth::user()->hasRole("superadmin") && User::find($id)->roles()->pluck(\'name\') != "owner")
<div class="btn-group">
<i class="fa fa-pencil"></i> {{{ Lang::get(\'button.edit\') }}}
<i class="fa fa-trash-o"></i> {{{ Lang::get(\'button.delete\') }}}
</div>
#endif
')
->remove_column('id')
->remove_column('rn') // rownum for oracle
->remove_column('created_at') // rownum for oracle
->make();
}
My view is
<table id="users" class="table table-striped table-hover table-bordered">
<thead>
<tr>
<th class="col-md-2">first name</th>
<th class="col-md-2">last name</th>
<th class="col-md-2">username</th>
<th class="col-md-2">email</th>
<th class="col-md-2">roles</th>
<th class="col-md-2">activated</th>
<th class="col-md-2">actions</th>
</tr>
</thead>
</table>
MY JS code is
<script type="text/javascript">
var oTable;
$(document).ready(function() {
oTable = $('#users').dataTable( {
"sDom": "<'row'<'col-md-6'l><'col-md-6'f>r><'row'<'col-md-6'i><'col-md-6'p>>t<'row'<'col-md-6'i><'col-md-6'p>>",
"aoColumnDefs": [
{ "bSearchable": true, "bSortable": false, "aTargets": [ 2,5 ] }
],
"sPaginationType": "bootstrap",
"oLanguage": {
"sLengthMenu": "_MENU_ records per page"
},
"bProcessing": true,
"bServerSide": true, //this means data will come from server, ajax based
"sAjaxSource": "{{ URL::to('admin/users/data') }}", // get data from this URL
"fnDrawCallback": function ( oSettings ) {
$(".iframe").colorbox({iframe:true, width:"80%", height:"80%"});
}
});
});
</script>
You really, really need to use server-side pagination in this case.
The problem with relying on client-side pagination (i.e., the plugin's pagination feature) is that the response from your API containing all 18,000 records will be humongous, and your users will not only have to wait for the request to complete (which literally could take minutes for this much data), but depending on how the plugin works they may also have to wait while it renders the DOM for all these records.
It looks like Datatables supports server-side pagination. Why not give that a try?
I have adopted another solution, using paginate method from laravel and forget DataTables plugin, DataTables is a great plugin!, but in my case, to use this plugin, would have to implement an ajax script to get data.
Currently I have the system implemented to work with routes, controllers, views with Teepluss themes and a search tool.
I thought there was a simpler way to implement this plugin with Laravel using MVC pattern.
With this lines I have what I need:
My controller
public function index()
{
$data = Client::orderBy('created_at', 'desc')->paginate(50);
$theme = Theme::uses('mytheme');
$view = array(
'name' => 'Teepluss',
'data' => $data,
);
return $theme->scope('clients.index', $view)->render();
}
My view
//-- Table head here
#foreach($data->getCollection()->all() as $value)
//-- Table and data here
#endforeach
//-- Pagination links
{{ $data->appends(Request::except('page'))->links() }}
No 500 error, get all data, pagination working fine. Of course, I am giving up other features of DataTables plugin for the moment...
Anyway thank you very much!

Categories