user3489502
user3489502

Reputation: 3611

Converting datetime data on retrieval with user's timezone using date mutators in Laravel 5

I'm saving all datetime data (created_at, updated_at and a custom datetime column: appointment_at) in UTC format.

I would like to retrieve all these dates, and convert them to the user's timezone for display.

I've added these functions to my model thinking this would retrieve the datetime in the user's timezone:

public function getCreatedAtAttribute($value)
{
    return $created_at->timezone(Auth::user()->timezone);
}

public function getUpdatedAtAttribute($value)
{
    return $updated_at->timezone(Auth::user()->timezone);
}

public function getAppointmentAtAttribute($value)
{
    return $appointment_at->timezone(Auth::user()->timezone);
}

But I get the following error:

Call to a member function timezone() on a non-object

I'm guessing there's an error in my syntax. Am I missing something? Thanks

UPDATE #1 Made corrections to Note Model and added complete Model below (including corrections by @bernie)

<?php namespace App;


use Illuminate\Database\Eloquent\Model;


class Note extends Model {


/**
 * The database table used by the model.
 *
 * @var string
 */
protected $table = 'notes';


/**
 * The attributes that are mass assignable.
 *
 * @var array
 */
protected $fillable = ['client_id', 'business_id', 'note'];


/**
 * Note belonging to client.
 * 
 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
 */
public function client()
{
    return $this->belongsTo('App\Client');
}


public function getCreatedAtAttribute($value)
{
    return $this->created_at->timezone(Auth::user()->timezone);     
}   

public function getUpdatedAtAttribute($value)
{
    return $this->updated_at->timezone(Auth::user()->timezone);     
}   

public function getAppointmentAtAttribute($value)
{
    return $this->appointment_at->timezone(Auth::user()->timezone);     
}   

Database Model definition

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateNotesTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('notes', function(Blueprint $table)
        {
            $table->increments('id');

            $table->integer('client_id')->unsigned();
            $table->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');

            $table->integer('business_id')->unsigned();
            $table->foreign('business_id')->references('id')->on('businesses')->onDelete('cascade');

            $table->text('note');
            $table->dateTime('appointment_at');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('notes');
    }

}

More info about the error (after updates by bernie)

 ErrorException in Note.php line 40: Undefined property: App\Note::$created_at

in Note.php line 40
at HandleExceptions->handleError('8', 'Undefined property: App\Note::$created_at', '/var/www/html/laravel5/app/Note.php', '40', array()) in Note.php line 40
at Note->getCreatedAtAttribute('2015-09-22 12:50:20') in Model.php line 2669
at Model->mutateAttribute('created_at', '2015-09-22 12:50:20') in Model.php line 2592
at Model->getAttributeValue('created_at') in Model.php line 2557
at Model->getAttribute('created_at') in Model.php line 3263
at Model->__get('created_at') in NotesController.php line 54
at NotesController->show('1')

Solution

public function getCreatedAtAttribute($value)
{
    $date = $this->asDateTime($value);
    return $date->timezone(\Auth::user()->timezone);
}

or

public function getCreatedAtAttribute($value)
{
    $format = $this->getDateFormat();      
    return  Carbon::createFromFormat($format, $value, 'UTC')->setTimezone( \Auth::user()->timezone);
}   

Both of these solutions worked for me.

Upvotes: 3

Views: 3652

Answers (1)

bernie
bernie

Reputation: 10390

Ah now I see! I realized you're using Accessors and Mutators. You're also overriding the built-in date mutators used for created_at and other dates fields.

So, try this instead :

public function getCreatedAtAttribute($value)
{
    // asDateTime() is the built-in date mutator.
    $date = $this->asDateTime($value);
    return $date->timezone(Auth::user()->timezone);
}

public function getUpdatedAtAttribute($value)
{
    $date = $this->asDateTime($value);
    return $date->timezone(Auth::user()->timezone);
}

public function getAppointmentAtAttribute($value)
{
    $date = $this->asDateTime($value);
    return $date->timezone(Auth::user()->timezone);
}

Upvotes: 6

Related Questions