phplaravelmariadbphp-carbon

Using a custom MariaDb Grammar for Carbon timestamp precision with Laravel, the application crashes when calling `$builder->toRawSql()`


My goal is to store microseconds in a MariaDB database timestamp fields when using a laravel application.

Following the instructions on https://carbon.nesbot.com/laravel/, I created my Grammar class:


<?php

namespace App\Database\Query\Grammars;

use Illuminate\Database\Query\Grammars\MariaDbGrammar as IlluminateMariaDbGrammar;

class MariaDbGrammar extends IlluminateMariaDbGrammar
{
    public function getDateFormat(): string
    {
        return 'Y-m-d H:i:s.u';
    }
}

and on my AppServiceProvides.php, I included the line DB::connection()->setQueryGrammar(new \App\Database\Query\Grammars\MariaDbGrammar());

Then I created a sample artisan command on console.php

Artisan::command('raw', function () {
    dd(DB::table('user')->where('id_user', 'abc')->toRawSql());
});

Running php artisan raw, the application crashes with

 RuntimeException 

  The database driver's grammar implementation does not support escaping values.

  at vendor/laravel/framework/src/Illuminate/Database/Grammar.php:238
[truncated]
      +1 vendor frames 

  2   [internal]:0
      Illuminate\Database\Query\Grammars\Grammar::Illuminate\Database\Query\Grammars\{closure}()
      +2 vendor frames 

  5   routes/console.php:84
      Illuminate\Database\Query\Builder::toRawSql()

Commenting out the line, the program works as expected:

"select * from `user` where `id_user` = 'abc'" // routes/console.php:84

What is the correct way to enable microseconds for MariaDB databases on a laravel 11 application?


Solution

  • Solved by

    1. Creating a MariaDbGrammar exactly as described in the question (following the instruction on https://carbon.nesbot.com/laravel/

    2. Creating a MariaDbConnection class in my application that extends Illuminate's MariadDbConnection:

    class MariaDbConnection extends IlluminateMariaDbConnection
    {
        protected function getDefaultQueryGrammar(): MariaDbGrammar
        {
            // this is the Grammar created on the previous step
            ($grammar = new MariaDbGrammar())->setConnection($this);
    
            return $this->withTablePrefix($grammar);
        }
    }
    
    1. On the AppServiceProvider.php, register the connection with the new Connection class:
    public function boot(): void
    {
        Connection::resolverFor('mariadb', fn(...$args) => new MariaDbConnection(...$args));
    }
    

    Done.