Сравнение строк в 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
Author: Benjamin, 2009-01-23

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. Не совсем уверен в этом.

Вероятно, было бы проще использовать базу данных, хотя, как уже предлагали другие.

 9
Author: troelskn, 2009-01-24 12:34:56

Почему бы вам просто не позволить MySQL решить, существует ли уже запись с тем же ключом?

Вы можете запустить запрос SELECT, чтобы спросить, есть ли уже запись с этим атрибутом:

SELECT 1
FROM UniTest
WHERE str = "À"

Или вы просто пытаетесь вставить новую запись и используете функции mysql_error() и mysql_errno(), чтобы проверить, произошла ли ошибка.

 1
Author: Gumbo, 2009-01-22 22:14:20

Было бы разумно просто позволить 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));  
        }  
    }  

Затем вам нужно будет проверить каждую строку по символу, чтобы убедиться, что а) они одинаковы, а если нет, б) они эквивалентны.

 1
Author: dkretz, 2014-02-27 19:40:45

Итак, если я правильно понял, вы хотите провести аналогичное сравнение в 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
 0
Author: alphadogg, 2009-02-04 20:33:11

Используйте коллатор или транслитератор 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);
}
 0
Author: masakielastic, 2013-09-19 07:50:34