查找在laravel中未来7天有生日的客户

时间:2019-06-20 04:42:10

标签: php laravel laravel-5.5 laravel-5.8

我需要获取在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();

我使用下面列出的查询,但缺少一些客户 enter image description here

缺少客户

enter image description here

9 个答案:

答案 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解决方案:

为了便于阅读并处理年度结转问题,您应该:

  1. 使用Carbon进行日期和日期计算
  2. 找到用户的下一个/即将到来的生日
  3. 请记住,Y-m-d格式通常表示时间为00:00:00。
$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();