php - mb_strlen() 和 strlen() 不会从对 PHP 的 Ajax 调用返回正确的值

标签 php javascript ajax encoding utf-8

我如何在 PHP 中添加对传递的 $username 长度的检查。该站点是 UTF-8,但我相信 Javascript 使用的是不同的编码。您可以在评论中看到我在 PHP 中尝试了不同的东西但它们不起作用。

我尝试过但没有成功的方法:

  • 更改 Ajax (javascript) 以通过 UTF-8 而不是 javascript 编码传递变量
  • PHP 中的 strlen、mb_strlen - 都返回不正确的值

更多信息

我的 Ajax 向我的 PHP 发送用户名,PHP 检查 SQL 数据库并返回可用与否。我决定在检查数据库之前尝试在 PHP 中做一些额外的检查(比如 mb_strlen($username)。mb_internal_encoding("UTF-8"); 也已设置.

我打算尝试以 UTF-8 格式发送 Ajax 请求,但没有找到方法。

在 MySQL 中是否正确使用了 UPPER? - 对于 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代码如下

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 中 DIE 时得到的返回结果,如下所示(在下面进行 Ajax 更改之前和之后 [在请求中添加 UTF-8]...

PHP 代码片段

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

测试数据

用户名:大卫佩里

!1!大卫佩里!2!11!3!11!4!

用户名: ܦ"~÷Û♦

!1!V\"~��%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)。

更新时间:美国东部时间 11 月 27 日晚上 9:11

好吧,经过大量阅读,我相信我的 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() 返回以字节为单位的长度,而不是以字符为单位的长度。这是因为php的“string”类型实际上是一个字节数组。 Utf8 为“特殊字符”使用每个字符多于一个字节。因此 strlen() 只会为您提供一小部分文本(= 纯英文文本)的正确答案。

Mb_strlen() 将字符串视为实际字符,但假定它采用通过 mbstring.internal_encoding 指定的编码,因为字符串本身只是一个字节数组,没有指定其字符集的元数据。如果您使用的是 utf8 数据并将 internal_encoding 设置为 utf8,它将为您提供正确的答案。如果您的数据不是 utf8,它会给您错误的答案。

Mysql 将从 php 接收字节流,并根据您通过 SET NAMES 指令设置的数据库 session 字符集对其进行解析。每次连接到数据库时,您都必须通知它您的 php 字符串的编码。

浏览器从 php 接收字节流,并根据内容类型字符集 http header 解析它,您可以通过 php.ini default_charset 控制它。 ajax 调用将以与其运行的页面相同的编码提交。

总而言之,您可以在下一页找到有关如何确保所有数据都被视为 utf8 的建议。遵循它,您的问题应该会自行解决。 http://malevolent.com/weblog/archive/2007/03/12/unicode-utf8-php-mysql/

关于php - mb_strlen() 和 strlen() 不会从对 PHP 的 Ajax 调用返回正确的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8250709/

相关文章:

javascript - 获取从 PHP 到 JavaScript 的输入值

php - 将数组值和其他表单值插入到两个不同的mysql表中

javascript - 强连通分量算法

javascript - 在父 div 调整大小时调整图表大小

c# - 如何检测客户端是否可以访问 iFrame 中的网站?

php - 查询不起作用

php - PHP 是否具有在给定有效内容类型的情况下返回正确文件扩展名的函数?

javascript - 输入按钮值用于附加 URL

javascript - ReactJS:未捕获类型错误:无法读取未定义的属性 'setState'

php - Paypal "add to cart"不离开页面