Php “Laravel”编码问题;拉丁语1“;分贝

Php “Laravel”编码问题;拉丁语1“;分贝,php,mysql,laravel,utf-8,Php,Mysql,Laravel,Utf 8,我有一个Laravel应用程序,它与一个字符集为latin1的数据库一起工作(我无法更改它) 在my.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_COLLA

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

在my
.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'
'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'),
],
config/database.php
中,我使用以下配置:

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'
'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';
当我执行
从客户选择estado
(我从控制台工作)时,我得到以下结果:

+---------------+
| 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             |
+-------------+-------------------+--------------------+

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

mb\u detect\u编码不可信,它通常会告诉某些东西是用utf8编码的,而不是。至少使用第三个参数使其“严格”:

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


从php输出来看,字符串肯定是用拉丁语1编码的。你看《康塔西》的原因是什么�n“是因为显示您的输出的程序(控制台?网页?日志查看器?)假定您的输出是UTF-8格式,而不是,它是拉丁文1。

在哪里建立了数据库连接?是否检查了.env变量的应用是否正确?请检查config dir中的database.php。希望你能找到你需要的。@Blackam,我如何检查它?@unclexo,刚刚在问题中添加了相关信息,谢谢。你是否尝试清除配置缓存?顺便说一句,您可以通过回显config('database.connections.mysqlIntranet.collation')来检查env vars。谢谢,对错误检测的良好解释。尽管如此,我的问题是为什么Laravel DB引擎不能正确地从数据库中读取条目,尽管连接知道它是latin1。为什么你说它不能正确读取?在我看来,你的问题似乎是在展示方面。或者您想保持UTF-8作为页面编码,同时保持后端为latin1吗?我从DB读取数据,并将其作为json发送到另一个服务。为了调试信息,我使用调试消息到控制台,在那里我看到了问题。JSON规范要求您使用UTF-8。即使在PHP中,如果在传递给
json\u encode
函数的内容中包含非utf8字符串,它也会失败。因此,您有两个问题:您的控制台没有正确显示latin1,您的json接口将无法工作。为什么您不能在.env中将数据库连接编码更改为utf8?更改连接编码意味着数据库将转换存储编码中的数据。您的应用程序将使用utf8与数据库通信,而数据库内部将使用latin1进行存储。这样,您就不需要更改控制台中的任何设置,也不需要跳转来使用
json\u encode