【问题标题】:Timezone middleware does not work时区中间件不起作用
【发布时间】:2017-09-21 05:44:03
【问题描述】:

我创建了一个中间件,以便根据数据库中设置的 auth 用户时区设置时区:

<?php

namespace App\Http\Middleware;

use Closure;

class TimezoneMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ($request->user()->guest()) {
            $timezone = config('app.timezone');
        }
        else {
            $timezone = $request->user()->timezone;
        }

        date_default_timezone_set($timezone);

        return $next($request);
    }
}

我将这个类添加到Kernel.php 中全局 HTTP 中间件声明的底部。

问题是它不起作用。显示created_at 字段时,无论我在数据库中设置什么用户时区,时间都保持不变。

【问题讨论】:

  • 数据库中的所有日期和时间都以 UTC 格式存储。除非您进行某种转换,否则您将从数据库查询中得到返回。
  • 我只想要从数据库中获取的任何timestamp 使用用户指定的时区。我试过中间件,服务提供商,没有任何效果。我迷路了。我正在使用数据表,所以我希望自动完成。
  • 你可能需要阅读这个stackoverflow.com/questions/15017799/…
  • 记住 date_default_timezone_set() 只影响 PHP 日期和时间函数的作用!!!
  • 我的问题是关于如何在每次查询时自动使用 Eloquent 执行此操作。

标签: php laravel timezone middleware


【解决方案1】:

我强烈建议您将日期保留在 UTC 的数据库中 - 这样可以省去您日后的麻烦。

我建议使用Eloquent Mutators,它可以是 应用于您的模型。

这将使您仍然可以使用数据表,因为突变发生在从数据库中提取数据之后。

您也许可以在您的应用程序中创建一个可重用的类,该类具有用于解析日期的静态方法,例如:

<?php

namespace App;

use Carbon\Carbon;

class DateTimeZoneMutator
{

    public static function mutate($value)
    {

        if (auth()->user()->guest()) {
            $timezone = config('app.timezone');
        }
        else {
            $timezone = auth()->user()->timezone;
        }

        return new Carbon(
            $value, $timezone
        );

    }

}

然后在您的模型中,为了论证,假设您的日期字段称为“registered_at”,您将添加以下方法:

<?php

namespace App;

use App\DateTimeZoneMutator;
use Illuminate\Database\Eloquent\Model;

class Something extends Model
{

    // ...

    public function getRegisteredAtAttribute($value)
    {
        return DateTimeZoneMutator::mutate($value);
    }

    // ...

}

【讨论】:

    【解决方案2】:

    你可以这样使用:

    {{ $model->created_at->setTimezone( $timezone )->toDateTimeString() }}
    

    不过,我相信一定有更好的选择。

    【讨论】:

      【解决方案3】:

      您的问题似乎是您想要普通的过滤器/系统中间件而不是 路由 中间件,所以如果您将中间件放在 kernel.php 文件的底部,那将无法正常工作。

      kernel.php中有不同的中间件,你应该在$middleware section and if your middleware is for routes to protect the routes then add intorouteMiddleware`中添加过滤器类型的中间件。

      过滤类型的中间件作为你的进入这个

      protected $middleware = [
          //.............
      ];
      

      如果路由保护和过滤中间件进入这个

      protected $routeMiddleware = [
          'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
          //..................
          //.................
      
      ];
      

      时区

      Config::set('app.timezone','custom time zone');
      

      【讨论】:

      • 我已经将该类放入全局 HTTP $middleware 声明中,就像我在 OP 中所说的那样。
      • 您是否尝试使用Config::set('app.timezone','custom time zone'); 而不是date_default_timezone_set($timezone); 设置时区
      • 为什么不直接保留时区,并在显示时格式化日期和时间,你有没有看过Carbon
      • "配置时区设置为 UTC,这是应用程序在将时间戳插入数据库时​​需要使用的时间。"只要您在数据库中使用正确的 TIMESTAMP 字段(而不是 DATETIME),无论配置值是什么,Laravel 都将始终存储为 UTC。
      • Laravel 使用应用程序时区来确定要插入数据库的时间戳。见Illuminate\Foundation\Bootstrap\LoadConfiguration
      猜你喜欢
      • 2017-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-22
      • 1970-01-01
      • 1970-01-01
      • 2021-04-19
      相关资源
      最近更新 更多