Сравнение строк в PHP так же, как это делает MySQL
Я сохраняю varchar в таблице MySQL utf8 и использую параметры сортировки utf8_general_ci. У меня есть уникальный индекс на varchar. Я хотел бы провести сравнение строк в PHP, которое эквивалентно тому, что MySQL будет делать с индексом.
Конкретный пример заключается в том, что я хотел бы иметь возможность определить, что "a" считается эквивалентным "À" в PHP, прежде чем это произойдет:
mysql> insert UniTest (str) values ('a');
Query OK, 1 row affected (0.00 sec)
mysql> insert UniTest (str) values ('À');
ERROR 1062 (23000): Duplicate entry 'À' for key 1
5 answers
Параметры сортировки не имеют никакого отношения к хранилищу. Вам необходимо установить кодировку, чтобы определить кодировку хранилища. Параметры сортировки определяют, как должно происходить сравнение и сортировка. Параметры сортировки должны быть заданы с учетом кодировки, но в противном случае они не имеют никакого отношения к кодировке.
Чтобы ответить на ваш вопрос, вы можете использовать iconv
для перевода текста, а затем сравнить его. Например:
function compare($s1, $s2) {
return strcmp(
iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $s1),
iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $s2));
}
Это в основном то, что MySQL сделает для вас, хотя это, вероятно, быстрее и может имейте несколько иную таблицу сортировки, чем ISO-8859-1//TRANSLIT
. Не совсем уверен в этом.
Вероятно, было бы проще использовать базу данных, хотя, как уже предлагали другие.
Почему бы вам просто не позволить MySQL решить, существует ли уже запись с тем же ключом?
Вы можете запустить запрос SELECT
, чтобы спросить, есть ли уже запись с этим атрибутом:
SELECT 1
FROM UniTest
WHERE str = "À"
Или вы просто пытаетесь вставить новую запись и используете функции mysql_error() и mysql_errno(), чтобы проверить, произошла ли ошибка.
Было бы разумно просто позволить MySQL выполнять эту работу, отправив запрос в MySQL, например:
SELECT CASE WHEN '$a' = '$b' THEN 1 ELSE 0 END
РЕДАКТИРОВАТЬ уточнение после публикации:
Вы могли бы один раз перебрать весь набор символов интересующей декартовой системы, соединенный с самим собой, и построить стандартный ассоциативный массив php наборов эквивалентности.
for each $char1 in $charset { for each $char2 in $charset { $charmatch[$char1][$char2] = mysqlTestMatch($char1, $char2)); } }
Затем вам нужно будет проверить каждую строку по символу, чтобы убедиться, что а) они одинаковы, а если нет, б) они эквивалентны.
Итак, если я правильно понял, вы хотите провести аналогичное сравнение в PHP, как при проверке общего индекса UTF-8 в MySQL?
Проще всего было бы создать вспомогательную функцию, которая преобразует строку в соответствии с правилами utf8_general_ci, используемыми MySQL, которые в основном предназначены для преобразования определенных букв в базовую букву.
Правила для этой сортировки MySQL перечислены здесь:
http://www.collation-charts.org/mysql60/mysql604.utf8_general_ci.european.html
Например, если вы немного прокрутите вниз до "золотого А", слева вы увидите все символы, которые преобразуются в этот A.
Учитывая вспомогательную функцию, называемую, например, utf8g_to_ascii()
, вы могли бы написать функцию:
function utf8_compare($s1, $s2) {
$a = utf8g_to_ascii($s1);
$b = utf8g_to_ascii($s2);
return strcmp( $a, $b );
}
Я бы смоделировал свой код после:
http://dev.splitbrain.org/view/darcs/dokuwiki/inc/utf8.php
Используйте коллатор или транслитератор intl.
$s1 = 'a';
$s2 = 'À';
var_dump(
is_same_string($s1, $s2),
$s1 === transliterator_transliterate('Any-Latin; Latin-ASCII; Lower()', $s2)
);
function is_same_string($str, $str2, $locale = 'en_US')
{
$coll = collator_create($locale);
collator_set_strength($coll, Collator::PRIMARY);
return 0 === collator_compare($coll, $str, $str2);
}