I have a curious conundrum about json fields and eloquent's whereJsonContains() method.
Setup
An eloquent model with a json field, so in this example its migration has something like
public function up(): void
{
Schema::create('blogs', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->json('categories');
$table->timestamps();
});
Blog::create([
'name' => 'Alpha',
'categories' => ['A'],
]);
Blog::create([
'name' => 'Epsilon',
'categories' => ['È'],
]);
}
and the model is something like
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
use Illuminate\Database\Eloquent\Model;
class Blog extends Model
{
protected $fillable = [
'name',
'categories',
];
protected $casts = [
'categories' => AsArrayObject::class,
];
}
Problem
After migrating, if I try this query in a controller it will work
dd(Blog::whereJsonContains('categories', 'A')->get());
but this one won't
dd(Blog::whereJsonContains('categories', 'È')->get());
If you look in the database you'll see a unicode instead of the È.
Obviously I tried json_encode, but it doesn't work.
What indeed work is writing some long string like this one, but I don't know why it works.
dd(Blog::whereJsonContains('categories', DB::raw('CONCAT(\'"\',' . str(json_encode('È'))->replace('\\', '\\\\') . ',\'"\')'))->get());
Does anyone has an idea of what's going on?
PS: Laravel 10.13.5 , PHP 8.1.4 , MariaDB 10.4.24