我如何在 eloquent 查询中使用连接变量并使用 Carbon 对其进行操作以获得我需要的结果
How can I use a joined variable in an eloquent query and manipulate it with Carbon to get the results I need
Laravel "^9.0"
我有点卡住了,因为我尝试构建的查询结果将解决一个更大的问题。情况是这样的:我有一个系统可以存储一天中的时间以向用户发送提醒。时间不与其他任何东西一起存储,而是与它们的时区相关联地存储。因此,如果用户在 America/Los_Angeles 时区,并且 select 每天下午 1 点提醒,他们应该在下午 1 点收到提醒。服务器和应用程序都在 UTC。因为我没有存储时间戳(我不需要日期,只需要一天中的时间,我发现在没有重要查询的情况下几乎不可能构建提醒逻辑(首先获取所有提醒,解析给用户,获取时区,然后按时间排序 selected)。我想通过简单的 JOIN 在使用用户时区的同时查询时间,但是,我似乎无法弄清楚如何使用 users.timezone 从 JOIN 开始工作。
提醒作业每 5 分钟运行一次,用户只能以 5 分钟为间隔 select 个提醒(例如 5:45 pm(存储为 17:45 pm))。 下面是看似简单的eloquent查询:
$reminders = Reminder::join('users as users', 'users.id', '=', 'reminders.user_id')
->where('reminders.time', '>=', Carbon::now()->subMinutes(2)->setTimezone('users.timezone')->format('G:i:s'))
->where('reminders.time', '<=', Carbon::now()->addMinutes(2)->setTimezone('users.timezone')->format('G:i:s'))
->get();
这里是错误:
Carbon\Exceptions\InvalidTimeZoneException
Unknown or bad timezone (users.timezone)
at vendor/nesbot/carbon/src/Carbon/CarbonTimeZone.php:106
102▕ }
103▕
104▕ if ($tz === false) {
105▕ if (Carbon::isStrictModeEnabled()) {
➜ 106▕ throw new InvalidTimeZoneException('Unknown or bad timezone ('.($objectDump ?: $object).')');
107▕ }
108▕
109▕ return false;
110▕ }
+2 vendor frames
3 app/Console/Commands/SendReminders.php:48
Carbon\Carbon::setTimezone("users.timezone")
+13 vendor frames
17 artisan:37
Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
如有任何帮助,我们将不胜感激。谢谢。
所以,事实证明我试图做的事情是不可能的(甚至 Taylor Otwell 在 Twitter 上发帖 - https://twitter.com/taylorotwell/status/1500100606274551816?s=21)。所以,我想我会折回并展示我最终做了什么:
首先,当我存储提醒时,我将其与当前用户时区和 UTC 一起存储,因此我有正确的时间用于其中任何一个。这里复杂的部分只是为了获得正确的偏移量,因为我没有存储完整的日期,只存储了小时和分钟。
然后在发送提醒的作业中,我有这个查询(替换上面的问题查询):
$results = Reminder::with('user')
->where('timeTz', Carbon::now()->format('H:i'))
->get();
我正在使用 Carbon::now(),因为我的应用程序以 UTC 运行,这就是 timeTz 的存储方式。我也是不看秒,只看时分。
那么,如果不是数千个查询(N+1,上面问题之前的原始问题),那么现在是一个。
我非常感谢 Twitter 上的 PHP 社区 - 一些重要的重量级人物出来并试图提供帮助。最终,上述解决方案最有意义。
Laravel "^9.0"
我有点卡住了,因为我尝试构建的查询结果将解决一个更大的问题。情况是这样的:我有一个系统可以存储一天中的时间以向用户发送提醒。时间不与其他任何东西一起存储,而是与它们的时区相关联地存储。因此,如果用户在 America/Los_Angeles 时区,并且 select 每天下午 1 点提醒,他们应该在下午 1 点收到提醒。服务器和应用程序都在 UTC。因为我没有存储时间戳(我不需要日期,只需要一天中的时间,我发现在没有重要查询的情况下几乎不可能构建提醒逻辑(首先获取所有提醒,解析给用户,获取时区,然后按时间排序 selected)。我想通过简单的 JOIN 在使用用户时区的同时查询时间,但是,我似乎无法弄清楚如何使用 users.timezone 从 JOIN 开始工作。
提醒作业每 5 分钟运行一次,用户只能以 5 分钟为间隔 select 个提醒(例如 5:45 pm(存储为 17:45 pm))。 下面是看似简单的eloquent查询:
$reminders = Reminder::join('users as users', 'users.id', '=', 'reminders.user_id')
->where('reminders.time', '>=', Carbon::now()->subMinutes(2)->setTimezone('users.timezone')->format('G:i:s'))
->where('reminders.time', '<=', Carbon::now()->addMinutes(2)->setTimezone('users.timezone')->format('G:i:s'))
->get();
这里是错误:
Carbon\Exceptions\InvalidTimeZoneException
Unknown or bad timezone (users.timezone)
at vendor/nesbot/carbon/src/Carbon/CarbonTimeZone.php:106
102▕ }
103▕
104▕ if ($tz === false) {
105▕ if (Carbon::isStrictModeEnabled()) {
➜ 106▕ throw new InvalidTimeZoneException('Unknown or bad timezone ('.($objectDump ?: $object).')');
107▕ }
108▕
109▕ return false;
110▕ }
+2 vendor frames
3 app/Console/Commands/SendReminders.php:48
Carbon\Carbon::setTimezone("users.timezone")
+13 vendor frames
17 artisan:37
Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
如有任何帮助,我们将不胜感激。谢谢。
所以,事实证明我试图做的事情是不可能的(甚至 Taylor Otwell 在 Twitter 上发帖 - https://twitter.com/taylorotwell/status/1500100606274551816?s=21)。所以,我想我会折回并展示我最终做了什么:
首先,当我存储提醒时,我将其与当前用户时区和 UTC 一起存储,因此我有正确的时间用于其中任何一个。这里复杂的部分只是为了获得正确的偏移量,因为我没有存储完整的日期,只存储了小时和分钟。
然后在发送提醒的作业中,我有这个查询(替换上面的问题查询):
$results = Reminder::with('user')
->where('timeTz', Carbon::now()->format('H:i'))
->get();
我正在使用 Carbon::now(),因为我的应用程序以 UTC 运行,这就是 timeTz 的存储方式。我也是不看秒,只看时分。
那么,如果不是数千个查询(N+1,上面问题之前的原始问题),那么现在是一个。
我非常感谢 Twitter 上的 PHP 社区 - 一些重要的重量级人物出来并试图提供帮助。最终,上述解决方案最有意义。