HTML 特殊字符和表情符号在 Laravel 网页上显示不正确

HTML Special Characters and Emojis Showing up Incorrectly on Laravel Webpage

我可能正在做一些愚蠢的事情,并且认为这会非常简单。我正在从外部 API 提取数据并通过 Eloquent 模型将其直接存储到数据库中 我是 creating/saving.

保存到数据库字段中的数据如下所示: I Can't Believe It's A - 该字段正在使用 utf8mb4_unicode_ci 排序规则。

我的网页有以下元数据:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

我通过我的 Laravel blade 模板显示它,如下所示:

<td>{{ $company->type->name }}</td>

我有点困惑我在这里做错了什么?从文档和其他 Whosebug 问题来看,我似乎做得对。我的 config/database.php 有以下内容:

        'mysql' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => 'InnoDB',
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],

我相信这一切都是正确的。我在这里缺少什么吗?切换到使用未转义的 {!! !!} 似乎导致内容仍然显示相同。我正在使用 Laravel v7.13.0

另外 Google Chrome 报告它是 UTF-8 呈现的:

> document.characterSet
"UTF-8"

编辑:

这是获取响应以及返回的 JSON 名称的示例:

>>> $response = Http::withOptions(
            [
                'verify' => false,
                'base_uri' => config('custom.torn_api_base'),
                'timeout' => 5.0
            ]
        )->get(
            "company/79831",
            [
                'selections' => 'profile',
                'key' => config('custom.torn_api_key')
            ]
        );
=> Illuminate\Http\Client\Response {#3393
     +"cookies": GuzzleHttp\Cookie\CookieJar {#3379},
     +"transferStats": GuzzleHttp\TransferStats {#3418},
   }

>>> $response->json()['company']['name'];
=> " Button Mashers™"

^ 你可以在上面看到他们的 API 给我提供了与他们网站上使用的 UTF-8 编码相同的字符串。

这是我创建模型并将其保存到数据库的过程:

            $company = Company::updateOrCreate(
                [
                    'id' => $tornPlayerData['job']['company_id']
                ],
                [
                    'name' => $tornPlayerData['job']['company_name'],
                    'player_id' => $this->player->id,
                    'isOwner' => true
                ]
            );

我也在记录回复,下面是带有表情符号的行之一:

Log::info("Updating company '{$company->name}'' now", ['company' => $company]);

laravel.log│[2020-06-22 00:43:52] staging.INFO: Updating company '&#128126; Button Mashers&#8482;'' now {"company":{"App\Company":{"id":79831,"name":"&#128126; Button Mashers&#8482;","player_id":2141091,"updated_at":"2020-06-22T04:43:52.000000Z","created_at":"2020-06-22T04:43:52.000000Z"}}}

编辑 2: 我只是手动将 Button Mashers™ 的 Tinker 输出复制并粘贴到关联数据库行中的 name。现在网站显示手动调整一个正确。所以看起来 Laravel 在存储数据时对来自 API 的数据做了一些奇怪的事情,我不确定为什么会这样。

编辑 3:

使用用户在回答中提出的 HEX 查询。

SELECT id,name,HEX(name) FROM `companies` WHERE id=60335

(60335, 'Pokey&#039;s Play House!', '506F6B657926233033393B7320506C617920486F75736521');

(60335, '&#039;', '26233033393B');

第二个结果是我将 Pokey&#039;s Play House! 修改为 &#039; 这样您就可以看到撇号的结果。

编辑 4:

blade 模板:

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Company Directory</title>

        <!-- Fonts -->
{{--        <link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">--}}

        <!-- Styles -->
          ** Snipped some minor CSS away from here **
        </style>
        <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.css">

        <!-- Scripts -->

        <script type="text/javascript" charset="utf8" src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
        <script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.js"></script>
        <script type="text/javascript" charset="utf8">
            **removed some datatables code from here for this paste**
        </script>

    </head>
    <body>
        <table id='directory-table' class='display'>
            <thead>
                <tr>
                    <th>Player Name</th>
                    <th>Company Name</th>
                    <th>Type</th>
                    <th>Rank</th>
                    <th>Positions</th>
                </tr>
            </thead>
            <tbody>
                @forelse ($companies as $company)
                    <tr>
                        <td>
                            <a href='https://www.example.
net/profiles.php?XID={{ $company->player->id }}'>
                                {{ $company->player->name }}
                            </a>
                        </td>
                        <td>
                            <a href='https://www.example.net/joblist.php#/p=corpinfo&userID={{ $company->id }}'>
                                {{ $company->name }}
                            </a>
                        </td>
                        <td>{{ $company->type->name }}</td> //THIS IS THE PROBLEM STRING HERE BEING OUTPUTTED
                        <td> {{ $company->rank }}</td>
                        <td> {{ $company->hired_employees }}/{{ $company->max_employees }}</td>
                    </tr>
                @empty
                    <tr>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td></td>
                    </tr>
                @endforelse
            </tbody>
        </table>
    </body>
</html>

"HTML 个实体"(例如 &#039;)对网页很有用,但不应该是将内容存储到数据库中的方式。

可能是你转了两次实体,一次是存储数据前,一次是展示在网页上。要进一步诊断问题,请获取字符串的 SELECT HEX(..) ...

在您的 blade 中,尝试使用以下语句进行打印:

{!! html_entity_decode($company->name) !!}

<?php echo $company->name; ?>

关于 printing data in blade 的官方文档。

我觉得是编码问题。

您需要打开 AppServiceProvider 并在 boot method 中添加以下代码:

Blade::setEchoFormat('e(utf8_encode(%s))');

希望这对你有用!!