Сравнение строк в 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
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
6
0
4 939
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Было бы разумно просто позволить MySQL выполнять эту работу, отправив в MySQL запрос, например:

SELECT CASE WHEN '$a' = '$b' THEN 1 ELSE 0 END


EDIT post clarification:

Вы можете однократно перебрать весь интересующий декартов набор символов, соединенный с самим собой, и построить стандартный ассоциативный массив php наборов эквивалентности.

    for each $char1 in $charset {  
        for each $char2 in $charset {  
            $charmatch[$char1][$char2] = mysqlTestMatch($char1, $char2));  
        }  
    }  

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

Я делаю это с очень большим количеством строк по разным причинам, поэтому я бы не хотел использовать базу данных.

twk 29.01.2009 02:46

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

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

SELECT 1
FROM UniTest
WHERE str = "À"

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

Ответ принят как подходящий

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

Чтобы ответить на ваш вопрос, вы можете использовать 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. Не совсем уверен в этом.

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

Я отредактировал вопрос, чтобы точно отразить сопоставление и кодировку для хранения. Не могли бы вы привести мне пример использования mb_string для реализации этого? Я не вижу mb_strcmp в документации.

twk 23.01.2009 19:12

Я ошибся - нужно использовать iconv, а не mb_string. Я отредактировал свой ответ.

troelskn 24.01.2009 15:35

Это приближается. трюк // TRANSLIT хорош, но, как вы упомянули, ISO-8859-1 мне не нужен. MySQL использует сопоставление, которое выглядит примерно так, которое мне нужно как-то подражать: collation-charts.org/mysql60/…

twk 24.01.2009 22:31

Если довольно ограниченная функциональность Iconv вам не подходит, вы можете попробовать это расширение: derickrethans.nl/translit.php или это (простой php): sitepoint.com/blogs/2006/03/03/…

troelskn 25.01.2009 00:18

Оба позволяют использовать базу данных транслитерации, определяемую пользователем. Вы можете скопировать MySqls, если вам нужно точное совпадение. Но, вероятно, было бы проще просто использовать базу данных в первую очередь;)

troelskn 25.01.2009 00:19

Также посмотрите на форму нормализации юникода c (iirc). Я недавно сделал это для чего-то на питоне. Он разбивает символ на составные части, после чего вы можете вырезать не-ascci. "<акцент A>" => "A <акцент Unicode>" => "A"

Richard Levasseur 04.02.2009 21:12

Ссылка на сайт, размещенная @troelskn, сейчас не работает. Вот замена: sitepoint.com/us-ascii-transliterations-of-unicode-text

Jpsy 09.10.2012 13:06

Итак, если я правильно понял, вы хотите провести такое же сравнение в PHP, как если бы вы проверяли общий индекс UTF-8 в MySQL?

Самым простым было бы создать вспомогательную функцию, которая преобразовывала бы строку в соответствии с правилами utf8_general_ci, используемыми MySSQL, которые в основном предназначены для преобразования определенных букв в базовую букву.

Правила для этого сопоставления MySQL перечислены здесь:

http://www.collation-charts.org/mysql60/mysql604.utf8_general_ci.european.html

Например, если вы прокрутите немного вниз до «золотого А» слева, вы увидите все символы, которые будут преобразованы в этот А.

Учитывая вспомогательную функцию, например, 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);
}

Другие вопросы по теме