There's nothing wrong with your query. It's your environment.
Problem
Laravel's MySqlGrammar
translates the field->key
notation in field names (on Laravel side) into field->'$.key'
-style extractions (on MySQL side):
/**
* Wrap the given JSON selector.
*
* @param string $value
* @return string
*/
protected function wrapJsonSelector($value)
{
$path = explode('->', $value);
$field = $this->wrapValue(array_shift($path));
$path = collect($path)->map(function ($part) {
return '"'.$part.'"';
})->implode('.');
// Here:
return sprintf('%s->\'$.%s\'', $field, $path);
}
I just confirmed that MariaDB does not support the ->
extraction operator as an alias to the JSON_EXTRACT()
function. However, the same query works against a vanilla MySQL 5.7 server.
Assuming this test
table:
╔════╤══════════════════╗
║ id │ payload ║
╟────┼──────────────────╢
║ 1 │ {"a": 1, "b": 2} ║
╚════╧══════════════════╝
A query that uses the ->
extraction operator:
SELECT payload->"$.b" FROM test;
fails against MariaDB 10.2.8 while it yields a correct 2
against a MySQL 5.7.19 server.
Solutions
The right solution depends on what you're using on production.
Replace MariaDB
If you're using MySQL, replace MariaDB with MySQL in your development env. On a macOS machine managed by homebrew, it'd be as easy as:
brew services stop mysql
brew uninstall mariadb
brew install mysql
brew services start mysql
your data will remain intact.
Rewrite your queries
However, if you're using MariaDB in production, you need to rewrite your queries to use JSON_EXTRACT()
function as Elias already mentioned. As you can see you need to be much more verbose with the Laravel API.
The above query would be:
SELECT JSON_EXTRACT(payload, "$.b") FROM test;