已弃用的 utf8_encode($foo) 可以工作,而 mb_convert_encoding($foo, 'UTF-8) 则不行

问题描述 投票:0回答:1

在 web.config

 设置为 
IIS 环境中,将数据从 PHP(使用 default_charset = 'UTF-8' 设置)传输到 MySQL 时,我遇到了一个非常烦人的问题:

<globalization requestEncoding="UTF-8" responseEncoding="UTF-8" />

还在具有相同默认字符集的 Apache 环境中进行了测试,结果相同。我还设置了 MySQLi 在任何查询之前设置字符集:

$mysqli->set_charset('UTF-8');
我还有一组准备好的语句,用于搜索字符串中的

each字符,以使用以下方法将任何非 UTF-8 编码转换为 UTF-8:

mb_convert_encoding($char, 'UTF-8', mb_detect_encoding($char));

尝试失败后,通过使用相同的过程解析整个字符串:

mb_convert_encoding($string, 'UTF-8', mb_detect_encoding($string));
带有脚本的文件的内容类型设置为标题上的 

content-type charset UTF-8

。但这仍然没有解决问题。

我也,

已将 MySQL 表和模式的所有排序规则设置为 utf8mb4

,当然还使用“utf8mb4_unicode_520_ci”。尽管如此,问题仍然存在。

我写的分割字符串的函数如下:

static private function split_and_convert($value, $encoding = 'UTF-8') { $split = mb_str_split($value); $filter = []; foreach($split as $chr) { $from = mb_detect_encoding($chr); $encoded = ($from !== $encoding) ? mb_convert_encoding($chr, $encoding, $from) : $chr; $filter[] = $encoded; // echoing for testing echo 'char ' . $encoded . ' (' . $from . ')<br>'; } return join('', $filter); }
这回显了以下尝试保存的内容

Martínez

char M (ASCII) char a (ASCII) char r (ASCII) char t (ASCII) char � (UTF-8) char n (ASCII) char e (ASCII) char z (ASCII)
MySQL 抛出以下错误:

Error No: 1366 - Incorrect string value: '\xEDnez' for column 'contactLast' at row 1
还是没有喜悦。但如果我这样做,它就像一个魅力:

static private function split_and_convert($value, $encoding = 'UTF-8') { $split = mb_str_split($value); $filter = []; foreach($split as $chr) { $from = mb_detect_encoding($chr); $encoded = ($from !== $encoding) ? mb_convert_encoding($chr, $encoding, $from) // set to actually encode the 'UTF-8' encoded char // I'm supposed not to do this, but is what works // which makes no sense : utf8_encode($chr); $filter[] = $encoded; // echoing for testing echo 'char ' . $encoded . ' (' . $from . ')<br>'; } return join('', $filter); }
结果如下:

char M (ASCII) char a (ASCII) char r (ASCII) char t (ASCII) char í (UTF-8) char n (ASCII) char e (ASCII) char z (ASCII)
MySQL 不会抛出任何错误。如果我将 

utf8_encode

 替换为 
mb_convert_encoding($encoded, 'UTF-8')
,我会得到与不过滤字符串相同的错误。

我怀疑

mb_detect_encoding

 要么错误地检测到字符编码,要么只是 mb_convert_encoding 没有完成它的工作。

如果有人可以提供帮助,我将不胜感激。我花了几个小时寻找解决方案,但所提供的解决方案都不起作用。我发现自己陷入了困境,因为有效的方法已被弃用。

所以,这些是我面临的问题列表:

    mb_convert_encoding -> 不编码或编码为 UTF8 以外的内容
  1. mb_detect_encoding -> 未正确检测
  2. 字符串被编码为 ASCII 而不是 UTF-8 作为请求头中的字符集。
  3. 困惑:为什么我需要将 UTF-8 编码的字符编码为 UTF-8 才能工作?
php mysql utf-8 utf8mb4 mb-convert-encoding
1个回答
0
投票
在寻找答案和一整天的研究之后,这就是问题所在。过度加工。在开发过程中的某个时刻,会设置一个中间人来验证每个 POST/GET 请求并处理每个值,以确保发送的编码是 UTF-8。我正在重构的代码已经处理了数据。

中间人是使用

utf8_encode

进行编码的,所以,我怀疑函数检查本身是为了避免过度处理。我还必须重构中间人,这样就不会有冲突。

所以,这就是问题所在,两个不同的代码正在处理编码,从而产生了冲突。一旦我重构了中间人,问题就消失了。

总之,问题不是

mb_convert_encoding

mb_detect_encoding
,如果您有类似的问题,请确保您正在处理的代码没有使用两种不同的方法使用不同的功能执行类似的过程。

在我的例子中,中间人没有验证或设置为检测字符串是否已经编码为 UTF-8,它只是实现编码。这也是我获得报酬来重构代码的原因。

对于我来说,为什么正确的 UTF-8 编码字符串会导致 MySQL 抛出错误,这仍然是没有意义的。为此,我怀疑过度处理正在破坏输入。

© www.soinside.com 2019 - 2024. All rights reserved.