Laravel sorting merged collections - php

I have 3 collections being merged in my controller, my problem is I want the merged collection to be sorted by expiry_date.
$expiry = date('Y-m-d', strtotime('+3 months'));
$servers = Server::where('expiry_date', '<', $expiry)->orderBy('expiry_date', 'asc')->get();
$domains = Domain::where('expiry_date', '<', $expiry)->orderBy('expiry_date', 'asc')->get();
$hosts = Host::where('expiry_date', '<', $expiry)->orderBy('expiry_date', 'asc')->get();
$invoices = $domains->merge($servers)->merge($hosts);

If orderBy() works properly inside your queries, this should work for you:
$expiry = date('Y-m-d', strtotime('+3 months'));
$servers = Server::where('expiry_date', '<', $expiry)->get();
$domains = Domain::where('expiry_date', '<', $expiry)->get();
$hosts = Host::where('expiry_date', '<', $expiry)->get();
$invoices = $domains->merge($servers)->merge($hosts);
$invoices->sortBy('expiry_date');

Solved using SQL queries, in case anyone is looking for something similar.
$servers = DB::table('servers')->select(DB::raw('"Server" as type, servers.id, servers.client_id, servers.expiry_date, servers.name, clients.name as clientName'))->leftJoin('clients', 'servers.client_id', '=', 'clients.id')->where('expiry_date', '<', $expiry);
$domains = DB::table('domains')->select(DB::raw('"Domain" as type, domains.id, domains.client_id, domains.expiry_date, domains.name, clients.name as clientName'))->leftJoin('clients', 'domains.client_id', '=', 'clients.id')->where('expiry_date', '<', $expiry);
$hosts = DB::table('hosts')->select(DB::raw('"Host" as type, hosts.id, hosts.client_id, hosts.expiry_date, hosts.name, clients.name as clientName'))->leftJoin('clients', 'hosts.client_id', '=', 'clients.id')->where('expiry_date', '<', $expiry)->unionAll($domains)->unionAll($servers)->orderBy('expiry_date', 'asc')->get();

Related

Laravel whereBetween function not working to my query

My table column data type is Date and the date format is "2022-05-25". My Query is
$customers = Customer::with(['outstanding_invoices', 'address', 'rep'])
->where('status', 'A');
$from_date = Carbon::parse($from_date)->format('Y-m-d');
$end_date = Carbon::parse($end_date)->format('Y-m-d');
$customers->whereHas('outstanding_invoices', function ($query) use ($from_date, $end_date) {
$query->whereBetween('invoice_date', [$from_date, $end_date]); //* 1
// $query->where('invoice_date', '>=', $from_date); //* 2
// $query->where('invoice_date', '<=', $end_date);
// $query->whereDate('invoice_date', '>=', $from_date); //* 3
// $query->whereDate('invoice_date', '<=', $end_date);
});
$customers = $customers->get();
I have tried below three commented options but did not filter to the dates.

Getting datetime edge cases with laraval eloquent

Im currently building a reservation system for a restaurant and i have a question regarding edge cases in the reservation. to filter out tables that are not available i try to get the reservations and filter out the tables. for example, if reservation a starts at june 17 11:00 and ends june 17 12:00
you should not be able to book that table for that time period, however you should be able to end an earlier reservation at 11:00 and start a new reservation at 12:00 for that table.
this is the code that i had in laravel that did this (sort of):
$startDate = $request->query('start_date');
$endDate = $request->query('end_date');
$people_amount = $request->query('people_amount');
$reservation_id = $request->query('reservation_id');
$tables = Table::all();
$reservations = Reservation::whereBetween('start_datetime', [$startDate, $endDate])->orWhereBetween('end_datetime', [$startDate, $endDate])->get();
this worked perfectly except it wil not account for edge cases so i did this:
$reservations = Reservation::where([['start_datime', '>', $startDate],
['start_datetime', '<', $endDate]
])->orWhere([['start_datetime', '>', $startDate],
['end_datetime', '>', $startDate]]);
somewhere i went wrong but for the life of me i cant figure it out. any help would be greatly appreciated!
(this is the entire code):
public function showTables(Request $request)
{
$startDate = $request->query('start_date');
$endDate = $request->query('end_date');
$people_amount = $request->query('people_amount');
$reservation_id = $request->query('reservation_id');
$tables = Table::all();
// $reservations = Reservation::whereBetween('start_datetime', [$startDate, $endDate])->orWhereBetween('end_datetime', [$startDate, $endDate])->get();
// dd($reservations);
$reservations = Reservation::where([['start_datetime', '<', $startDate],
['start_datetime', '>', $endDate]
])->orWhere([['start_datetime', '<', $startDate],
['end_datetime', '<', $startDate]])->get();
if (isset($reservation_id)) {
$reservations = $reservations->filter(function ($item) use ($reservation_id) {
return $item->id != $reservation_id;
});
}
// dd($reservations);
foreach ($reservations as $key => $reservation) {
foreach ($tables as $key => $table) {
if ($table->seats_amount < $people_amount) {
unset($tables[$key]);
}
if ($table->id === $reservation->table_id) {
unset($tables[$key]);
}
}
}
TableCollection::wrap('tables');
return new TableCollection($tables);
}
edit, the fix:
$reservations = Reservation::where([['start_datetime', '>', $startDate],
['start_datetime', '<', $endDate]
])->orWhere([['end_datetime', '>', $startDate],
['end_datetime', '<', $endDate]])->orWhere([['start_datetime', '<', $startDate],
['end_datetime', '>', $startDate]])->orWhere([['start_datetime', '=', $startDate],
['end_datetime', '=', $endDate]])->get();

Laravel get entries in the database in given interval of time

I want to display in the admin panel statitics about users and other things in the database.
For example to show how many users were registered today, this month etc.
For now I am doing this with the users for today the following way:
$users = User::where('admin', 0)->get();
$usersRegisteredToday = array_filter($users->toArray(), function ($user) {
$registerDate = \DateTime::createFromFormat('Y-m-d H:i:s', $user['created_at']);
$registerDate->setTime(0,0,0);
$today = new \DateTime();
$today->setTime(0,0,0);
$diff = $today->diff($registerDate);
$diffDays = (integer)$diff->format("%R%a"); // Extract days count in interval
return $diffDays == 0;
});
return view('admin.index', compact("users", "usersRegisteredToday"));
And in the view:
<p class="text-no">Today: {{ count($usersRegisteredToday) }} </p>
I wonder if there is a better, simpler and faster way to do this, because I think if I get the information for the other things that way it will be very slow and heavy. So i want to know the best and lightest way to do this.
As of Laravel 5.3 we can use whereDate / whereMonth / whereDay / whereYear
For example to get records created today:
$users = User::whereDate('created_at', DB::raw('CURDATE()'))->get();
Possibly a similar question is asked here: Get only records created today in laravel
$todayStart = (new Carbon())->setTime(0, 0);
$todayEnd = (new Carbon())->setTime(23, 59, 59);
$users = User::where('admin', 0)
->where('created_at', '>=', $todayStart)
->where('created_at', '<=', $todayEnd)
->get();
You could use query scopes which would make it even better. Inside User model:
class User extends Model
{
public function scopeCreatedBefore(Carbon $date)
{
return $this->where('created_at', '<=', $date);
}
public function scopeCreatedAfter(Carbon $date)
{
return $this->where('created_at', '>=', $date);
}
}
And for the usage:
$todayStart = (new Carbon())->setTime(0, 0);
$todayEnd = (new Carbon())->setTime(23, 59, 59);
$users = User::where('admin', 0)
->createdAfter($todayStart)
->createdBefore($todayEnd)
->get();
Its quite easy to do it. Im doing this in laravel 5.6
We are working in controller here. Lets say $date1 and $date2 is your range.
First, parse the date to carbon
$olddate = Carbon::parse($date1)->format('Y-m-d');
$newdate = Carbon::parse($date2)->format('Y-m-d');
Now, we get the users within that date range.
$users = Users::latest()
->whereBetween('created_at', array($olddate, $newdate))
->orderBy('id', 'desc')
->get(); // or count if you just want to count
basically, the function will look like below
public function betweendates(Request $request)
{
// get dates from request
$date1= $request->olddate;
$date2= $request->newdate;
// parse date to carbon
$olddate = Carbon::parse($date1)->format('Y-m-d');
$newdate = Carbon::parse($date2)->format('Y-m-d');
// the magic stuff
$users = Users::latest()
->whereBetween('created_at', array($olddate, $newdate))
->orderBy('id', 'desc')
->count();
return view('users.dashboard', compact('users'));
}

PHP laravel query

How can I query all users whose last donation is more than 90 days. This is my query but when it is executed I get an error unknown column.
$value = Session::get('key');
$dateToday = new DateTime();
$data = Users::where('userType','=', 'user' )
->where($dateToday->format('m/d/Y') - 'lastDonation', '=', 1)
->whereNotIn('username', [$value ])
->get();
$data = Users::where('userType','=', 'user' )
->where('lastDonation', '<', Carbon::now()->subDays(90))
->whereNotIn('username', [$value ])
->get();
You can use the TIMESTAMPDIFF mysql function to compute the difference between two datetimes.
To do that you need to add a clause using whereRaw
$value = Session::get('key');
$dateToday = new DateTime();
$data = Users::where('userType', '=', 'user')
->whereRaw('TIMESTAMPDIFF(DAY, lastDonation, NOW()) > 90')
->whereNotIn('username', [$value])
->get();

Adding arrays within loop Laravel

Please need help...
$months = Records::select('payment_month')
->distinct()->where('payment_year',$year)
->where('company_id',$company_id)->get();
foreach ($months as $month) {
$data = Records::select(
DB::raw('SUM(record_db.credits) as credits'),
DB::raw('SUM(record_db.amount) as amount'),
DB::raw('SUM(record_db.totalamount) as totalamt'), 'record_db.payment_month')
->where('record_db.company_id','=',$company_id)
->where('record_db.payment_month','=',$month->payment_month)
->where('record_db.payment_year','=',$year)
->first();
}
return Response::json($data);
The above query works fine and I have the month of January, February and March in the database table but it only returns the records of March.
I tried results[]=$data but still don't work.
I think this is what you need:
$data = Records::select(
'payment_month',
DB::raw('SUM(record_db.credits) as credits'),
DB::raw('SUM(record_db.amount) as amount'),
DB::raw('SUM(record_db.totalamount) as totalamt')
)->where('company_id', '=', $company_id)
->where('payment_year', '=', $year)
->groupBy('payment_month')
->orderBy('payment_month')
->get();
// then
$data->toJson(); // returns something like:
[{"payment_month":"January","credits":"123","amount":"456","totalamt":"789"}, ... ]
You had override $data array from every month result. You should use whereIn as follows.
$months = Records::select('payment_month')
->distinct()->where('payment_year', $year)
->where('company_id',$company_id)->get();
$monthValues = array();
foreach ($months as $month) {
$monthValues[] = $month->payment_month;
}
$data = Records::select(
DB::raw('SUM(record_db.credits) as credits'),
DB::raw('SUM(record_db.amount) as amount'),
DB::raw('SUM(record_db.totalamount) as totalamt'), 'record_db.payment_month')
->where('record_db.company_id','=',$company_id)
->whereIn('record_db.payment_month', $monthValues)
->where('record_db.payment_year','=',$year)
->first();

Categories