Laravel - Get data based on date range using eloquent - laravel

Heei, I want to show data according to daterange. Specifically data on this day and 6 days to go. Here's my code now.
Controller
$hari = [];
for ($i=0; $i < 6; $i++)
{
$hari[] = date("Y M d") + $i;
}
$booking_room = jadwal_meeting::whereBetween('tanggal', [$hari, $hari + 6])->get();
return view('homepage')->with($booking_room);
Note: 'tanggal' is a field on table.
But I just get error like this
Unsupported operand types
: $booking_room = jadwal_meeting::whereBetween('tanggal', [$hari, $hari + 6])->get();
What's wrong with my code, anyone can help me please :)

Since $hari is an array, you have to use something like this:
$booking_room = jadwal_meeting::whereBetween('tanggal', [$hari[0], $hari[5]])->get();
Or more general:
$booking_room = jadwal_meeting::whereBetween('tanggal', [$hari[0], end($hari)])->get();

Try this code it will help you.
$from = '2018-04-12';
$to = date('Y-m-d', strtotime($from. ' + 6 days'));
$reservations = Reservation::whereBetween('tanggal', [$from, $to])
->get();
Thanks,

Related

How to get missing dates between 7 latest rows from database?

I want to get 7 latest rows (in order from down to up), for the current week (Sunday to Saturday), for the current logged in user.
To do this, I used this one method:
Carbon::setWeekStartsAt(Carbon::SUNDAY);
Carbon::setWeekEndsAt(Carbon::SATURDAY);
$strikes = UserStrike::where('user_id', $user)->whereBetween('created_at', [Carbon::now()->startOfWeek(), Carbon::now()->endOfWeek()])->latest()->take(7)->get();
$strikes = $strikes->reverse(); //to order the list from DESC to ASC
But the problem with this method is that it doesn't get any missing days.
So if there are data like this for the current week (2020-05-12 is missing):
created_at: 2020-05-10
created_at: 2020-05-11
created_at: 2020-05-13
Then for that one day which is missing, there should be a null in array. Something like this:
$days = ["Sun", "Mon", null, "Wed"];
I'm having hard time to find a way to replace missing day with a null in array.
If anyone here can help me with this problem please leave your comment. Thank you in advance.
You can take data from DB and then create array by iterating on DateTimeInterval(). I don't know Laravel and Carbon well but it could be something like this:
Carbon::setWeekStartsAt(Carbon::SUNDAY);
Carbon::setWeekEndsAt(Carbon::SATURDAY);
$start = Carbon::now()->startOfWeek();
$end = Carbon::now()->endOfWeek();
$strikes = UserStrike::where('user_id', $user)
->whereBetween(
'created_at',
[$start, $end]
)
->latest()
->take(7)
->get();
$strikes = $strikes->reverse();
$timePeriod = new DatePeriod(
$start,
new DateInterval('P1D'),
$end
);
$days = [];
for ($i = 0; $i < count($timePeriod) $i++) {
$days[$i] = null;
foreach ($strikes as $strike) {
if ($strike->created_at->format('Y-m-d') == $timePeriod[$i]->format('Y-m-d') {
$days[$i] = $strike->created_at->format('Y-m-d');
break;
}
}
}

Getting non overlapping between two dates with Carbon

UseCase: Admin assigns tasks to People. Before we assign them we can see their tasks in a gantt chart. According to the task assign date and deadline, conflict days (overlap days) are generated between tasks.
I wrote this function to get overlapping dates between two dates. But now I need to get non overlapping days between two dates, below is the function I wrote.
$tasks = Assign_review_tasks::where('assigned_to', $employee)
->where('is_active', \Constants::$REVIEW_ACTIVE)
->whereNotNull('permit_id')->get();
$obj['task'] = count($tasks);
// count($tasks));
if (count($tasks) > 0) {
if (count($tasks) > 1) {
$start_one = $tasks[count($tasks) - 1]->start_date;
$end_one = $tasks[count($tasks) - 1]->end_date;
$end_two = $tasks[count($tasks) - 2]->end_date;
$start_two = $tasks[count($tasks) - 2]->start_date;
if ($start_one <= $end_two && $end_one >= $start_two) { //If the dates overlap
$obj['day'] = Carbon::parse(min($end_one, $end_two))->diff(Carbon::parse(max($start_two, $start_one)))->days + 1; //return how many days overlap
} else {
$obj['day'] = 0;
}
// $arr[] = $obj;
} else {
$obj['day'] = 0;
}
} else {
$obj['day'] = 0;
}
$arr[] = $obj;
start_date and end_date are taken from database,
I tried modifying it to,
(Carbon::parse((min($end_one, $end_two))->add(Carbon::parse(max($start_two, $start_one))))->days)->diff(Carbon::parse(min($end_one, $end_two))->diff(Carbon::parse(max($start_two, $start_one)))->days + 1);
But it didn't work, in simple terms this is what I want,
Non conflicting days = (end1-start1 + end2-start2)- Current overlapping days
I'm having trouble translate this expression . Could you help me? Thanks in advance
before trying to reimplement complex stuff I recommend you take a look at enhanced-period for Carbon
composer require cmixin/enhanced-period
CarbonPeriod::diff macro method is what I think you're looking for:
use Carbon\CarbonPeriod;
use Cmixin\EnhancedPeriod;
CarbonPeriod::mixin(EnhancedPeriod::class);
$a = CarbonPeriod::create('2018-01-01', '2018-01-31');
$b = CarbonPeriod::create('2018-02-10', '2018-02-20');
$c = CarbonPeriod::create('2018-02-11', '2018-03-31');
$current = CarbonPeriod::create('2018-01-20', '2018-03-15');
foreach ($current->diff($a, $b, $c) as $period) {
foreach ($period as $day) {
echo $day . "\n";
}
}
This will output all the days that are in $current but not in any of the other periods. (E.g. non-conflicting days)

Lumen: Auto increment and Reset Transaction_ID Automatically every month

I trying to generate random transaction_id, with format "2000-yymmm-0000".
I already know how to set the transaction_id, but I have a problem with the auto-increment from "2000-yymm-0000" to "2000-yymm-0001", and reseting automatically to "2000-yymm-0000" at every new month.
I put this logic in different path of controller.
PS: I'm using Lumen 6.0 with Laravel 6.0.
I'm trying to create the increment with:
$number = sprintf('%04d', 0000);
$number++;
but it didn't work.
$year = 2000;
$time = date('ym');
$number = sprintf('%04d', 0000);
$transaction_id = $year . '-' . $time . '-' . $number;
$transaction_data = explode('-', $transaction_id);
$month = date("m", strtotime($transaction_data[0]));
I expect the result to automatically increment every time a new data is stored to the database. But the actual result is transaction_id being having always the same value 2000-yymm-0000.
What am I doing wrong?
I know it's weird to answer my own question, but i already find the solution.
in Models/Order.php
i create a function like this.
public function count()
{
$this->where(transaction_id)->count();
}
after that i call the function from Model/Order.php to OrdersController.php
public function create(Request $request)
{
$year = 2000;
$date = date('ym');
$total_data = $this->table->count();
$number = str_pad($total_data + 1, 4, 0, STR_PAD_LEFT);
$transaction_id = $year . '-' . $date . '-' . $number;
return $this->success('count all transaction id', $t_id);
}

-loop, is there easier way to do with carbon?

I'm using Laravel 5.7 and carbon 1.x.
I need to build dateLooper which interval is 5 days and follows calender dates.
I need to find the way build looper which add 5 days for startdate.
ex.
$startDate = "2014-01-01";
$interval = "5";
so $endDate = $startDate + 5 ;
so endDates 2014-01-05
2014-01-10
till 2014-01-30, so this is tricky because need to follow calender.
Next 2014-02-04.
I was reading Carbon but did not find any examples
which could have open solution for my problem.
And I realized that L5.7 is still using 1.x carbon.
I have tried to build double for-loop, but did not work
as it stops after reach end of inside loop.
$month ="13" ; // +1;
$day ="29" ; // +1;
for ($i = 1; $i < $month; $i++)
{
echo "Month: ".$i.'<br/>';
for ($i = 1; $i < $day; $i++)
{
echo "Day: ".$i.'<br/>';
}
}
1) So is there way to do with Carbon?
or is there some other library which I could use? Ideas..
Thanks MikroMike.
I found it from How to add CarbonInterval instance in Carbon instance
$carbon = Carbon::now();
$monthLater = clone $carbon;
$monthLater->addDay(15);
dd($carbon, $monthLater);
This has resolved my issue.

How to fetch users who does not have reports for 6 consecutive months using laravel?

I'm developing a report system, and I want to fetch users who did not report for six (6) consecutive months. How do I achieve this?
I've tried the code below but I'm not getting the desired output. There is also a problem. Let's say the date interval is 12 months. How can I determine if there is no report for 6 consecutive months?
$dateStart = '2018-10-31';
$dateEnd = '2019-03-31';
$intervals = Carbon::parse($dateStart)->diffInMonths($dateEnd);
$users = $users->whereDoesntHave('reports', function($query) use($intervals) {
for ($i = 5; $i >= 0; $i--) {
$firstMonth = Carbon::parse($dateEnd)->subMonthsNoOverflow($intervals);
$query->where('date', '>=', $firstMonth->format('Y-m-d'))->where('date', '<=', $dateEnd);
}
});
What I will do is that I will create a loop per month based on the start and end date, then check if he did not have a report for that month. If it doesn't have a report for that month, I will increment a counter, and if that counter reaches 6 counts, exit the loop and the condition was satisfied.
Below is the basic idea:
$dateStart = '2018-10-31';
$dateEnd = '2019-10-31';
$count = 0;
$no_report_for_6_consecutive_months = 0 ;
startloop
$have_report = Model::whereMonth('date_column', $date_of_loop->format('m'))->get();
if($have_report->count()){
$count = 0;
}
else{
$count++;
}
if($count==6){
$no_report_for_6_consecutive_months = 1 ;
break;
}
endloop
You have to find distinct users who report for six (6) consecutive and get difference with all users.
$enddate = 2019-04-15;
$startdate = date("Y-m-d", strtotime("-6 months", strtotime($enddate)));
$users = User::all();
$usersIdArray = $users->pluck("id")->all();
$reportedBy = Report::where('date', '>=', $startdate)
->where('date', '<=', $enddate)
->distinct("user_id")->get();
$reportedByIdArray = $reportedBy ->pluck("id")->all();
$notReportedByIdArray = array_values(array_diff($usersIdArray , $reportedByIdArray));
$notREportedUsers = User::whereIn(id", $notReportedByIdArray)->get();
//its a way but not tested
I have modified the query from this answer
I believe the query can be wrote cleaner. I will let you do this if you want to.
App\User::select('*')
->from(\DB::raw("(select
low.*,
low.`date` as date_start,
high.`date` as date_end,
to_days(high.`date`) - to_days(low.`date`) as day_gap,
period_diff(date_format(high.`date`, '%Y%m'),
date_format(low.`date`, '%Y%m')) as month_gap
from reports low, reports high
where high.`date` =
(select
min(`date`)
from reports
where
`date` > low.`date`
and low.user_id = high.user_id
)
) as d")
)->get();
Now you will get all the users with 4 extra fields: date_start; date_end, day_gap and month_gap
If you want the users with a month gap of 6 months you can do this:
App\User::select('*')
->from(\DB::raw("..."))
->where('month_gap', '>=', 6)
->get();

Resources