如何在Laravel中查询MariaDB JSON列含Unicode字符的键
问题描述
模型包含JSON类型属性,当JSON键使用希腊字符(如μ)时,MariaDB会将其自动编码为Unicode转义序列(例如μ存储为\u03bc)。通过Eloquent读取数据时字符会自动还原,但使用whereJsonContainsKey查询含这类非标准字符的JSON键时,无法匹配到记录;查询常规字符键(如k)则正常。
数据创建代码:
$unit = Unit::factory()->create(); $unit->name = 'Some name'; $unit->unit = 'Ω'; $unit->prefixes = ['μ' => 0.000001, 'k' => 1000, 'M' => 1000000]; $unit->save();
查询示例:
// 返回null,无法命中记录 $u = Unit::whereJsonContainsKey('prefixes->μ')->first(); // 正常返回目标数据 $u = Unit::whereJsonContainsKey('prefixes->k')->first();
解决方案
方法1:直接用原始SQL匹配Unicode转义序列
利用MariaDB的JSON_CONTAINS_PATH函数,直接传入Unicode转义后的键进行查询:
$u = Unit::whereRaw("JSON_CONTAINS_PATH(prefixes, 'one', '$.\\u03bc')")->first();
注:PHP字符串中需双反斜杠转义,确保SQL语句最终传入$.\u03bc。
方法2:手动转义字符后使用whereJsonContainsKey
先将目标字符转换为Unicode转义格式,再传入whereJsonContainsKey:
// 手动转义μ为Unicode序列 $escapedKey = '\u03bc'; $u = Unit::whereJsonContainsKey("prefixes->{$escapedKey}")->first();
如果需要通用处理任意非ASCII字符,可以封装转义函数:
function jsonEscapeUnicode(string $str): string { return preg_replace_callback('/[^\x00-\x7F]/u', function ($match) { $char = mb_convert_encoding($match[0], 'UTF-16BE', 'UTF-8'); return sprintf('\u%04s', bin2hex($char)); }, $str); } // 转义μ后查询 $escapedMu = jsonEscapeUnicode('μ'); $u = Unit::whereJsonContainsKey("prefixes->{$escapedMu}")->first();
方法3:通过JSON_KEYS提取键后匹配
使用JSON_KEYS提取JSON的所有键,再用JSON_SEARCH检查目标字符是否存在:
$u = Unit::whereRaw("JSON_SEARCH(JSON_KEYS(prefixes), 'one', ?)", ['μ'])->first();
内容的提问来源于stack exchange,提问作者bartek_zet
相关产品推荐
相关产品推荐

