You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中pusher-php-server推送Unicode而非西里尔字符问题求助

问题描述

我有一个带实时聊天功能的Laravel API项目,使用的依赖如下:

"beyondcode/laravel-websockets": "^1.13",
"pusher/pusher-php-server": "7.0"

定义了如下MessagePushNotification事件:

<?php

namespace App\Events;

use App\Http\Resources\Messenger\WebsocketResource;
use App\Models\Messages;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;

class MessagePushNotification implements ShouldBroadcast
{
    use Dispatchable;
    use InteractsWithSockets;
    use SerializesModels;

    public $user;
    public Messages $message;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct(Messages $message, $user)
    {
        $this->message = $message;
        $this->user = $user;
    }

    public function broadcastWith(): array
    {
        return (new WebsocketResource($this->message))->toArray(request());
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return Channel|array
     */
    public function broadcastOn(): Channel|array
    {
        Log::channel('websockets')->debug('Broadcasting event: MyWebSocketEvent', [
            'payload' => $this->message
        ]);

        return new Channel('chatMessage');
    }

    public function broadcastAs(): string
    {
        return 'chatMessage';
    }
}

以及对应的WebsocketResource资源:

<?php

namespace App\Http\Resources\Messenger;

use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\Log;

class WebsocketResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param \Illuminate\Http\Request $request
     * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
     */
    public function toArray($request): array|\JsonSerializable|Arrayable
    {
        $message = $this->text;
        $senderId = $this->sender_id;
        $createdAt = $this->created_at->toDateTimeString();

        Log::info('WebsocketResource', [
            'message' => $message,
            'sender_id' => $senderId,
            'message_created_at' => $createdAt,
        ]);

        return [
            'message' => $message,
            'sender_id' => $senderId,
            'message_created_at' => $createdAt,
        ];
    }
}

通过REST接口创建消息后,Message观察者会触发上述事件。WebSocket通道返回的响应中,拉丁字符显示正常,但西里尔字符会被转为Unicode编码(如\u041f\u0440\u0438\u0432\u0435\u0442)。Resource中的日志显示消息内容正常,已排除数据库配置问题,需要解决该问题使响应正常显示西里尔字符。

解决方案

该问题源于Pusher PHP SDK默认对非ASCII字符进行Unicode转义编码,以下是三种可行的解决方法:

方法1:修改broadcastWith方法手动处理编码

在MessagePushNotification事件的broadcastWith方法中,先将Resource返回的数据转为JSON字符串(禁用Unicode转义),再解码为数组,绕过Pusher的自动转义:

public function broadcastWith(): array
{
    $resourceData = (new WebsocketResource($this->message))->toArray(request());
    return json_decode(json_encode($resourceData, JSON_UNESCAPED_UNICODE), true);
}

方法2:配置Pusher客户端禁用转义

在Laravel的广播配置文件config/broadcasting.php中,为Pusher添加json_options配置项,指定禁用Unicode转义:

'pusher' => [
    'driver' => 'pusher',
    'key' => env('PUSHER_APP_KEY'),
    'secret' => env('PUSHER_APP_SECRET'),
    'app_id' => env('PUSHER_APP_ID'),
    'options' => [
        'cluster' => env('PUSHER_APP_CLUSTER'),
        'useTLS' => true,
        'host' => '127.0.0.1',
        'port' => 6001,
        'scheme' => 'http',
        // 添加此行禁用Unicode转义
        'json_options' => JSON_UNESCAPED_UNICODE,
    ],
],

方法3:重写事件的序列化逻辑

如果前两种方法无效,可重写事件的serialize方法,自定义序列化过程:

use Illuminate\Contracts\Queue\SerializesModels;

class MessagePushNotification implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    // 现有代码...

    /**
     * Serialize the event for broadcasting.
     *
     * @return array
     */
    public function serialize()
    {
        $data = $this->broadcastWith();
        return json_decode(json_encode($data, JSON_UNESCAPED_UNICODE), true);
    }
}
验证

修改完成后,重新触发消息创建事件,检查WebSocket响应中的西里尔字符是否直接显示为原始字符(如Привет),而非Unicode转义编码。

内容的提问来源于stack exchange,提问作者Dav Us

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 07:15:04