mb_strlen () & strlen () не возвращают правильные значения из вызова Ajax в PHP

Как я могу добавить проверку в PHP для длины переданного имени $. Сайт UTF-8, но я считаю, что Javascript использует другую кодировку. Вы можете видеть в комментариях, где я пробовал разные вещи в PHP, и они не работают.

Что я пробовал и не работал:

  • Изменение Ajax (javascript) для передачи переменных по UTF-8, а не кодировке javascript
  • strlen, mb_strlen в PHP – оба возвращают неверные значения

БОЛЬШЕ ИНФОРМАЦИИ

Мой Ajax отправляет имя пользователя на мой PHP, который проверяет SQL-базу данных и возвращает ее или нет. Я решил попробовать и выполнить дополнительную проверку на PHP перед проверкой БД (например, mb_strlen($username ). Также установлено значение mb_internal_encoding("UTF-8"); .

Я собирался попытаться отправить запрос Ajax в UTF-8, но не видел способа сделать это.

правильно ли используется UPPER в MySQL? – для UTF-8?

PHP НИЖЕ * ** * ** * ** * *

 // Only checks for the username being valid or not and returns 'taken' or 'available' require_once('../defines/mainDefines.php'); // Connection variables require_once('commonMethods.php'); require_once('sessionInit.php'); // start session, check for HTTP redid to HHHTPs sleep(2); // Looks cool watching the spinner $username = $_POST['username']; //if (mb_strlen($username) < MIN_USERNAME_SIZE) echo 'invalid_too_short'; //if (mb_strlen($username, 'UTF-8') < 10) { echo ('invalid_too_short'); exit; } //die ('!1!' . $username . '!2!' . mb_strlen($username) . '!3!' . strlen($username) . '!4!'); $dbc = mysqli_connect(DB_HOST, DB_READER, DB_READER_PASSWORD, DB_NAME) or die(DB_CONNECT_ERROR . DB_HOST . '--QueryDB--checkName.php'); $stmt = mysqli_stmt_init($dbc); $query = "SELECT username FROM pcsuser WHERE UPPER(username) = UPPER(?)"; if (!mysqli_stmt_prepare($stmt, $query)) { die('SEL:mysqli_prepare failed somehow:' . $query . '--QueryDB--checkName.php'); } if (!mysqli_stmt_bind_param($stmt, 's', $username)) { die('mysqli_stmt_bind_param failed somehow --checkName.php'); } if (!mysqli_stmt_execute($stmt)) { die('mysqli_stmt_execute failed somehow' . '--checkName.php'); } mysqli_stmt_store_result($stmt); $num_rows = mysqli_stmt_num_rows($stmt); mysqli_stmt_bind_result($stmt, $row); echo ($num_rows >= 1) ? 'taken' : 'available'; mysqli_stmt_close($stmt); mysqli_close($dbc); 

AJAX CODE НИЖЕ

 function CheckUsername(sNameToCheck) { document.getElementById("field_username").className = "validated"; registerRequest = CreateRequest(); if (registerRequest === null) alert("Unable to create AJAX request"); else { var url= "https://www.perrycs.com/php/checkName.php"; var requestData = "username=" + escape(sNameToCheck); // data to send registerRequest.onreadystatechange = ShowUsernameStatus; registerRequest.open("POST", url, true); registerRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); registerRequest.send(requestData); } } function ShowUsernameStatus() { var img_sad = "graphics/signup/smiley-sad006.gif"; var img_smile = "graphics/signup/smiley-happy088.gif"; var img_checking = "graphics/signup/bluespinner.gif"; if (request.readyState === 4) { if (request.status === 200) { var txtUsername = document.getElementById('txt_username'); var fieldUsername = document.getElementById('field_username'); var imgUsername = document.getElementById('img_username'); var error = true; var response = request.responseText; switch (response) { case "available": txtUsername.innerHTML = "NAME AVAILABLE!"; error = false; break; case "taken": txtUsername.innerHTML = "NAME TAKEN!"; break; case "invalid_too_short": txtUsername.innerHTML = "TOO SHORT!"; break; default: txtUsername.innerHTML = "AJAX ERROR!"; break; } // matches switch if (error) { imgUsername.src = img_sad; fieldUsername.className = 'error'; } else { imgUsername.src = img_smile; fieldUsername.className = 'validated'; } } // matches ===200 } // matches ===4 } 

ИСПЫТАТЕЛЬНЫЕ РЕЗУЛЬТАТЫ

Это то, что я верну, когда я УМЕРЛЮ в PHP и выхожу как в следующем (до и после изменения Ajax ниже [добавление в UTF-8 к запросу] …

PHP SNIPPIT

 die ('!1!' . $username . '!2!' . mb_strlen($username) . '!3!' . strlen($username) . '!4!'); 

ИСПЫТАНИЯ

Имя пользователя: David Perry

1! Дэвид Перри! 2! 11! 3! 11! 4!

Имя пользователя: Ü| "~ ÷ Û ♦

! 1! ܦ \ "~% u2666! 2! 9! 3! 13! 4!

Первый работает. Второй должен работать, но похоже, что кодирование странно (понятно).

7 видимых символов для второго. mb_strlen показывает 9, strlen показывает 13.

После прочтения решения и ссылки Joeri Sebrechts, которые они мне дали, я искал параметры запроса Ajax, и у кого-то было следующее …

AJAX SNIPPIT (изменено с исходного кода)

 registerRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8"); 

(Я добавил в charset=UTF-8 из примера, который я видел в статье).

ОБНОВЛЕНИЕ: 27 ноября, 21:11 EST

Хорошо, после долгих чтений я считаю, что я кодирую свое JS неправильно. Я использовал побег … следующим образом …

 var requestData = "username=" + escape(sNameToCheck); 

Посмотрев этот сайт …

http://www.the-art-of-web.com/javascript/escape/

это помогло мне понять, что происходит с каждой функцией и как они кодируются и декодируются. Я должен это сделать …

 var requestData = "username=" + encodeURIComponent(sNameToCheck); 

в JS и PHP я должен это сделать …

 $username = rawurldecode($_POST['username']); 

Выполнение этого еще дает мне 8 символов для моего странного примера выше, а не 7. Это близко, но я делаю что-то неправильно? Если я курсор через текст на экране, это 7 символов. Любые идеи, которые помогут мне лучше понять это?

ИСПРАВЛЕНО / РЕШИТЬ !!!

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

В AJAX – я использовал escape (sNameToCheck);

 var requestData = "username=" + encodeURIComponent(sNameToCheck); 

В PHP * – у меня было $ username = $ _POST ['username']; – *

 $username = rawurldecode($_POST['username']); if (get_magic_quotes_gpc()) $username = stripslashes($username); 

Я действительно ненавижу magic_quotes … это вызвало у меня около 50 часов разочарования по данным формы в целом, потому что я забыл об этом. Пока это работает. Я счастлив!

Итак, теперь mb_strlen работает, и я могу легко добавить это обратно в …

 if (mb_strlen($username) < MIN_USERNAME_SIZE) { echo 'invalid_too_short'; exit; } 

Прекрасно работает!

PHP – это байтовый процессор, он не поддерживает кодировку. Это имеет ряд сложных последствий.

Strlen () возвращает длину в байтах, а не длину в символах. Это связано с тем, что тип «string» php на самом деле представляет собой массив байтов. Utf8 использует более одного байта на символ для «специальных символов». Поэтому strlen () даст вам правильный ответ для узкого подмножества текста (= простой текст на английском языке).

Mb_strlen () обрабатывает строку как действительные символы, но предполагает, что она находится в кодировке, заданной через mbstring.internal_encoding, потому что сама строка представляет собой всего лишь массив байтов и не имеет метаданных, указывающих свой набор символов. Если вы работаете с данными utf8 и устанавливаете internal_encoding в utf8, он даст вам правильный ответ. Если ваши данные не являются utf8, это даст вам неправильный ответ.

Mysql получит поток байтов из php и проанализирует его на основе набора символов сеанса базы данных, который вы устанавливаете с помощью директивы SET NAMES. Каждый раз, когда вы подключаетесь к базе данных, вы должны сообщить ей, в какой кодировке находятся ваши php-строки.

Браузер получает поток байтов от php и будет анализировать его на основе заголовка http-типа charset содержимого, который вы контролируете через php.ini default_charset. Ajax-вызов будет отправляться в ту же кодировку, что и страница, из которой она выполняется.

Подводя итог, вы можете найти рекомендации на следующей странице о том, как обеспечить, чтобы все ваши данные обрабатывались как utf8. Следуйте за ней, и ваша проблема должна решить сама. http://malevolent.com/weblog/archive/2007/03/12/unicode-utf8-php-mysql/

С быстрым взглядом вы можете очистить это:

 if (request.status == 200) { if (request.responseText == "available") { document.getElementById("txt_username").innerHTML = "NAME AVAILABLE!"; document.images['img_username'].src=img_smile; document.getElementById("continue").disabled = false; document.getElementById("field_username").className = 'validated'; } else if (request.responseText == "taken") { document.getElementById("txt_username").innerHTML = "NAME TAKEN!"; document.images['img_username'].src=img_sad; document.getElementById("field_username").className = 'error'; } else if (request.responseText == "invalid_too_short") { document.getElementById("txt_username").innerHTML = "TOO SHORT!"; document.images['img_username'].src=img_sad; document.getElementById("field_username").className = 'error'; } else { document.getElementById("txt_username").innerHTML = "AJAX ERROR!"; document.images['img_username'].src=img_sad; document.getElementById("field_username").className = 'error'; } } 

чтобы:

 // I prefer triple equals // Read more at http://javascript.crockford.com/style2.html if (request.status === 200) { // use variables! var txtUsername = document.getElementById('txt_username'); var fieldUsername = document.getElementById('field_username'); var imgUsername = document.getElementById('img_username'); var response = request.responseText; var error = true; // you can do a switch statement here too, if you prefer if (response === "available") { txtUsername.innerHTML = "NAME AVAILABLE!"; document.getElementById("continue").disabled = false; error = false; } else if (response === "taken") { txtUsername.innerHTML = "NAME TAKEN!"; } else if (response === "invalid_too_short") { txtUsername.innerHTML = "TOO SHORT!"; } else { txtUsername.innerHTML = "AJAX ERROR!"; } // refactor error actions if (error) { imgUsername.src = img_sad; fieldUsername.className = 'error'; } else { imgUsername.src = img_smile; fieldUsername.className = 'validated'; } }