首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >"latin1“DB的Laravel编码问题

"latin1“DB的Laravel编码问题
EN

Stack Overflow用户
提问于 2019-01-31 23:09:09
回答 1查看 1.9K关注 0票数 4

我有一个Laravel应用程序,它使用带字符集latin1的数据库(我不能更改它)。

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

代码语言:javascript
复制
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中,我使用以下配置:

代码语言:javascript
复制
'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'),
],

模型使用这个连接:

代码语言:javascript
复制
class Cliente extends Model
{
    protected $connection = 'mysqlIntranet';

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

代码语言:javascript
复制
+---------------+
| estado        |
+---------------+
| Informado     |
| Contratación  |

然而,尽管我在Laravel中配置了字符集,但当我运行以下代码时:

代码语言:javascript
复制
$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));

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

代码语言:javascript
复制
string(20) "Contrataci�n - UTF-8"
string(21) "Contratación - UTF-8"

我不明白为什么.env的配置不能完成这项工作--有什么想法吗?

======================更新======================

我试着在本地模拟这个问题,发现Laravel工作得很好。我创建了这个数据库:

代码语言:javascript
复制
CREATE DATABASE my_db CHARACTER SET latin1 COLLATE latin1_swedish_ci;

使用.env值:

代码语言:javascript
复制
DB_CHARSET_INTRANET="latin1"
DB_COLLATION_INTRANET='latin1_swedish_ci'

正如预期的那样,一切都运行良好。

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

代码语言:javascript
复制
DB_CHARSET_INTRANET="utf8"
DB_COLLATION_INTRANET='utf8_general_ci'

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

为了以防万一,我直接检查了MySql服务器:

代码语言:javascript
复制
> 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             |
+-------------+-------------------+--------------------+

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

EN

回答 1

Stack Overflow用户

发布于 2019-02-01 12:40:40

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

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

从你的php输出来看,这个字符串肯定是用latin1编码的。您看到"Contrataci�n“的原因是因为显示输出的程序(console?网页?日志查看器?)假设你的输出是UTF-8格式,但它不是,它是latin1。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54463558

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档