我需要获取在laravel中未来7天有生日的客户列表。我使用以下查询。该查询显示还可以过生日。
$customerslist=Customers::WhereRaw('DAYOFYEAR(curdate()) <= DAYOFYEAR(date_of_birth) AND DAYOFYEAR(curdate()) + 7 >= dayofyear(date_of_birth)' )->OrderBy(DB::raw("DAYOFYEAR(date_of_birth)"),'ASC')->get();
缺少客户
答案 0 :(得分:2)
对于即时解决方案,我已经创建了原始查询
// start range 7 days ago
$start = date('z') + 1 - 7;
// end range 7 days from now
$end = date('z') + 1 + 7;
$customerslist = Customers::whereRaw("DAYOFYEAR(birthday) BETWEEN $start AND $end")->get();
已编辑
所以我用随机的年份和日期创建了 5000 记录
MethodOne使用口才
filter
$checkRange = array_map(
function ($date) {
return $date->format('Y-m-d');
},
\Carbon\CarbonPeriod::create(now(), now()->addDays(7))->toArray()
);
$carbonWay = Customer::get()->filter(function($eachCus) use ( $checkRange){
return in_array( $eachCus->dob, $checkRange);
});
但是如果您有许多客户,它将使sql服务器变热
第二种QueryBuilder方法
$eloquentway = Customer::whereDate('dob','>=', now())
->whereDate( 'dob', '<=', now()->addDays(7))
->get();
所以对我来说,这两个结果都是相同的
最后我已经检查了id是否是数学符号
$idsofCarbon = $carbonWay->pluck('id')->toArray();
$idsofFilter = $elequentway->pluck('id')->toArray();
dump(array_diff( $idsofFilter, $idsofCarbon));
dump(array_diff( $idsofCarbon, $idsofFilter));
两者都给了我[]
,这意味着结果是准确的
有关日期过滤的更多信息
https://laraveldaily.com/eloquent-date-filtering-wheredate-and-other-methods/ https://laravel.com/docs/5.8/queries#where-clauses
如有任何问题,请发表评论
希望有帮助
答案 1 :(得分:2)
我发现使用 DAYOFYEAR 方法的原始查询非常优雅,因为它消除了不同出生年份的所有问题。然而,它不会很好地处理闰年。
我发现 BETWEEN 和 DATE_FORMAT 的组合产生了正确的结果。 它确实需要检查来处理多年来的边缘。
以下是如何在模型的范围内实现此功能的示例:
public function scopeBirthDayBetween ($query, Carbon $from, Carbon $till)
{
$fromMonthDay = $from->format('m-d');
$tillMonthDay = $till->format('m-d');
if ($fromMonthDay <= $tillMonthDay) {
//normal search within the one year
$query->whereRaw("DATE_FORMAT(birthdate, '%m-%d') BETWEEN '{$fromMonthDay}' AND '{$tillMonthDay}'");
} else {
//we are overlapping a year, search at end and beginning of year
$query->where(function ($query) use ($fromMonthDay, $tillMonthDay) {
$query->whereRaw("DATE_FORMAT(birthdate, '%m-%d') BETWEEN '{$fromMonthDay}' AND '12-31'")
->orWhereRaw("DATE_FORMAT(birthdate, '%m-%d') BETWEEN '01-01' AND '{$tillMonthDay}'");
});
}
}
用法:
$users = User::birthDayBetween(Carbon::now(), Carbon::now()->addWeek())->get()
要在出生日而不是出生日期添加排序,更多原始查询和 DATE_FORMAT 可以提供帮助。
$users = User::query()
->birthDayBetween($from, $till)
->orderByRaw("DATE_FORMAT(birth_date,'%m%d')")
->orderByRaw("DATE_FORMAT(birth_date,'%y') desc")
->orderBy('first_name')
->get();
注意:查看年份边缘时,订购将关闭,因为将首先订购明年年初生日的用户。 我选择在前端解决。
答案 2 :(得分:1)
您可以尝试阅读laravel ORM文章。
使用whereBetween选择日期,并且使用Carbon日期更易于阅读。
return $this->model
->whereBetween('dateOfBirth_Column', [Carbon::today()->toDate(), Carbon::today()->addDays(7)->toDate()])
->orderBy('dateOfBirth_Column')
->get();
希望这会有所帮助。
答案 3 :(得分:1)
正如@TimLewis在注释中指出的那样,您的模型有一个date-of-birth
字段,并且您正在将其与当前日期(可能是出生日期的很多年)进行比较。
php解决方案:
为了便于阅读并处理年度结转问题,您应该:
$now = Carbon::now();
$customers = Customer::all();
// find next birthday for each customer
foreach ($customers as $customer) {
$curyear_bd = Carbon::createFromFormat('Y-m-d', $customer->date_of_birth)->setYear($now->year);
$now > $curyear_bd->endOfDay() ? $next_bd = $curyear_bd->addYear(1) : $next_bd = $curyear_bd;
if ($now <= $next_bd->startOfDay() && $next_bd <= Carbon::now()->addDay(7)->endOfDay())
{
print "customer $customer->name has birthday coming up\n";
}
}
MySQL解决方案
您可以这样使用SQL查询:
select * from customers where
if (
CURDATE() >= date_add(date_of_birth, interval TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) year),
date_add(date_of_birth, interval (TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE())+1) year),
date_add(date_of_birth, interval TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) year)
)
between
curdate()
and
date_add(curdate(), interval 7 day);
但我会注意时区(服务器,客户端等)。这可能会引起它自己的SO问题...
我从Get difference in years between two dates in MySQL as an integer找到了TIMESTAMPDIFF
答案 4 :(得分:0)
我添加了原始查询,请检查其是否正常运行,并告诉我
$customerslist=Customers::WhereRaw(' date_of_birth >= DATEADD(day,-7, GETDATE())' )->get();
希望有帮助
答案 5 :(得分:0)
一个可能的解决方案是
$ customerslist =客户:: whereRaw(“出生日期之间的日期()和DATE_ADD(NOW()之间,间隔7天”)-> get()
答案 6 :(得分:0)
使用碳日期
$ customerslist = Customers :: whereDate('date_of_birth','<=',Carbon :: today()-> addDays(7))-> get();
答案 7 :(得分:0)
我的解决方案:
在您的用户模型上
use Carbon\CarbonPeriod;
public function scopeBirthdayBetween($query, $dateBegin, $dateEnd)
{
$monthBegin = explode('-', $dateBegin)[0];
$dayBegin = explode('-', $dateBegin)[1];
$monthEnd = explode('-', $dateEnd)[0];
$dayEnd = explode('-', $dateEnd)[1];
$currentYear = date('Y');
$period = CarbonPeriod::create("$currentYear-$monthBegin-$dayBegin", "$currentYear-$monthEnd-$dayEnd");
foreach ($period as $key => $date) {
$queryFn = function($query) use ($date) {
$query->whereMonth("birthday", '=', $date->format('m'))->whereDay("birthday", '=', $date->format('d'));
};
if($key === 0) {
$queryFn($query);
} else {
$query->orWhere(function($q) use ($queryFn) {
$queryFn($q);
});
}
}
return $query;
}
用法:
User::birthdayBetween('01-30', '02-15')->get()
答案 8 :(得分:0)
我遇到了这个挑战并以这种方式解决了它:
$next_days = now()->addDays(7);
$customers = Customers::query()->whereMonth('date_of_birth', $next_days->month)->whereDay('date_of_birth',$next_days->day)->get();