Carbon in Laravel 4 InvalidArgumentException - Unexpected data found. Trailing data
Asked Answered
G

3

14

I'm trying to get an Eloquent query result for DB::raw("DATE_FORMAT(created_at, '%m-%d-%Y %r') AS created_at") but each time I get this exception from Carbon:

InvalidArgumentException
Unexpected data found. Trailing data

If I change it to just created_at instead of employing MySQL's DATE_FORMAT() function, then it gets the data without issue.

I've not only done this sort of date formatting without issue before, but I checked every field in the database table (there are only 10 for this seed) and each is a standard valid date, so I'm wondering why Carbon is pitching a fit.

Running this in Laravel 4.1.

Guyot answered 11/6, 2014 at 16:56 Comment(0)
E
25

In an Eloquent query result (model) every date field is a carbon object, it means, if you query a model which contains any timestamp field like created_at, updated_at (basically created using timestamps() during migration) and deleted_at, Laravel converts them to a Carbon object and you may use any public methods of Carbon, for example:

$user = User::find(1);

// '2014-04-20 19:02:09' will become 'Apr 20, 2014'
$user->created_at->toFormattedDateString();

So, you may directly use any public method of Carbon on a timestamp field available in a model. If you try this:

dd($user->created_at);

Then the output will be:

object(Carbon\Carbon)[456]
  public 'date' => string '2014-04-20 19:02:09' (length=19)
  public 'timezone_type' => int 3
  public 'timezone' => string 'UTC' (length=3)

So, if you want to format a date, you may use:

// outputs like: 'Sunday 20th of April 2014 07:02:09 PM'
$user->created_at->format('l jS \\of F Y h:i:s A')

Update:

If you want to change this behavior, means that, if you want tell Laravel that, which fields should be converted automatically to Carbon object then you may override that by creating a method in your model like:

public function getDates()
{
    // only this field will be converted to Carbon
    return array('updated_at');
}

To totally disable date mutations, simply return an empty array from the getDates method. For more details, check Date Mutators on Laravel website.

Embodiment answered 11/6, 2014 at 20:3 Comment(2)
How can I do this as part of the original query? I need to fetch quite a few rows and several different columns, so that is why I was seeking to format the date in advance.Guyot
In your model you can override that by adding public function getDates()` as a date mutator. `Embodiment
I
6

I realise the original question refers to MySQL but I had the same error with MSSQL. The problem turned out to be that MSSQL's datetime column type has a precision of .001 seconds but I was setting my model's format to no precision:

protected function getDateFormat()
{
    return 'Y-m-d G:i:s';
}

By using the newer DateTime2 column type and turning off the precision, I fixed the error. I.e.

datetime2(0)

You could instead change the format in getDateFormat, of course.

Indiscreet answered 2/6, 2015 at 7:58 Comment(0)
J
0

If it helps anyone else, I got the same error when attempting to copy a date.

$user->last_login = Carbon::now();

if ($user->first_login < Carbon::createFromDate(2000, 1, 1)) {
    // This is the users first login
    $user->first_login = $user->last_login; // FAILS!
}

Turns out Laravel casts the value of $user->last_login to a DateTime+Timezone string. It's no longer a Carbon object.

You could fix the error by using copies of a single Carbon object (example below), or by setting up mutators (setters) on the underlying model.

$now = Carbon::now();
$user->last_login = $now;

if ($user->first_login < Carbon::createFromDate(2000, 1, 1)) {
    // This is the users first login
    $user->first_login = $now;
}
Jobye answered 19/4, 2016 at 1:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.