Laravel 变音符号不敏感搜索

Laravel diacritic insensitive search

我尝试制作一个 API,它接受一个查询参数来过滤以下 link api/results/search?somefield=er 中的结果。我期望的结果应该是例如:

简而言之,Google Chrome 的实际版本正是我所需要的,当您在 Google Chrome 中按 CTRL+F 并尝试搜索时对于此页面 https://fr.lipsum.com/ 上的 er,您将获得包含 érer.

亮点的全文搜索

我正在使用 Laravel 集合而不是 Eloquent。

为了使搜索不区分大小写,PHP 已经为这种情况提供了一个名为 stristr($haystack, $needle)

的函数
foreach (request()->except('perPage') as $key => $value) {
    $results = $results->filter(function ($item) use ($key, $value) {
        return false !== stristr($item->$key, $value);
    });
}

关于如何正确搜索变音字母(french/spanish/etc.accents),现在我陷入了困境。

我已经做了一个字符列表,但不知道如何使用代码。

return [
    'siblings' => [
        'A'  => ['À', 'Á', 'Â', 'Ã', 'Å', 'Ǻ', 'Ā', 'Ă', 'Ą', 'Ǎ', 'Α', 'Ά', 'Ả', 'Ạ', 'Ầ', 'Ẫ', 'Ẩ', 'Ậ', 'Ằ', 'Ắ', 'Ẵ', 'Ẳ', 'Ặ', 'А'],
        'B'  => ['B'],
        'C'  => ['Ç', 'Ć', 'Ĉ', 'Ċ', 'Č'],
        'D'  => ['Ð', 'Ď', 'Đ', 'Δ'],
        'E'  => ['È', 'É', 'Ê', 'Ë', 'Ē', 'Ĕ', 'Ė', 'Ę', 'Ě', 'Ε', 'Έ', 'Ẽ', 'Ẻ', 'Ẹ', 'Ề', 'Ế', 'Ễ', 'Ể', 'Ệ', 'Е', 'Э'],
        'F'  => ['ƒ'],
        'G'  => ['Ĝ', 'Ğ', 'Ġ', 'Ģ'],
        'H'  => ['Ĥ', 'Ħ'],
        'I'  => ['Ì', 'Í', 'Î', 'Ï', 'Ĩ', 'Ī', 'Ĭ', 'Ǐ', 'Į', 'İ', 'Η', 'Ή', 'Ί', 'Ι', 'Ϊ', 'Ỉ', 'Ị'],
        'J'  => ['Ĵ'],
        'K'  => ['Ķ', 'Κ', 'К'],
        'L'  => ['Ĺ', 'Ļ', 'Ľ', 'Ŀ', 'Ł', 'Λ', 'Л'],
        'M'  => [''],
        'N'  => ['Ñ', 'Ń', 'Ņ', 'Ň', 'Ν'],
        'O'  => ['Ò', 'Ó', 'Ô', 'Õ', 'Ō', 'Ŏ', 'Ǒ', 'Ő', 'Ơ', 'Ø', 'Ǿ', 'Ο', 'Ό', 'Ω', 'Ώ', 'Ỏ', 'Ọ', 'Ồ', 'Ố', 'Ỗ', 'Ổ', 'Ộ', 'Ờ', 'Ớ', 'Ỡ', 'Ở', 'Ợ', 'О'],
        'P'  => [''],
        'R'  => ['Ŕ', 'Ŗ', 'Ř'],
        'S'  => ['Ś', 'Ŝ', 'Ş', 'Ș', 'Š', 'Σ'],
        'T'  => ['Ț', 'Ţ', 'Ť', 'Ŧ', 'Τ', 'Т'],
        'U'  => ['Ù', 'Ú', 'Û', 'Ũ', 'Ū', 'Ŭ', 'Ů', 'Ű', 'Ų', 'Ư', 'Ǔ', 'Ǖ', 'Ǘ', 'Ǚ', 'Ǜ', 'Ủ', 'Ụ', 'Ừ', 'Ứ', 'Ữ', 'Ử', 'Ự'],
        'X'  => [''],
        'Y'  => ['Ý', 'Ÿ', 'Ŷ', 'Υ', 'Ύ', 'Ϋ', 'Ỳ', 'Ỹ', 'Ỷ', 'Ỵ'],
        'W'  => ['Ŵ'],
        'Z'  => ['Ź', 'Ż', 'Ž', 'Ζ'],
        'AE' => ['Ä', 'Æ', 'Ǽ'],
        'UE' => ['Ü'],
        'IJ' => ['IJ'],
        'OE' => ['Ö', 'Œ'],
        'TH' => ['þ'],
        'SS' => ['ß'],
        'KS' => ['ξ'],
    ]
];

如果有人能告诉我我应该使用什么方法,我将不胜感激。我相信我需要使用 preg_match,但也许有更简单的方法类似于 stristr() ?

感谢任何给定的想法。

您实际上不需要制作自己的列表 Laravel 有一个名为 Str::ascii 的方法可以将 non-ascii 字符转换为它们的 ascii 等效字符,因此您可以:

foreach (request()->except('perPage') as $key => $value) {
    $results = $results->filter(function ($item) use ($key, $value) {
        return false !== stristr(\Str::ascii($item->$key), \Str::ascii($value));
    });
}

Str::ascii 中还有第二个参数用于语言,尽管据我所知,您只需要将它用于 bg(保加利亚语)或 de(德语)

如果您需要检查整个列表是什么,您可以查看 the source which also mentions that it's based on the Stringy 库。

底线是不要写你自己的列表,除非已经存在的列表对你来说不够用。

请注意,还有使用 iconv("UTF-8", "ASCII//TRANSLIT", $string) 的选项,它将音译非 ascii 字符。更多信息请见 iconv