Като MySQL или PHP разработчик , след като прекрачите удобните граници на набори от символи само на английски, вие бързо се озовавате в чудесно шантавия свят на UTF-8 кодиране.
Бърз UTF-8 грундНа предишен работа , започнахме да се сблъскваме с проблеми с кодирането на данни, когато показвахме биография на художници от цял свят. Скоро стана ясно, че има проблеми със съхранените данни, тъй като понякога данните са правилно кодирани, а понякога не.
Това накара програмистите да внедрят смесица от кръпки, понякога с JavaScript, понякога с мета тагове на HTML кодове, понякога с PHP и т.н. Скоро завършихме със списък с 600 000 биографии на художници с двойно или тройно кодирана информация, като данните се съхраняват по различни начини в зависимост от това кой е програмирал функцията или е приложил кръпката. Класическо техническо гнездо на плъх.
Всъщност навигацията през проблемите с кодирането на данни UTF-8 може да бъде разочароващо и издърпващо преживяване. Тази публикация предоставя кратка готварска книга за справяне с тези проблеми с UTF-8, по-специално при работа с PHP и MySQL, въз основа на практически опит и научени уроци (и с благодарности, отчасти, на откритата информация тук и тук по пътя).
как да прехвърля erc20 токени
По-конкретно, ще разгледаме следното в тази публикация:
php.ini
файл и PHP код .my.ini
файл и други Проблеми, свързани с MySQL за да сте наясно (включително конфигурационни модове, необходими, ако използвате Сфинкс )Първото нещо, което трябва да направите, е да промените вашия php.ini
файл, който да използва UTF-8 като набор от символи по подразбиране:
default_charset = 'utf-8';
(Забележка: Впоследствие можете да използвате phpinfo()
, за да проверите дали това е зададено правилно.)
Добре, готини, така че сега PHP и UTF-8 трябва да работят добре заедно. Нали?
Е, не точно. Всъщност, дори и близо.
Въпреки че тази промяна ще гарантира, че PHP винаги извежда UTF-8 като кодиране на символи (в заглавките на Content type тип отговор на браузъра), все пак трябва да направите няколко модификации на вашия PHP код, за да сте сигурни, че той правилно обработва и генерира UTF- 8 знака.
Свързани: Най-добри практики и съвети за PHP от разработчиците на ApeeScapeЗа да сте сигурни, че вашият PHP код играе добре в пясъчника за кодиране на данни UTF-8, ето нещата, които трябва да направите:
Задайте UTF-8 като набор от символи за всички заглавки, изведени от вашия PHP код
Във всеки PHP изходен заглавие посочете UTF-8 като кодиране:
header('Content-Type: text/html; charset=utf-8');
Посочете UTF-8 като тип кодиране за XML
function utf8_for_xml($string) { return preg_replace('/[^x{0009}x{000a}x{000d}x{0020}-x{D7FF}x{E000}-x{FFFD}]+/u', ' ', $string); }
Извадете неподдържани символи от XML
Тъй като не всички UTF-8 символи се приемат в XML документ, ще трябва да премахнете всички такива знаци от всеки XML, който генерирате. Полезна функция за това (което намерих тук ) е следното:
$safeString = utf8_for_xml($yourUnsafeString);
Ето как можете да използвате тази функция във вашия код:
htmlspecialchars
Посочете UTF-8 като набор от символи за цялото HTML съдържание
За HTML съдържание посочете UTF-8 като кодиране:
htmlspecialchars($str, ENT_NOQUOTES, 'UTF-8')
В HTML формите посочете UTF-8 като кодиране:
default_charset
Посочете UTF-8 като кодиране при всички разговори към htmlspecialchars
e.g.:
htmlentities
*Забележка: От PHP 5.6.0, mysql_set_charset
стойност се използва като по подразбиране. От PHP 5.4.0, UTF-8 беше по подразбиране, но преди PHP 5.4.0, ISO-8859-1 се използваше по подразбиране. Следователно е добра идея винаги да се посочва изрично UTF-8, за да бъде в безопасност, въпреки че този аргумент е технически незадължителен.
Също така имайте предвид, че за UTF-8, $link = mysql_connect('localhost', 'user', 'password'); mysql_set_charset('utf8', $link);
и mysql_set_charset
може да се използва взаимозаменяемо.
Задайте UTF-8 като набор от символи по подразбиране за всички MySQL връзки
Посочете UTF-8 като набор от символи по подразбиране, който да се използва при обмен на данни с базата данни MySQL, използвайки mysqli::set_charset
:
$mysqli = new mysqli('localhost', 'my_user', 'my_password', 'test'); /* check connection */ if (mysqli_connect_errno()) { printf('Connect failed: %s
', mysqli_connect_error()); exit(); } /* change character set to utf8 */ if (!$mysqli->set_charset('utf8')) { printf('Error loading character set utf8: %s
', $mysqli->error); } else { printf('Current character set: %s
', $mysqli->character_set_name()); } $mysqli->close();
Имайте предвид, че от PHP 5.5.0, strlen
е оттеглено и iconv
трябва да се използва вместо:
iconv_strlen
Винаги използвайте UTF-8 съвместими версии на функции за манипулиране на низове
Има няколко PHP функции, които ще се провалят или поне няма да се държат според очакванията, ако представянето на символа се нуждае от повече от 1 байт (както UTF-8 прави). Пример е mbstring
функция, която ще върне броя байтове, а не броя символи.
Има две възможности за справяне с това:
The my.ini
функции, които са достъпни по подразбиране с PHP, предоставят многобайтови съвместими версии на много от тези функции (напр. [client] default-character-set=UTF-8 [mysql] default-character-set=UTF-8 [mysqld] character-set-client-handshake = false #force encoding to uft8 character-set-server=UTF-8 collation-server=UTF-8_general_ci [mysqld_safe] default-character-set=UTF-8
и т.н.). Не забравяйте обаче, че низовете, които предоставяте на тези функции, трябва сами да бъдат кодирани правилно.
Има и my.ini
разширение към PHP (налична е информация за активирането и конфигурирането му) тук ). Това разширение предоставя изчерпателен набор от функции, които правилно отчитат многобайтовото кодиране.
От страна на нещата MySQL / UTF-8, модификации на mysql> show variables like 'char%';
файл са необходими, както следва:
Задайте следните конфигурационни параметри след всеки съответния маркер:
| character_set_client | UTF-8 | character_set_connection | UTF-8 | character_set_database | UTF-8 | character_set_filesystem | binary | character_set_results | UTF-8 | character_set_server | UTF-8 | character_set_system | UTF-8 | character_sets_dir | /usr/share/mysql/charsets/
След като направите горните промени във вашия latin1
файл, рестартирайте вашия MySQL демон.
За да проверите дали всичко е правилно настроено да използва кодирането UTF-8, изпълнете следната заявка:
utf8mb4
Резултатът трябва да изглежда по следния начин:
set names UTF-8;
Ако вместо това видите sphinx.conf
изброени за някое от тези, проверете отново конфигурацията си и се уверете, че сте рестартирали правилно своя демон на mysql.
MySQL UTF-8 всъщност е частично изпълнение на пълния набор от знаци UTF-8. По-конкретно, MySQL UTF-8 кодирането използва максимум 3 байта, докато 4 байта са необходими за кодиране на пълния набор от знаци UTF-8. Това е добре за всички езикови символи, но ако трябва да поддържате астрални символи (чиито кодови точки варират от U + 010000 до U + 10FFFF), те изискват четирибайтово кодиране, което не се поддържа в MySQL UTF-8. В MySQL 5.5.3 това беше адресирано с добавяне на поддръжка за utf8mb4 набор от символи който използва максимум четири байта на символ и по този начин поддържа пълния набор от знаци UTF-8. Така че, ако използвате MySQL 5.5.3 или по-нова версия, използвайте charset_type = utf-8
вместо UTF-8 като набор от символи на вашата база данни / таблица / ред. Повече информация е на разположение тук .
Ако свързващият клиент няма начин да посочи кодирането за комуникацията си с MySQL, след установяване на връзката може да се наложи да изпълните следната команда / заявка:
sql_query_pre = SET CHARACTER_SET_RESULTS=UTF-8 sql_query_pre = SET NAMES UTF-8
Когато определяте размера на полетата на varchar, когато моделирате базата данни, не забравяйте, че UTF-8 символите може да изискват до 4 байта на символ.
вид валутен риск
Във вашия конфигурационен файл на Sphinx (т.е. charset_table
):
Задайте дефиницията на индекса си да има:
my.ini
Добавете следното към вашата дефиниция на източника:
ALTER SCHEMA `your-db-name` DEFAULT CHARACTER SET UTF-8;
Рестартирайте двигателя и преработете всички индекси.
Ако искате да конфигурирате сфинкса така, че всички букви като C c Ć ć Ĉ ĉ Ċ ċ Č č да се третират като еквивалентни за целите на търсенето, ще трябва да конфигурирате mysql> show variables like 'char%';
(известен още като сгъване на символи), което по същество представлява картографиране на еквивалентност между символите. Налична е повече информация тук .
Ако имате съществуваща база данни MySQL, която вече е кодирана в latin1, ето как да конвертирате latin1 в UTF-8:
Уверете се, че сте направили всички промени в настройките за конфигурация във вашия mysqldump -u USERNAME -pDB_PASSWORD --opt --skip-set-charset --default-character-set=latin1 --skip-extended-insert DATABASENAME --tables TABLENAME > DUMP_FILE_TABLE.sql
файл, както е описано по-горе.
Изпълнете следната команда:
mysqldump -u root --opt --skip-set-charset --default-character-set=latin1 --skip-extended-insert artists-database --tables tbl_artist > tbl_artist.sql
Чрез командния ред проверете дали всичко е правилно настроено на UTF-8
perl -i -pe 's/DEFAULT CHARSET=latin1/DEFAULT CHARSET=UTF-8/' DUMP_FILE_TABLE.sql
Създайте dump файл с кодиране latin1 за таблицата, която искате да конвертирате:
mysql> source 'DUMP_FILE_TABLE.sql';
e.g:
c# урок за дискорд бот
mysql> select count(*) from MY_TABLE where LENGTH(MY_FIELD) != CHAR_LENGTH(MY_FIELD);
Направете глобално търсене и заменете набора от символи в dumpfile от latin1 на UTF-8:
напр. използване на Perl:
create table temptable ( select * from MY_TABLE where LENGTH(MY_FIELD) != CHAR_LENGTH(MY_FIELD));
Забележка за потребителите на Windows: Тази подмяна на символни символни низове (от latin1 на UTF-8) може да се извърши и чрез намиране и замяна в WordPad (или някакъв друг текстов редактор, като vim). Не забравяйте да запазите файла точно такъв, какъвто е (не го запазвайте като unicode txt файл!).
От този момент ще започнем да се забъркваме с данните от базата данни, така че вероятно би било разумно да направите резервно копие на базата данни, ако все още не сте го направили. След това възстановете дъмп в базата данни:
alter table temptable modify temptable.ArtistName varchar(128) character set latin1;
Потърсете записи, които може да не са преобразували правилно, и ги коригирайте. Тъй като не-ASCII символите са многобайтови по дизайн, можем да ги намерим, като сравним дължината на байта с дължината на символа (т.е., за да идентифицираме редове, които могат да съдържат двойно кодирани UTF-8 символи, които трябва да бъдат фиксирани).
Вижте дали има записи с многобайтови символи (ако тази заявка връща нула, тогава в таблицата ви не изглежда да има записи с многобайтови символи и можете да преминете към стъпка 8).
alter table temptable modify temptable.ArtistName blob; alter table temptable modify temptable.ArtistName varchar(128) character set UTF-8;
Копирайте редове с многобайтови символи във временна таблица:
delete from MY_TABLE where LENGTH(MY_FIELD) = CHAR_LENGTH(MY_FIELD);
Преобразувайте двойно кодирани UTF-8 знака в правилни UTF-8 знаци
Това всъщност е малко сложно. Двойно кодиран низ е този, който е бил правилно кодиран като UTF-8. Тогава обаче MySQL ни направи грешна услуга да го преобразуваме (от това, което е мисъл беше латински1) до UTF-8 отново , когато задаваме колоната на UTF-8 кодиране. Следователно разрешаването на това изисква процес от две стъпки, чрез който „подвеждаме“ MySQL, за да го изключим да ни прави тази „услуга“.
Първо, задаваме типа кодиране за колоната обратно на latin1, като по този начин премахваме двойното кодиране:
e.g.:
replace into MY_TABLE (select * from temptable);
Забележка: Не забравяйте да използвате правилния тип поле за вашата таблица. В горния пример за нашата таблица правилният тип поле за „Име на изпълнител“ е varchar (128), но полето в таблицата ви може да бъде текстово или друг вид. Не забравяйте да го посочите правилно!
Проблемът е, че сега, ако зададем кодирането на колоната обратно на UTF-8, MySQL ще стартира кодирането на данни latin1 до UTF-8 за нас отново и ще се върнем там, откъдето започнахме. За да избегнем това, променяме типа колона на blob и СЛЕД това го задаваме на UTF-8. Това използва факта, че MySQL няма да се опитва да кодира blob. По този начин ние сме в състояние да „заблудим“ преобразуването на набора от MySQL, за да избегнем проблема с двойното кодиране.
e.g.:
|_+_|
(Отново, както беше отбелязано по-горе, не забравяйте да използвате правилния тип поле за вашата таблица.)
Премахнете редове само с еднобайтови символи от временната таблица:
|_+_|
Поставете отново фиксирани редове обратно в оригиналната таблица (преди да направите това, може да искате да изпълните някои селекти на изкусителното, за да проверите дали изглежда правилно коригирани, точно като проверка на здравословното състояние).
Проверете останалите данни и, ако е необходимо, повторете процеса в стъпка 7 (това може да е необходимо, например, ако данните са били тройно кодирани). Допълнителни грешки, ако има такива, може да са най-лесни за отстраняване ръчно.
Друго нещо, което трябва да запомните и проверите, е, че вашите файлове с изходен код, файлове с ресурси и т.н., се запазват правилно с UTF-8 кодиране на данни. В противен случай евентуалните „специални“ знаци в тези файлове може да не се обработват правилно.
Например в Netbeans можете да щракнете с десния бутон върху вашия проект, да изберете свойства и след това в „Източници“ ще намерите опцията за кодиране на данни (обикновено по подразбиране е UTF-8, но си струва да се провери).
Или в Windows Notepad, използвайте опцията “Save As ...” в менюто File и изберете опцията за кодиране UTF-8 в долната част на диалоговия прозорец. (Обърнете внимание, че опцията „Unicode“, която Notepad предлага, всъщност е UTF-16, така че не е това, което искате.)
Въпреки че може да е малко досадно, отделянето на време, за да преминете през тези стъпки за системно справяне с вашите проблеми с кодирането на данни MySQL и PHP UTF-8, в крайна сметка може да ви спести много време и скръб. В дългосрочен план този тип методичен подход е далеч по-добър от твърде разпространената тенденция просто да продължава да се коригира системата.
Надяваме се, че това ръководство подчертава важността да се вземе предвид дефиницията на набора символи при първоначално създаване на среда на проект и работа в среда на софтуерен проект, която правилно отчита кодирането на символи при манипулирането на текст и низове.
Свързани: Преди да отстраните грешки в PHP, който не работи, консултирайте се със списъка с 10-те най-често срещани грешки, които PHP разработчиците правятДефиниран от стандарта Unicode, UTF-8 е 8-битово кодиране на символи, способно да съхранява ay Unicode символ. Той е обратно съвместим с ASCII.
UTF е съкращение от Unicode Transformation Format, докато суфиксът „8“ обозначава използването на 8-битови блокове за представяне на символи.
За да вмъкнете Unicode символи в MySQL, трябва да създадете таблица с поддръжка на Unicode, да изберете подходящите настройки за кодиране / съпоставяне и да посочите набора от символи в MySQL връзката. След това можете да продължите и да използвате PHP код, за да вмъкнете Unicode, както желаете.