Laravel“ latin1” DB的编码问题

时间:2019-01-31 15:09:09

标签: php mysql laravel utf-8

我有一个Laravel应用程序,可与字符集为'strict' => true的数据库一起使用(我无法更改它)。

在我的database.php中,我具有以下配置:

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';

但是,尽管我在Laravel中配置了字符集,但是在运行此代码时:

SELECT estado FROM clientes

我得到这个奇怪的结果:

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

我不明白为什么$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)); 的配置不起作用-有任何想法吗?

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

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

具有.env值:

CREATE DATABASE my_db CHARACTER SET latin1 COLLATE latin1_swedish_ci;

一切都按预期进行。

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

.env

让我大吃一惊的是,我设法正确地检索了值!

以防万一,我直接在MySql服务器中检查了

DB_CHARSET_INTRANET="latin1"
DB_COLLATION_INTRANET='latin1_swedish_ci'

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

1 个答案:

答案 0 :(得分:0)

mb_detect_encoding无法信任,它经常告诉某些内容在utf8中被编码。至少要使用第三个参数使其“严格”:http://php.net/manual/en/function.mb-detect-encoding.php

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

从您的php输出中,该字符串绝对以latin1编码。之所以看到“ Contrataci n”,是因为显示输出的程序(控制台?网页?日志查看器?)假设您的输出是UTF-8,不是,而是latin1。