I am trying to build a Artisan Cron Job in the Laravel 4 that gets all our subscribers that should pay using the Eloquent ORM. I am trying to accomplish that I get all users with a subscription who paid for the last time at least one month ago, or new subscriptions who never paid at all.
Yet I only get the info from the user table (user 1 and 3), the values of the payment table are 'null'. Which means they are not with in range, however I only want 'null' values if they don't have any values in table payments.
my code:
$Payments = user::leftJoin('payments', function ($query) {
$query->on ('payments.user_id', '=', 'user.id')
->where ('payments.paid_on', '<=',
date('Y-m-d H:i:s',mktime(0, 0, 0, date("m")-1, date("d"), date("Y"))))
->where ('payments.paid_on', '>=',
date('Y-m-d H:i:s',mktime(0, 0, 0, date("m")-1, date("d")-10, date("Y"))));
})
->where('user.start', '<', date('Y-m-d H:i:s',time()) )
->where('user.end', '>', date('Y-m-d H:i:s',time()) )
->get(['user.*','payments.paid_on']);
This is example data:
(user)
id start end
| 1 | 2014-02-24 00:00:00 | 2015-02-24 00:00:00 |
| 2 | 2012-03-24 00:00:00 | 2013-01-24 00:00:00 |
| 3 | 2014-03-24 00:00:00 | 2015-03-24 00:00:00 |
(payments)
user_id paid_on
| 1 | 2014-02-24 00:00:00 |
| 1 | 2014-03-24 00:00:00 |
| 2 | 2013-01-24 00:00:00 |
I hope it would out put something like:
| 1 | 2014-02-24 00:00:00 | 2015-02-24 00:00:00 | 1 | 2014-03-24 00:00:00 |
| 3 | 2014-03-24 00:00:00 | 2015-03-24 00:00:00 |
don't know if I came to the right conclusion but this is what I ended up with. Check if a value existed in the right table in the where clause and if it didn't I checked if there was one for NULL. Here is the code:
$Payments = user::leftJoin('payments', 'user.id', '=', 'payments.user_id')
->where('user.start', '<', date('Y-m-d H:i:s',time()) )
->where('user.end', '>', date('Y-m-d H:i:s',time()) )
->where (function($query)
{
$query->where ('payments.paid_on', '<=',
date('Y-m-d H:i:s',mktime(0, 0, 0, date("m")-1, date("d"), date("Y"))))
->where ('payments.paid_on', '>=',
date('Y-m-d H:i:s',mktime(0, 0, 0, date("m")-1, date("d")-5, date("Y"))))
->orWhere(function($orQuery)
{
$orQuery->whereNull ('payments.paid');
});
}
->get(['user.*','payments.paid_on']);
Related
I have data like this:
id | employee_id | absent_type | do_date_start | do_date_end
1 | EMPLOYEE-1 | Absent | 2022-02-14 00:00:00 | 2022-02-18 00:00:00
What I want to do is to get data between field do_date_start and do_date_end.
Case example using data above:
Start Date | End date | Expected Result
2022-02-14 | 2022-02-18 | Data Found
2022-02-13 | 2022-02-19 | Data Found
2022-02-15 | 2022-02-17 | Data Found
2022-02-13 | 2022-02-17 | Data Found
2022-02-19 | 2022-02-20 | Data Not Found
2022-02-12 | 2022-02-13 | Data Not Found
So as long as the date between do_date_start and do_date_end is between filter start date and end date it still getting the data, if not it won't getting the data.
I've tried like this:
DB::table('attendance_absent as absent')
->where(function($query) use ($start_date, $end_date){
$query->where('absent.do_date_start', '<=', $start_date)
->where('absent.do_date_end', '>=', $end_date)
->orWhere(function ($q) use($start_date, $end_date) {
$q->where('absent.do_date_start', '>=', $start_date)
->where('absent.do_date_end', '<=', $end_date)
->orWhere(function ($k) use ($start_date, $end_date) {
$k->where('absent.do_date_start', '>=', $start_date)
->where('absent.do_date_end', '>=', $end_date)
->orWhere(function ($l) use ($start_date, $end_date) {
$l->where('absent.do_date_start', '<=', $start_date)
->where('absent.do_date_end', '<=', $end_date);
});
});
});
})
->get();
When I tested my code using case example above, the result is like this:
Start Date | End date | Expected Result | Correct?
2022-02-14 | 2022-02-18 | Data Found | Yes
2022-02-13 | 2022-02-19 | Data Found | Yes
2022-02-15 | 2022-02-17 | Data Found | Yes
2022-02-13 | 2022-02-17 | Data Found | Yes
2022-02-19 | 2022-02-20 | Data Not Found | No
2022-02-12 | 2022-02-13 | Data Not Found | No
Somehow I still getting the data even though the data is outside date range, I don't know what's wrong with my code. Any help would be very helpful for me, thanks
I came up with a code in Eloquent that I think works with your situation. Not sure how you can do this with DB facade. But here's the code:
$period = ['2022-02-15','2022-02-16'];
return Test::
where(function($q) use ($period) {
return $q->where('do_date_start', '>=', $period[0])->where('do_date_start','<=',$period[1]);
})
->orWhere(function($q) use ($period) {
return $q->where('do_date_end', '>=', $period[0])->where('do_date_end','<=',$period[1]);
})
->orWhere(function($q) use ($period) {
return $q->where('do_date_start', '<=', $period[0])->where('do_date_end','>=',$period[1]);
})
->get();
If it worked for you please inform me so that I can provide more info on how I came up with this.
I am trying to make a Laravel Eloquent query which will find me orders by order number and product name.
I have 3 tables orders, order_details & products.
orders table
id | user_id | order_id | order_cart_id
---------------------------------------------------------
1 | 1 | 123-456-7890 | 1
2 | 1 | 789-456-3210 | 2
order_details table
id | order_id | cart_id | p_id
---------------------------------------------------------
1 | 1 | 1 | 22
2 | 1 | 1 | 42
3 | 1 | 1 | 2
4 | 1 | 1 | 32
5 | 1 | 1 | 423
6 | 2 | 2 | 432
products table
id | p_name
--------------------
1 | ABC
2 | CAD
42 | PRO
22 | XYZ
32 | IND
423 | MP
432 | ETC
Orders Model
public function order_cart_products()
{
return $this->hasManyThrough(\App\Models\Products\Product::class,
\App\Models\Orders\OrderDetail::class,
'cart_id',
'id',
'cart_id','p_id');
}
Order Controller
$orders = Order::where('user_id', auth()->user()->id)
->where('order_id', 'LIKE', '%'.$search.'%')
->with('order_cart_products', function ($query) use ($search) {
$query->orWhere('p_name', 'LIKE', '%'.$search.'%');
})
->get()->toArray();
What I am trying to do is by searching order_id(123-456-7890) I need to get all its details with products in it and if I search via p_name(ABC). I need to get all orders in which ABC has been listed. But I don't understand where am I going wrong am not getting desired output.
Try something like below:
$orders = Order::with('order_cart_products')
->where('user_id',auth()->user()->id)
->where(function ($query) use ($search) {
$query->where('order_id', 'LIKE', '%'.$search.'%')
->orWhereHas('order_cart_products', function ($query) use ($search) {
$query->where('p_name', 'LIKE', '%'.$search.'%')
})
})
->get();
If the selected dates ($postFr, $postTo) are within defined periods, I want to list the related products. So can I do something like the following example?
example:
$q->whereBetween('start_date', array($postFr, $postTo));
$q->orWhereBetween('end_date', array($postFr, $postTo));
//Could there be a similar use like this???;
$q->whereBetween(array(start_date, end_date), $postFr);
$q->orWhereBetween(array(start_date, end_date), $postTo);
Detailed explanation:
I have a periods table like this
periods
| id | start_date | end_date | product_id |
|------|--------------|------------|------------|
| 1 | 2021-02-19 | 2021-03-21 | 1 |
| 2 | 2021-02-19 | 2021-03-21 | 2 |
| 3 | 2021-02-19 | 2021-03-21 | 3 |
| 4 | 2021-02-19 | 2021-03-21 | 2 |
and I have a products table like this
products
| id | name |
|-------|-----------|
| 1 | pro1 |
| 2 | pro2 |
| 3 | pro3 |
The relevant codes on my model page are as follows
public $belongsTo = [
'relationPeriod' => [
'Model->periods table',
'key' => 'id',
'otherKey' => 'product_id',
]
]
$query->whereHas('relationPeriod', function($q) use ($postFr, $postTo){
$q->whereBetween('start_date', array($postFr, $postTo]));
$q->orWhereBetween('end_date', array($postFr, $postTo));
});
it works
$q->whereDate('start_date', '<=', $postFr);
$q->whereDate('end_date', '>=', $postFr);
$q->orWhereDate('start_date', '<=', $postTo);
$q->whereDate('end_date', '>=', $postTo);
This will work:
$start_date = '2021-01-01';
$end_date = '2021-02-01';
$filter = Atom_juice_data_history::whereBetween('created_at',[$start_date, $end_date])
->where('atom_juice_data_id',$product_id)
->orderBy('created_at', 'ASC')
->get();
This is reference url
https://medium.com/#sectheater/how-to-use-laravel-wherebetween-method-elegantly-20a50f3b0a2a
I have two related tables:
projects:
| id | name |
| 1 | Test |
| 2 | Example |
project_dates:
| id | project_id | date |
| 1 | 1 | 2020-02-01 |
| 2 | 1 | 2020-02-10 |
| 3 | 1 | 2020-01-25 |
| 4 | 2 | 2020-01-10 |
| 5 | 2 | 2019-12-15 |
Now for example I would like to get all projects where the first date of project_dates is equal to 2020-01-25. So I tried the following:
$projects = Project::whereHas('dates', function($query) {
$query->whereRaw("MIN(date) = '2020-01-25'");
});
But this returns the following error:
SQLSTATE[HY000]: General error: 1111 Invalid use of group function
which revers to MIN(date). So my question remains how can I get all projects with the first date being equal to 2020-01-25 or any other specific date. From the example above I would expect to get the project with id 1 since the first date of 2 is 2019-12-15
I know that is possible to use a subqueryjoin however I feel like doing 2 queries shouldn't be required.
$firstDates = ProjectDate::groupBy('project_id')
->selectRaw('project_id, MIN(date) as first_date');
Project::joinSub($firstDates, 'first_dates', function($join){
$join->on('first_dates.project_id', '=', 'project.id')
->where('first_date', '=','2020-01-25');
})->get();
You cannot use where aggregate function with groupBy, try to use havingRaw instead:
$projects = Project::whereHas('dates', function($query) {
$query->havingRaw("MIN(date) = ?", ['2020-01-25']);
});
// Or
$projects = Project::whereHas('dates', function($query) {
$query->having(DB::raw("MIN(date)"), '2020-01-25');
});
$projects = Project::whereHas('dates', function($query) {
$query->having(DB::raw("MIN(date)"), '2020-01-25')
->groupBy( 'project_dates.id' ); // For sql_mode=only_full_group_by
});
I have a method that get a month parameter to select rows of that month from users table. I want to show count of registered user for a month.
public function registeredUsersDaily($month)
{
$countOfDailyRegisteredUsersForAMonth = User::user()
->where(DB::raw('created_at'), '=', $month)
->groupBy('date')
->orderBy('date')
->get([
DB::raw('DATE(created_at) as date'),
DB::raw('COUNT(*) as count')
]);
dd($countOfDailyRegisteredUsersForAMonth);
}
It return count only for dates that exists in users table, so i want to have zero for dates that don't exists.
|date|count|
| 5 | 10 |
| 15 | 3 |
I want to have a result like this:
|date |count |
| 1 | 0 |
| 2 | 0 |
| 3 | 0 |
| 4 | 0 |
| 5 | 10 |
| 6 | 0 |
| 7 | 0 |
| 8 | 0 |
| 9 | 0 |
| 10 | 0 |
| 11 | 0 |
| 12 | 0 |
| 13 | 0 |
| 14 | 0 |
| 15 | 3 |
....
Please check out like this
$dateValues = array_column($countOfDailyRegisteredUsersForAMonth, "date");
$maxDate = max($dateValues);
$likeYouWant=[];
for ($i = 1; $i <= $maxDate; $i++)
{
$likeYouWant[] = ["date" => $i, "count" => in_array($i, $dateValues) ? $countOfDailyRegisteredUsersForAMonth[array_search($i, $dateValues)]["count"] : 0];
}
print_r($likeYouWant);
If you want default date than you can mention in that migration file or you can also do that in your model from where you can retrieve data when there is no date given by user.
You can also refer this for more
How to pass default values to controller by routing in Laravel 5?
From what I've got from the comments:
I think the best thing here is to count the number of users created each day of the month. This will get you zero's in case no one registered on a given date.
With this, you'd probably loop through the dates checking the total users registered each date.
For instance, let's try to get the users created the last 30 days from now:
$results = [];
$startOfDay = now()->createMidnightDate();
for($i=0; $i<=30; $i++)
{
$total_count = User::whereBetween('created_at', [$startOfDay->subDays($i-1), $startOfDay->subDays($i)])
->count();
array_push($results[ $startOfDay->subDays($i)->format('d')], $total_count);
}
With this I think you can now work with the results from the array.