必须用php-amqplib且消息体需json_encode()后显式设content_type='application/json'和delivery_mode=>2,否则json会变乱码或重启丢消息;因amqp只传字节流,php数组会转成"array"字符串,未编码数据导致消费者json_decode()失败;delivery_mode=>2确保消息持久化,队列也须声明持久,否则rabbitmq重启即清空;消费者须校验json_last_error()并安全解码,content_type是决定是否json解析的关键依据。

必须用 php-amqplib,且消息体要 json_encode() 后显式设 content_type 和 delivery_mode => 2,否则 JSON 可能被当乱码或重启即丢。
为什么不能直接传 PHP 数组或裸字符串
AMQP 协议不理解 PHP 类型,AMQPMessage 构造函数接收的是原始字节流。如果你传一个数组:new AMQPMessage($task),它会调用 (string) $task,结果是 "Array";如果传未编码的关联数组,json_encode() 缺失会导致消费者收到无法 json_decode() 的数据。
常见错误现象:json_decode($msg->body, true) === null,但 json_last_error() 返回 JSON_ERROR_SYNTAX——实际是消息体根本不是合法 JSON 字符串。
- 始终先
json_encode($data),再传给AMQPMessage - 必须设置
'content_type' => 'application/json',方便消费者识别格式 - 避免使用
serialize()或base64_encode()包装,跨语言兼容性差
delivery_mode => 2 不设等于白发
默认 delivery_mode 是 1(非持久),消息只存在内存里。RabbitMQ 进程重启、服务器断电,所有未消费消息立刻清空——这对订单、支付、通知类业务是灾难性的。
基于三引擎设计,从微信文章、新闻和博客网页提取干净内容,支持标题作者日期元数据,多格式和批量处理。
正确写法必须显式声明:
$body = json_encode(['order_id' => 123, 'status' => 'paid']);
$message = new AMQPMessage($body, [
'delivery_mode' => 2,
'content_type' => 'application/json',
]);
$channel->basic_publish($message, '', 'payment_queue');
-
delivery_mode => 2是硬性要求,不能依赖队列或交换机的持久化来弥补 - 对应队列也得声明为持久:
$channel->queue_declare('payment_queue', false, true, false, false)(第三个参数true) - 若用了自定义交换机,同样要加
durable => true参数
消费者端解码 JSON 的安全边界
消费者拿到 $msg->body 后不能直接 json_decode() 就用,必须校验返回值和错误码。
典型隐患:生产者发了 malformed JSON(比如中文没转义、嵌套过深),或中间被截断,json_decode() 返回 null 但没检查,后续代码直接访问字段就报 Notice: Trying to access array offset on value of type null。
- 务必检查
json_last_error() === JSON_ERROR_NONE - 推荐封装一个安全解码函数:
safeJsonDecode(string $json): ?array - 对关键字段(如
order_id)做类型和存在性断言,别信“上游一定发对了” - 日志中记录原始
$msg->body(截断前 200 字符即可),便于排查格式问题
最易被忽略的一点:content_type 不只是“文档规范”,它是消费者决定是否走 JSON 解码路径的第一依据。如果生产者漏设,而消费者又盲目 json_decode(),就会把纯文本或二进制内容当成 JSON 解析,出错无声无息。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










