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
相关产品推荐
相关产品推荐

