-
Notifications
You must be signed in to change notification settings - Fork 11.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Eloquent ->where
on JSON boolean does not perform as expected
#45642
Comments
https://laravel.com/docs/9.x/queries#json-where-clauses
I guess usage of the |
Thank you for reporting this issue! As Laravel is an open source project, we rely on the community to help us diagnose and fix issues as it is not possible to research and fix every issue reported to us via GitHub. If possible, please make a pull request fixing the issue you have described, along with corresponding tests. All pull requests are promptly reviewed by the Laravel team. Thank you! |
Problem is framework/src/Illuminate/Database/Connection.php Lines 678 to 694 in 7a35c57
I don't see this changing any time soon, as many applications use boolean values for flag columns filtering, and most databases store those as integers. To compare a boolean stored in a JSON field unwrapped of an object or array, you can keep using |
I haven't used JSON in MySQL enough to hold an informed opinion, but framework/src/Illuminate/Database/Query/Grammars/Grammar.php Lines 565 to 581 in 69c0b92
But – since we're talking about not converting bindings in any way ( |
You are right I considered your example without bindings, but of course a real world scenario would require bindings. I just tried locally using dd(TestModel::where('json_column', new Expression('true'))->exists()); // true Generated query below: select exists(select * from `dummies` where `json_column` = true) as `exists` As this is verbose, you can add a macro to the query builder: \Illuminate\Database\Query\Builder::macro('whereJsonBool', function ($column, $value) {
$this->where(
$column,
new \Illuminate\Database\Query\Expression($value ? 'true' : 'false')
);
});
dd(TestModel::whereJsonBool('json_column', true)->exists()); Note: I kept the full qualified class names to make clear which classes I am using. |
Ah, fascinating! This seems like a perfectly sound workaround. I'll probably implement this (not even with the macro) for now. I'll leave this issue open in case someone has a more creative PR idea, but wouldn't be butt-hurt if it was closed in favor of prioritizing more important issues 😁 Thanks for taking the time to look into this! |
@shengslogar as a side note, a good place to register your macros is inside a Service Provider's Also see my updated code above, I changed the macro name so it does not conflict with the protected method you mentioned before. |
You're welcome, glad to help =) @driesvints usually reviews updated issues in his morning, but I believe this one won't make the cut into the framework, as storing unwrapped JSON scalar types seems to be a very particular use case, and there is a workaround. But any way you can give it a try. |
Agreed. Unless there's a smart way to have this work with normal query builder methods, it seems overkill to add a specific method for this. Thanks again for your help! |
@shengslogar I found this much tidy way: dd(TestModel::whereRaw('IF(json_column, 1, 0) = ?', [ true ])->exists()); // true Hope it helps you |
Seems like there's a workaround to this for now so going to leave it at this. Thanks all 👍 |
Description:
Apologies if this has already been discussed. #27847 suggests that we should be able to query primitives on JSON columns, but an actual, raw,
true
orfalse
inside a JSON column (that isn't nested in any object) cannot be queried via->where
.Steps To Reproduce:
$table->json('json_column');
class TestModel extends Model { protected $casts = [ 'json_column' => 'json' ]; }
TestModel::create([ 'json_column' => true ]);
Conversely, if
TestModel::create([ 'json_column' => [ 'foo' => true ] ]);
:The text was updated successfully, but these errors were encountered: