TimeZone updating in layout files but not view files

Can I set the user’s timezone in the layout file and let that flow through to the view files? Because it’s not working for me, but I suspect I’m doing something wrong.

Let’s say I have:

  • views/layout/main.php
  • views/something1/detailview1.php
  • views/something2/gridview2.php

in views/layout/main.php, I have:

Yii::$app->formatter->timeZone = $user->timezone

So anything my layout shows is in the user timezone. Anything in views/something1/detailview1.php or views/something2/gridview2.php is in UTC (my default). I am using attribute defs like: 'someattr1:datetime'.

If I move the timeZone setting above into each view file, then everything works. But, I’d much prefer to keep this in my layout file if possible to make it “global.”

The view is rendered (to a variable) before the layout is rendered.
You can set the timezone in the controller.

2 Likes

Okay, this is exactly what I needed to better understand, thank you. I now have this and it works just fine:

	public function beforeAction($action)
	{
		Yii::$app->formatter->timeZone = Yii::$app->user->identity->timezone;
	
		if (!parent::beforeAction($action)) {
			return false;
		}
	
		return true;
	}

View in MVC is for presentation. All such changes should be done in the controller and result, if any, passed to the view. Or if global then done in the configuration

Do you need it for all controllers?
In that case why not setup in the configuration or Boostrap class?

That’s even smarter that what I was did Stefano. What’s the best way to set this up in the site-wide configuration while not breaking anything? :slight_smile:

$config = [
    'modules' => [
        //....
    ],
    'components' => [
        //...
    ],
    'on beforeAction' => function ($e) {
        $tz = Yii::$app->user->identity->timezone ?? 'Africa/Dar_es_Salaam', //Default timezone when user timezone field is null
        Yii::$app->formatter->timeZone = $tz;
    },
];

//...

return $config;

You can also bootstrap it.

Prepare class:

<?php

declare(strict_types=1);

namespace app\components;

use yii\base\BootstrapInterface;

class TimeZoneSelector implements BootstrapInterface
{
    public function bootstrap($app)
    {
        if ($app && $app->user && !$app->user->isGuest) {
            $app->timeZone = $app->user->timezone ?? 'Africa/Dar_es_Salaam';
        }
    }
}

Then add it in your bootstrap config:


'bootstrap' => [
    'log', // you most probably have log in here already
    \app\components\TimeZoneSelector::class
],
2 Likes