【问题标题】:Laravel encoding problem with "latin1" DB“latin1”数据库的 Laravel 编码问题
【发布时间】:2019-06-25 02:09:14
【问题描述】:

我有一个 Laravel 应用程序,它与带有字符集 latin1 的数据库一起工作(我无法更改它)。

在我的.env 我有以下配置:

DB_CONNECTION_INTRANET=mysql
DB_HOST_INTRANET=xxxxx
DB_PORT_INTRANET=3306
DB_DATABASE_INTRANET=xxx
DB_USERNAME_INTRANET=xxx
DB_PASSWORD_INTRANET=xxx
DB_CHARSET_INTRANET='latin1'
DB_COLLATION_INTRANET='latin1_swedish_ci'

config/database.php我使用这个配置:

'mysqlIntranet' => [
    'driver'    => env('DB_CONNECTION_INTRANET'),
    'host'      => env('DB_HOST_INTRANET'),
    'port'      => env('DB_PORT_INTRANET'),
    'database'  => env('DB_DATABASE_INTRANET'),
    'username'  => env('DB_USERNAME_INTRANET'),
    'password'  => env('DB_PASSWORD_INTRANET'),
    'unix_socket' => env('DB_SOCKET_INTRANET', ''),
    'charset' => env('DB_CHARSET_INTRANET'),
    'collation' => env('DB_COLLATION_INTRANET'),
],

并且模型使用这个连接:

class Cliente extends Model
{
    protected $connection = 'mysqlIntranet';

当我执行SELECT estado FROM clientes(我从控制台工作)时,我得到以下结果:

+---------------+
| estado        |
+---------------+
| Informado     |
| Contratación  |

然而,虽然我在 Laravel 中配置了字符集,但当我运行这段代码时:

$client = Cliente::query()->first();
$estado = $client->getAttribute('estado');
var_dump($estado . " - " . mb_detect_encoding($estado));
$estado2 = utf8_encode($estado);
var_dump($estado2 . " - " . mb_detect_encoding($estado2));

我得到了这个奇怪的结果:

string(20) "Contrataci�n - UTF-8"
string(21) "Contratación - UTF-8"

我不明白为什么.env 的配置不起作用 - 有什么想法吗?

=======================更新======================
我尝试在本地模拟问题,发现 Laravel 工作正常。我创建了这个数据库:

CREATE DATABASE my_db CHARACTER SET latin1 COLLATE latin1_swedish_ci;

带有.env 值:

DB_CHARSET_INTRANET="latin1"
DB_COLLATION_INTRANET='latin1_swedish_ci'

一切正常,正如预期的那样。

我决定尝试在我的服务器中设置以下配置:

DB_CHARSET_INTRANET="utf8"
DB_COLLATION_INTRANET='utf8_general_ci'

令我大吃一惊的是,我成功地正确检索了这些值!

以防万一,我直接在MySql服务器中查看:

> SELECT * FROM information_schema.SCHEMATA  WHERE schema_name = "xxx";
+--------------+-------------+----------------------------+------------------------+----------+
| CATALOG_NAME | SCHEMA_NAME | DEFAULT_CHARACTER_SET_NAME | DEFAULT_COLLATION_NAME | SQL_PATH |
+--------------+-------------+----------------------------+------------------------+----------+
| NULL         | xxx         | latin1                     | latin1_swedish_ci      | NULL     |
+--------------+-------------+----------------------------+------------------------+----------+

> SELECT T.table_name, CCSA.* 
  FROM information_schema.`TABLES` T, information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA 
  WHERE CCSA.collation_name = T.table_collation AND T.table_schema = "xxx";
+-------------+-------------------+--------------------+
| table_name  | COLLATION_NAME    | CHARACTER_SET_NAME |
+-------------+-------------------+--------------------+
| clientes    | latin1_swedish_ci | latin1             |
| clientes_sm | latin1_swedish_ci | latin1             |
+-------------+-------------------+--------------------+

所以现在我有工作了,我只想了解为什么......

【问题讨论】:

  • 您的数据库连接在哪里建立?您是否检查过 .env 变量是否应用正确?
  • 查看配置目录中的 database.php。希望你能找到你需要的东西。
  • @Blackbam,如何查看?
  • @unclexo,刚刚在问题中添加了相关信息,谢谢。
  • 您是否尝试清除配置缓存?顺便说一句,您可以通过回显 config('database.connections.mysqlIntranet.collat​​ion') 来检查环境变量

标签: php mysql laravel utf-8


【解决方案1】:

mb_detect_encoding 不能被信任,它通常会告诉一些东西是不是用 utf8 编码的。至少使用第三个参数使其“严格”:http://php.net/manual/en/function.mb-detect-encoding.php

一种可以信任的方法是查看单个字节。如果ó被编码为单个字节,它可能是latin1,如果它是两个字节,它可能是utf8。 php 函数 bin2hex 将字符串转换为十六进制,它使您更容易检查它包含的字节。

从您的 php 输出中,该字符串肯定是用 latin1 编码的。您之所以看到“Contratacin”,是因为显示您的输出的程序(控制台?网页?日志查看器?)假设您的输出是 UTF-8 格式,但不是,它是 latin1。

【讨论】:

  • 谢谢,对错误检测的很好解释。尽管如此,我的问题是为什么 Laravel DB 引擎没有从数据库中正确读取条目虽然连接知道它是 latin1。
  • 为什么说它没有正确读取?对我来说,您的问题似乎出在显示器方面。或者你想保持 UTF-8 作为页面编码,同时保持后端为 latin1?
  • 我从数据库读取数据并将其作为 json 发送到另一个服务。为了调试信息,我使用调试消息来控制台,我看到了问题。
  • JSON 规范要求您使用 UTF-8。即使在 PHP 中,如果您在传递给 json_encode 函数的内容中包含非 utf8 字符串,它也会以 JSON_ERROR_UTF8 失败。所以你有两个问题:你的控制台没有正确显示latin1,你的json接口也不起作用
  • 为什么不能在.env 中将数据库连接编码更改为utf8?更改连接编码意味着数据库将从存储编码转换数据。您的应用程序将使用 utf8 与数据库通信,而在内部数据库将使用 latin1 进行存储。这样,您无需更改控制台中的任何设置,或跳过障碍即可使用json_encode
猜你喜欢
  • 2023-04-05
  • 1970-01-01
  • 2019-12-18
  • 2020-02-11
  • 1970-01-01
  • 2020-02-26
  • 2021-11-21
  • 1970-01-01
  • 2013-01-09
相关资源
最近更新 更多