Laravel 的 UTF-8字符可能编码错误

我使用 Laravel (一个 PHP 框架)为移动设备编写服务,并以 JSON格式返回数据。在数据结果中有一些字段是用 UTF-8编码的。

以下陈述

return JsonResponse::create($data);

返回下面的错误

InvalidArgumentException
HELP
Malformed UTF-8 characters, possibly incorrectly encoded


Open: /var/www/html/vendor/symfony/http-foundation/Symfony/Component/HttpFoundation/JsonResponse.php
} catch (\Exception $exception) {
restore_error_handler();


throw $exception;
}


if (JSON_ERROR_NONE !== json_last_error()) {
throw new \InvalidArgumentException($this->transformJsonError());
}

我变了:

return JsonResponse::create($data);

return JsonResponse::create($data, 200, array('Content-Type'=>'application/json; charset=utf-8' ));

但还是没用。

我该怎么补救?

229015 次浏览

我编写这个方法是为了处理 UTF8数组和 JSON 问题。

/**
* Encode array from latin1 to utf8 recursively
* @param $dat
* @return array|string
*/
public static function convert_from_latin1_to_utf8_recursively($dat)
{
if (is_string($dat)) {
return utf8_encode($dat);
} elseif (is_array($dat)) {
$ret = [];
foreach ($dat as $i => $d) $ret[ $i ] = self::convert_from_latin1_to_utf8_recursively($d);


return $ret;
} elseif (is_object($dat)) {
foreach ($dat as $i => $d) $dat->$i = self::convert_from_latin1_to_utf8_recursively($d);


return $dat;
} else {
return $dat;
}
}
// Sample use
// Just pass your array or string and the UTF8 encode will be fixed
$data = convert_from_latin1_to_utf8_recursively($data);

在我的例子中,这会导致错误:

return response->json(["message" => "Model status successfully updated!", "data" => $model], 200);

但这不是:

return response->json(["message" => "Model status successfully updated!", "data" => $model->toJson()], 200);

我找到了这个问题的答案

照做就是了

mb_convert_encoding($data['name'], 'UTF-8', 'UTF-8');

在我的案例中,亚洲字母串上有一个 ucfirst。这是不可能的,并产生了一个非 utf8字符串。

我得到了这个错误,我修复了 iconv函数的问题,如下所示:

iconv('latin5', 'utf-8', $data['index']);

我也遇到过同样的问题,问题是我忘了在 xampp... : S 中启动 apache 和 mysql

我知道这已经是个老问题了,但我今天也犯了同样的错误。对我来说,设置模型上的连接变量起到了作用。

/**
* Table properties
*/
protected $connection = 'mysql-utf8';
protected $table = 'notification';
protected $primaryKey = 'id';

我不知道这个问题是否与数据库有关(可能) ,但是带有特殊字符(如 ~ 、 e 等)的文本字段都被搞乱了。

——编辑

$connect var 用于选择您的模型将要使用的 wichdb 连接。有时候,在 datase.php (在/config 文件夹下)中有多个连接,默认连接不使用 UTF-8字符集。

在任何情况下,一定要正确使用字符集和排序到您的连接。

'connections' => [


'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'your_database'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', 'database_password'),
'unix_socket' => env('DB_SOCKET', ''),
'prefix' => '',
'strict' => false,
'engine' => null
],


'mysql-utf8' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'your_database'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', 'database_password'),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
'engine' => null
],

为了更多的解决方案,我已经完成了(伟大的) Tiago Gouvêa 的解决方案之前只暴露了字符串和数组

我使用的是 md _ trans _ coding ()函数而不是 utf8 _ encode ()函数,它对我很有用: (12小时松动...)

//这个对象返回一个包含多个数组的大数组

$get_days = program::get_days($ARR, $client);

//和我使用这个函数很好地解析什么服务器返回 *

function convert_to_utf8_recursively($dat){
if( is_string($dat) ){
return mb_convert_encoding($dat, 'UTF-8', 'UTF-8');
}
elseif( is_array($dat) ){
$ret = [];
foreach($dat as $i => $d){
$ret[$i] = convert_to_utf8_recursively($d);
}
return $ret;
}
else{
return $dat;
}
}
                

// use
$data = convert_to_utf8_recursively($get_days);
  • 服务器返回的内容 * 因为我在两个不同的服务器上测试了相同的代码 第一个返回我一个格式良好的 json,没有任何功能,因为我们通常这样做,但第二个服务器不发送我回来什么,如果我不应用这个功能..。

将字符集设置为连接到 db 后的位置,如下所示

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}


if (!$conn->set_charset("utf8")) {
printf("Error loading character set utf8: %s\n", $conn->error);
exit();
} else {
printf("Current character set: %s\n", $conn->character_set_name());
}

正确指定邮件的.ENV 文件中的所有设置。

我为此浪费了6个小时

例子

MAIL_DRIVER=smtp
MAIL_MAILER=smtp
MAIL_HOST=smtp.yandex.ru
MAIL_PORT=465
MAIL_USERNAME=yourmail@yandex.ru
MAIL_PASSWORD=password //Create password for Apps in settings. NOT PASTE YOUR REAL MAIL PASSWORD
MAIL_ENCRYPTION=SSL
MAIL_FROM_ADDRESS=yourmail@yandex.ru
MAIL_FROM_NAME="${APP_NAME}"

当 Laravel 试图以 Json 格式返回一个错误(在开发 API 时)时,我就遇到了这种情况。在解决了 bug 之后,这个错误就消失了。

在 Laravel 7.x 中,这帮助我摆脱了这个错误。

$newString = mb_convert_encoding($arr, "UTF-8", "auto");
return response()->json($newString);

我也遇到过同样的问题。但是,在我的示例中,表中的列指定为 varchar (255) ,并且在执行插入时内容更大。因此,它用来截断部分,不能适应 varchar 列的大小。

为了解决这个问题,我将列类型更新为长文本,以便存储较大的文本。此外,还添加了一个前端验证,以确保文本不会大于列。(我用它来存储 js 转义的 HTML 草案)

在这里找到了答案。

解决方案在我的应用程序代码中,它与 Laravel 本身没有任何关系。

return mb_strtoupper(mb_substr($this->first_name, 0, 1) . mb_substr($this->last_name, 0, 1));

Https://barryvanveen.nl/blog/67-solving-malformed-utf-8-characters-possibly-incorrectly-encoded-error-in-laravel

对我来说,这种情况发生了两次:

  1. 我又忘记迁移了。我回滚(php artisan rollback)最新的迁移操作,因为我想要更改数据库模式上的某些内容,但是我忘记再次执行迁移命令: php artisan migrate

关于迁徙的更多信息: Https://laravel.com/docs/9.x/migrations

  1. 当 API 返回具有 blob类型属性(用 binary()方法创建的数据库上的列)的 JSON 响应时,这种情况也发生在我身上。对于我的用例,我通过将属性的名称添加到模型的数组属性 $hidden来隐藏该属性。之后就没问题了。

关于隐藏 JSON 属性的更多信息: Https://laravel.com/docs/9.x/eloquent-serialization#hiding-attributes-from-json

这是我的问题,我就是这样解决的,希望对别人有用。

确保文件的编码是 UTF-8,在 vscode 中是在右下部分。

Encoding position in vscode

当我修改一个已经存在于开发服务器中的文件时,我遇到了这个特殊的问题,当我在该服务器中编辑该文件时,不知怎么地,编码被更改为 ANSI,因此,也要确保您的文件在进行部署的服务器中以 UTF-8编码。

在我的例子中,错误类似于@dev1234在这里提到的(https://stackoverflow.com/a/71279140/7880201)作为建议答案的一部分。

但问题是幼虫输出包含 blob (s)的整个错误的结果。我建议你不要只返回错误信息的情况下

try {
} catch (\Throwable $th) {


// $code = $th->getCode();
$msg = $th->getMessage();
// dd($msg);
abort(404, 'THERE WAS AN ERROR: ' . $msg);


}

因此,要纠正这个问题,只需显示一个友好的小错误,即使您想要显示给自己作为一个开发人员。

检查所有的 blobs,以确保 laravel 不仅仅是从 ajax 响应中输出它们,这样就可以了。

我希望它今天能救你一命。如果没有,还是有好的答案可以试试的。 :)