mb_strlen()& strlen()不返回从Ajax调用到PHP的正确值 [英] mb_strlen() & strlen() don't return correct values from an Ajax call to PHP

查看:188
本文介绍了mb_strlen()& strlen()不返回从Ajax调用到PHP的正确值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在PHP中添加一个支票来传递$ username的长度。该网站是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:


  • 更改Ajax(javascript)以UTF-8传递变量,而不是JavaScript编码

  • strlen,PHP中的mb_strlen - 都返回不正确的值

更多信息

MORE INFO

我的Ajax发送一个用户名给我的PHP,它检查SQL数据库并返回可用。检查数据库之前,我决定尝试在PHP中进行一些额外的检查(如 mb_strlen($ username )。 mb_internal_encoding(UTF-8 ); 也被设置。

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.

我将尝试使用UTF-8发送Ajax请求,但没有看到一种方法

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 BELOW * ** * ** * ** * strong>

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代码

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添加到请求中)...

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 SNIPPIT

PHP SNIPPIT

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

测试数据

TEST DATA

用户名: David Perry

Username: David Perry

!1!David Perry!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 SNIPPIT (从原始代码更改)

AJAX SNIPPIT (changed from original code)

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

(我在

更新:11月27日晚上9点11分EST

好的,很多阅读后我相信我编码我的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/escape/

它帮助我了解每个函数的更多内容以及它们如何编码和解码,我应该可以这样做...

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);

在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中 - 我以前有escape(sNameToCheck); -

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

在PHP * - 我曾经有$ username = $ _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的string类型实际上是一个字节数组。 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接收一个字节流,并将根据content-type charset 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 / unicode-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/

这篇关于mb_strlen()&amp; strlen()不返回从Ajax调用到PHP的正确值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆