Based on malhal's answer, I was able to get fractional timestamp reading to work here. Pasting the answer here for convenience:
class BaseModel extends Model
{
protected $dateFormat = 'Y-m-d\TH:i:s.u';
protected function asDateTime($value)
{
try {
return parent::asDateTime($value);
} catch (\InvalidArgumentException $e) {
return parent::asDateTime(new \DateTimeImmutable($value));
}
}
public function newQuery()
{
$query = parent::newQuery();
if($this->usesTimestamps()) {
$table = $this->getTable();
$column = $this->getDeletedAtColumn();
$query->addSelect(DB::raw("concat($table.$column) as $column"));
}
return $query;
}
}
There is a lot going on here because it gets the query with scopes applied and then adds a select for the updated_at column to the end, which overwrites any previously loaded updated_at column later while Laravel hydrates the Model from the query. For being an ugly hack, it worked surprisingly well the very first time.
Timestamps are stored internally as Carbon in Laravel:
dd(MyModel->first()->updated_at->format('Y-m-d H:i:s.u'));
Output:
2017-04-14 22:37:47.426131
Also be sure to run a migration to convert your columns to fractional timestamps. Microsecond precision raises the size of timestamps from 4 bytes to 7 bytes but this is 2017, don't let saving a byte or two by choosing millisecond precision cost you a fortune later when you find yourself serving stale cache entries:
\DB::statement("ALTER TABLE my_table MODIFY updated_at TIMESTAMP(6) NULL DEFAULT NULL");
Sadly I haven't found a way to modify the migration schema timestamps()
function to do this.