So, I want to query the notifications
table in Laravel by comparing a certain ID with the data
column. This is how data
column looks like:
{
"Message": "some message",
"id": 3
}
Now, I need to select all the notifications that have an ID that is equal to 3. Here is how I was trying to do it:
DB::table('notifications')->where('data->id', '3')->get();
But this throws the following error:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '>'$."id"' = ?' at line 1 (SQL: select * from
notifications
wheredata
->'$."id"' = 3)
I am losing my mind here, can anyone help me out?
There's nothing wrong with your query. It's your environment.
Problem
Laravel's
MySqlGrammar
translates thefield->key
notation in field names (on Laravel side) intofield->'$.key'
-style extractions (on MySQL side):I just confirmed that MariaDB does not support the
->
extraction operator as an alias to theJSON_EXTRACT()
function. However, the same query works against a vanilla MySQL 5.7 server.Assuming this
test
table:A query that uses the
->
extraction operator: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:
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:
I made Laravel MariaDB driver for json support. Get it here: ybr-nx/laravel-mariadb
The issue is with the
->
, i think you have a var called $data with some collection in it. If that so then the correct way is:Or if you have a Model related to notifications table then:
If the
Model
is calledNotification
(following Eloquent convention)But if you tried to find all ID's equals 3 then just:
The problem is that only MySQL supports the
->
operator, then the query will fail on MariaDB, but:Both MariaDB and MySQL supports the
JSON_EXTRACT
function, that parses the JSON and get a value from it.You can solve it by doing a query like this:
To do it with Laravel's Query Builder, you'll need to use
DB::raw
method:Please try it and tell me if go wrong.
Note: The
JSON_EXTRACT()
is only available onMySQL >= 5.7
orMariaDB >= 10.2.3
Thanks to @Sepehr, I didn't know that the
->
was an MySQL Operator, neither that JSON type existed. :-)