数据是 UTF-8,Ajax 错误地返回了一些字符

Data is UTF-8, Ajax is returning some characters incorrectly

我花了很多时间在网上搜索并看到了很多类似的答案,但找不到适合我的情况的答案。

我花了一些时间将 MySQL 数据库从 latin1(默认)转换为 UTF-8。我从文本文件中清空了 tables(截断)和 re-imported 数据。我已经为我的页面设置 headers 以使用 UTF-8 元标记:

<meta http-equiv="Content-Type" content="text/html" charset="UTF-8" />

而且到处都在使用它。当我通过 PHP 读取数据并将其输出到表格中时,数据正确显示,文本如:Königstadt 出现,正如人们所希望的那样。保存它们(更新集...)它们似乎没问题,因为当我从数据中 re-read 它们时,表格中的显示是正确的。 (PHP Admin 中的显示显示 "Königstadt",这很奇怪,但当我读取数据时它似乎是正确的...... - 我希望这是 PHP 的一些奇怪之处管理员)

当我使用 Ajax 通过 PHP 检索数据时,我的 Ajax 代码似乎对我不利。下面是一个相对简单的例程,它调用 PHP 程序来为 SELECT:

生成选项标签
     function get_branches()
     {
        // numeric values that need to be passed to the
        // routine (so we show the correct item selected)
        var region = document.getElementById("search_region").value;
        // the code in load_branches needs this, but ...
        var branch = document.getElementById("search_branch").value;

        $.ajax
        ({
           type: "POST",
           url: "<?php echo $Roster_html_RootPath; ?>lookups/load_branches.php",
           data: {
                   'region' : region,
                   'local_branch' : branch
                 },
           //cache: false,
           success: function(data)
           {
              // load contents of DIV tag with id of branchoptions:
              $("#branch_options").html(data);
           }  // end success
        }); // end ajax call
     }; // end function get_branches()

  }); // end document.ready ...

大多数 returned 的记录都很好。然而,上面显示的 (Königstadt) 看起来像: HTML Select 中的 Königstadt 是 returned。

我一直在尝试寻找解决方案,例如为 Ajax 设置 contentType,以下是我尝试过的方法:

contentType: "application/x-www-form-urlencoded;charset=utf-8",

这个似乎没有任何区别。没有任何变化。

contentType: "application/text; charset=utf-8",

(或application/json) 这会杀死传递给 PHP 文件的值——数据数组似乎没有到达那里,因为我从 PHP:

得到错误
Notice: Undefined index: region in C:\xampp\htdocs\Heralds\Roster\lookups\load_branches.php on line 32

Notice: Undefined index: local_branch in C:\xampp\htdocs\Heralds\Roster\lookups\load_branches.php on line 33

我完全不知道如何正确 return 值。我需要文本或 html 的版本(我 return 一个 html table 或此处的选项标签),但我还需要使用 json 数组,我的一些代码可以正确 return 值。 None 其中似乎可以正确处理 UTF-8 编码数据。我已经为此工作了一段时间,并且感到非常沮丧。我看到的解释不起作用或在某些情况下没有意义...

PHP lookups/load_branches.php

<?php
// if session has not started:
session_start();

// load some basic configuration, including relative paths
// and variables needed ...
include_once( "../includes/configuration.php" );

// data connection
include_once( $Roster_RootPath . "includes/connect.php");

// values from Ajax code:
$region       = $_POST["region"];
$local_branch = $_POST["local_branch"];

// open the roster_branches table and get list
if( $region > 0 ) // check only needed for find_by_branch.php
{
   $branch_statement = "select * from roster_branches where region=" .  $region . " order by local";
}
else
{
   $branch_statement = "select * from roster_branches order by local";
}

// first, get the data from the table:
$branch_result = mysqli_query( $connect, $branch_statement );
if( !$branch_result )
{
   $out = "";
   $out .= "<div class='alert alert-danger'>";
   $out .= "<p><b>Error in SQL statement ...</b><br />";
   $errornum = mysqli_errno( $connect );
   $out .= "MySQL Error Number: " . $errornum . "<br />";
   $out .= "MySQL Error: " . mysqli_error( $connect ) . "<br />";
   $out .= "SQL Statement: " . $branch_statement . "</p>";
   $out .= "</div>";
   echo $out;
   die;   
}
else
{
   $out = "";
   // create select:
   $out = "<select class='form-control' id='local_branch' name='local_branch'>\n";

   // need the blank option:
   $out .= "   <option value=0 selected></option>\n";

   while( $branch_row = mysqli_fetch_array( $branch_result ) )
   {
      $id = $branch_row["rb_id"];
      $local = $branch_row["local"];
      $selected = "";
      if( $local_branch == $id )
      {
         $selected = " selected";
      }
      $out .= "<option value=" . $id . $selected . ">" . $local . "</option> \n";
   }

   $out .= "</select>\n";
   echo $out;      
} // we have something

?>

my MySQL database to UTF-8 from latin1 (the default).


1) I used "utf8_unicode_ci". 2) I have no idea what "multibyte safe functions" you're talking about. I use mysqli_real_escape_string() when reading data from $_POST, and the usual mysqli_query() and so on functions

这就是您遇到问题的原因。

有 3 个主要地方可以解决这个问题:

1)

您需要在 MySQL 中启用真正的 UTF-8(4 字节),以便存储在您的 SQL 中的数据是 stored 作为正确的 UTF-8 字符。通过普遍使用带有utf8mb4_前缀的排序规则和字符集。

2)

为确保来自 application/PHP 的数据被正确 保存,您需要确保数据 传递给 MySQL 作为UTF-8 4 字节字符 通过将 连接字符集 设置为完整 (4 字节 ) UTF-8 PHP:

$mysqliObject->set_charset('utf8mb4');   // object oriented style
mysqli_set_charset($connect, 'utf8mb4');    // procedural code style

3)

最后;您需要确保 PHP 对结果数据所做的任何处理都是 多字节感知 ;通过使用 mbstring 组函数。

最值得注意的是:

因此每个 PHP 页面的顶部在任何浏览器输出之前都应如下所示)

mb_internal_encoding('UTF-8');
mb_http_output('UTF-8');

然后,如果您使用 str_<whatever> 函数(和其他一些函数)执行任何操作,您就会知道在将字符串输出到浏览器(在本例中为 ajx)之前,它不会破坏您的字符串。


ö 对于 ö 是 "Mojibake"。请参阅 中的 "Mojibake"。

但真正的问题可能发生在您从 latin1 转换时。

需要通过 ALTER TABLE .. CONVERT TO CHARACTER SET utf8mb4 转换表格。任何其他技术都可能造成混乱。

与 MySQL 的任何连接都需要指定 utf8mb4