mb_strlen()及strlen的()不会从一个Ajax调用PHP返回正确的价值观价值观、正确、strlen、mb_strlen

2023-09-10 17:30:24 作者:绊绊绊绊死你

我如何在PHP中添加检查的顺利通过$用户名长度。该网站是UTF-8,但我相信JavaScript是使用不同的编码。您可以在我试图在PHP不同的事情的意见看,他们不工作。

How can I add a check in the PHP for the length of the $username passed. The site is UTF-8 but I believe Javascript is using a different encoding. You can see in the comments where I tried different things in the PHP and they don't work.

我尝试和没有工作:的

What I tried and didn't work:

更改阿贾克斯(JavaScript)的用UTF-8,而不是JavaScript的编码来传递变量 strlen的,mb_strlen在PHP - 都返回不正确的值

更多信息的

MORE INFO

我的阿贾克斯发送用户名到我的PHP,它检查SQL数据库,并返回可用。我决定尝试和检查数据库(如 mb_strlen($用户名)。 mb_internal_encoding(UTF-8之前,做在PHP一些额外的检查); 也设置

My Ajax sends a username to my PHP, which checks the SQL DB and returns available or not. I decided to try and do some extra checking in the PHP before checking the DB (like mb_strlen($username). mb_internal_encoding("UTF-8"); is also set.

我要尝试并发送Ajax请求的UTF-8,但没有看到一个办法做到这一点。

I was going to try and send the Ajax request in UTF-8 but didnt see a way to do that.

被正确使用MySQL的UPPER? - 为UTF-8的东西

PHP低于的 * 的**的 * 的**的 * 的**的 * 的*

PHP BELOW ***********

// 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以下

AJAX CODE BELOW

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和回声出如以下(之前和决策低于[加为UTF-8请求] ...

This is what I get back when I DIE in the PHP and echo out as in the following (before and after making the Ajax change below [adding in UTF-8 to the request]...

PHP的这段的

PHP SNIPPIT

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

测试数据的

TEST DATA

用户名:大卫·佩里

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

!1!David Perry!2!11!3!11!4!

用户名:Ü|〜÷Û♦

!1!ܦ\〜%u2666!2!9!3!13!4!

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

第一个作品。第二个应该工作,但它看起来像编码是怪异的(可以理解)。

The first one works. The second one should work but it looks like the encoding is weird (understandable).

7可见字符为:第二个。 mb_strlen显示9,strlen的显示13。

7 visible characters for the 2nd one. mb_strlen shows 9, strlen shows 13.

在读Joeri Sebrechts解决方案,链接,他们给了我,我抬头一看Ajax请求参数和别人有以下...

After reading Joeri Sebrechts solution and link they gave me I looked up Ajax request parameters and someone had the following...

AJAX的这段的(改变从原来的code)

AJAX SNIPPIT (changed from original code)

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

(我加了的charset = UTF-8 从我看到一个文章的例子)。

(I added in the charset=UTF-8 from an example I saw on a article).

更新:11月27日,下午9点11分美国东部时间

好了,大量的阅读后,我相信我在我的编码错误的JS。我用逃生......如下......

Ok, after much reading I believe I am encoding my JS wrong. I was using escape... as follows...

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

在看这个网站...

http://www.the-art-of-web.com / JavaScript的/越狱/

它帮助我了解更多的什么,每个功能的事情,以及他们如何连接code和德code。我应该能够做到这一点...

it helped me understand more of what's going on with each function and how they encode and decode. I should be able to do this...

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

在JS和PHP中我应该能够做到这一点...

in JS and in PHP I should be able to do this...

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

这样做仍然给了我8个字符我的怪异上面的例子,而不是7,这是接近,但我做错了什么?如果我通过屏幕上的文本光标这是7个字符。任何想法,以帮助我更好的理解?

Doing that still gives me 8 characters for my weird example above instead of 7. It's close, but am I doing something wrong? If I cursor through the text on the screen it's 7 characters. Any ideas to help me understand this better?

固定/解决!

好了,谢谢你的提示,导致我在正确的方向,使这项工作。我的改变是如下:

Ok, thank you for your tips that lead me in the right direction to make this work. My changes were as follows.

在AJAX - 我曾经有过逃生(sNameToCheck); - 的

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

在PHP * - 我曾经有$用户名= $ _ POST ['用户名']; - *

In the PHP *-- I used to have $username = $_POST['username']; --*

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

我真的很讨厌magic_quotes ...它引起了我大约50多个小时的挫折感重于形式的数据总量,因为我忘了。只要它的工作原理。我很高兴!

I really hate magic_quotes... it's caused me about 50+ hours of frustration over form data in total because I forgot about it. As long as it works. I'm happy!

所以,现在mb_strlen的作品,我可以轻松地添加此回...

So, now the mb_strlen works and I can easily add this back in...

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

伟大工程!

推荐答案

PHP是一个字节处理器,它不是字符集感知。这有许多棘手的后果。

PHP is a byte processor, it is not charset-aware. That has a number of tricky consequences.

STRLEN()返回字节长度,字符不是长度。这是因为PHP的字符串类型实际上是一个字节数组。 UTF8每个字符使用多个字节的特殊字符。因此,strlen的()只会给你的文字的极小部分(=纯英文文本)正确答案。

Strlen() returns the length in bytes, not the length in characters. This is because php's "string" type is actually an array of bytes. Utf8 uses more than one byte per character for the 'special characters'. Therefore strlen() will only give you the right answer for a narrow subset of text (= plain english text).

Mb_strlen()将字符串作为实际字符,但假定它是在经由mbstring.internal_encoding指定的编码,因为字符串本身是一个字节只是阵列和不具有元数据指定其字符集。如果您正在使用UTF8的数据和设置internal_encoding为utf8它会给你正确的答案。如果你的数据是不是UTF8它会给你错误的答案。

Mb_strlen() treats the string as actual characters, but assumes it's in the encoding specified via mbstring.internal_encoding, because the string itself is just an array of bytes and does not have metadata specifying its character set. If you are working with utf8 data and set internal_encoding to utf8 it will give you the right answer. If your data is not utf8 it will give you the wrong answer.

MySQL会收到来自PHP的字节流,并根据数据库会话的字符集,您通过SET NAMES指令集将解析它。每次你连接到数据库,你必须告诉它什么编码你的PHP字符串的

Mysql will receive a stream of bytes from php, and will parse it based on the database session's character set, which you set via the SET NAMES directive. Everytime you connect to the database you must inform it what encoding your php strings are in.

浏览器接收从PHP字节流,并根据内容类型字符集的HTTP标头,您通过php.ini中DEFAULT_CHARSET控制上会分析它。 Ajax调用将提交相同的编码,因为它从运行的页面。

The browser receives a stream of bytes from php, and will parse it based on the content-type charset http header, which you control via php.ini default_charset. The ajax call will submit in the same encoding as the page it runs from.

总结,你可以就如何确保所有的数据被视为UTF8下页中找到建议。遵循它,你的问题可以自行解决。 http://malevolent.com/weblog/archive/2007/03/12/uni$c$c-utf8-php-mysql/

Summarized, you can find advice on the following page on how to ensure all your data is treated as utf8. Follow it and your problem should resolve itself. http://malevolent.com/weblog/archive/2007/03/12/unicode-utf8-php-mysql/