2011-11-23 62 views
4

如何在PHP中添加一个支票,以传递$ username的长度。该网站是UTF-8,但我相信Javascript正在使用不同的编码。你可以在评论中看到我在PHP中尝试了不同的东西,但它们不起作用。mb_strlen()&strlen()不会从Ajax调用返回正确的值到PHP

我试过和不工作:

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

更多信息

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

我打算尝试用UTF-8发送Ajax请求,但没有看到这样做的方法。

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下面的代码

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格式添加请求]阿贾克斯变化后...

PHP SNIPPIT

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

测试数据

用户名:大卫佩里

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

(I在charset=UTF-8加入从I上的文章锯的一例)。

更新:11月27日,下午九时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个字符。任何想法帮助我更好地理解这一点?

FIXED /已解决!!!

好的,谢谢你的提示,使我在正确的方向使这项工作。我的更改如下。

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

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

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

$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; } 

添加此回的伟大工程!

+1

该段...伤害。整体,迂腐,looong。请编辑(至少添加一些段落)。 –

+0

那么,无论出于什么原因,你都有'mb_strlen()'部分注释掉了。什么不工作? –

+0

你好。 mb_strlen和strlen都给出了错误的值,因为我相信它在Ajax调用中的编码方式不同。 – PerryCS

回答

6

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

Strlen()返回字节长度,而不是字符长度。这是因为php的“字符串”类型实际上是一个字节数组。 Utf8使用每个字符多于一个字节的'特殊字符'。因此,strlen()只会给你正确答案的文本的一个狭窄的子集(=纯英文文本)。

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

Mysql将接收来自php的字节流,并将根据您通过SET NAMES指令设置的数据库会话字符集来解析它。每当你连接到数据库,你必须通知它你的php字符串是什么编码。

浏览器接收来自php的字节流,并将基于内容类型charset http头来解析它, php.ini default_charset。 ajax调用将以与它运行的页面相同的编码提交。总结一下,你可以在下面的页面找到关于如何确保所有数据都被视为utf8的建议。按照它,你的问题应该解决自己。 http://malevolent.com/weblog/archive/2007/03/12/unicode-utf8-php-mysql/

+0

我忘了一些代码行可能是问题...在最初的Ajax调用 registerRequest.setRequestHeader(“Content-Type”,“application/x-www-form-urlencoded”) ; 当我打印什么PHP看到它是一堆奇怪/ u2323的东西。所以,我认为这是Ajax编码。 有没有办法将我的Ajax作为UTF-8传递? – PerryCS

+0

我用更多的代码重新编辑了我的帖子,所以你可以确切地看到我在做什么。没有检查长度它确实工作(也许它是一个侥幸它的工作)。它插入数据库,告诉我,如果它采取或不。完美的作品(或似乎如此)。我也用奇怪的角色试了一下。问题出现时,我试图添加检查的长度。我还阅读了你链接的文章 - 非常感谢你。它有助于。除了我读过的'uni'选项之外,我已经完成了其中的所有工作。我必须再看一眼。 (对不起,改变我的帖子,不想在你尝试帮助时烦扰你)。 – PerryCS

+0

OH ...所以也许我把它搞乱了...... registerRequest。setRequestHeader( “内容类型”, “应用程序/ x WWW的形式进行了urlencoded”); 如果Ajax使用与页面相同的编码提交调用....嗯... – PerryCS

1

从快速浏览,你可以打扫一下:

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'; 
     } 
} 
+0

谢谢!你的方法更清洁。我会整理我的代码!任何方式你可以帮助它的strlen部分? – PerryCS

+0

我看了你链接的文章。从来没有想过这样!谢谢你的提示!我尝试和练习良好的编程,但是在学习时 - 哇......太多了!大声笑我用===之前,但我不知道那篇文章是什么。谢谢!!! – PerryCS

+0

没问题。很高兴我可以帮助:) – lrusli