thinkphp5的Illegal string offset 'id'错误

本文解析了ThinkPHP5中出现的Illegal string offset 'id'错误原因,指出该问题是由于在一个HTML页面中同时传递了两个同名数组(cateres)导致的。在控制器Base和Cate中分别定义了同名数组,使得系统无法确定在查找'id'时应使用哪个数组。

thinkphp5的Illegal string offset 'id'错误

问题

 

解答

数组同名了,一个html页面传进来两个cateres的数组,所以在找id的时候不知道找这两个里面的哪一个

第一个$cateres数组

报错这里的

这个$cateres写在了控制器Base里面,其它的控制器都要继承它 

 

第二个$cateres数组

这个$cateres写在了控制器Cate里面,加上继承的Base控制器里面的一个,所以有两个$cateres数组了。 

 

消息: 测试消息(主Topic: hello-unicast-dlq-no-partition)- 会触发死信 2025-10-15 11:35:38.531 WARN 25208 --- [nPool-worker-18] c.t.s.e.p.k.d.DLQEventHandlerWrapper : Event handle failed (attempt 1/3): [消费失败] 模拟业务异常 2025-10-15 11:35:38.533 INFO 25208 --- [nPool-worker-18] c.t.s.e.port.kafka.KafkaEventCenter : level=1, expirationTime=1760499339533 2025-10-15 11:35:38.537 INFO 25208 --- [nPool-worker-18] c.t.s.e.p.k.d.DLQEventHandlerWrapper : 事件延时 1000ms 后重试 消息: 测试消息(主Topic: hello-unicast-dlq-no-partition)- 会触发死信 2025-10-15 11:35:38.537 WARN 25208 --- [nPool-worker-18] c.t.s.e.p.k.d.DLQEventHandlerWrapper : Event handle failed (attempt 2/3): [消费失败] 模拟业务异常 2025-10-15 11:35:38.537 INFO 25208 --- [nPool-worker-18] c.t.s.e.port.kafka.KafkaEventCenter : level=2, expirationTime=1760499343537 2025-10-15 11:35:38.540 INFO 25208 --- [nPool-worker-18] c.t.s.e.p.k.d.DLQEventHandlerWrapper : 事件延时 5000ms 后重试 消息: 测试消息(主Topic: hello-unicast-dlq-no-partition)- 会触发死信 2025-10-15 11:35:38.540 WARN 25208 --- [nPool-worker-18] c.t.s.e.p.k.d.DLQEventHandlerWrapper : Event handle failed (attempt 3/3): [消费失败] 模拟业务异常 2025-10-15 11:35:38.541 ERROR 25208 --- [nPool-worker-18] c.t.s.e.p.k.d.DLQEventHandlerWrapper : Event failed after 3 retries, sent to DLQ 2025-10-15 11:35:38.544 INFO 25208 --- [r_group_level_2] c.t.s.e.p.k.c.GenericKafkaConsumerTask : 实际暂停成功,topic: delay_topic_level_2 2025-10-15 11:35:38.544 INFO 25208 --- [r_group_level_1] c.t.s.e.p.k.c.GenericKafkaConsumerTask : 实际暂停成功,topic: delay_topic_level_1 2025-10-15 11:35:38.544 INFO 25208 --- [nPool-worker-18] c.t.s.e.port.kafka.KafkaEventCenter : 暂停成功,topic: delay_topic_level_2 2025-10-15 11:35:38.544 INFO 25208 --- [nPool-worker-22] c.t.s.e.port.kafka.KafkaEventCenter : 暂停成功,topic: delay_topic_level_1 2025-10-15 11:35:38.544 INFO 25208 --- [nPool-worker-18] c.t.s.e.port.kafka.delay.DelayHandler : 暂停目标topic:delay_topic_level_2 2025-10-15 11:35:38.544 INFO 25208 --- [nPool-worker-22] c.t.s.e.port.kafka.delay.DelayHandler : 暂停目标topic:delay_topic_level_1 2025-10-15 11:35:38.544 INFO 25208 --- [ad | producer-1] c.t.s.e.p.k.d.DLQEventHandlerWrapper : 发送至死信队列!原始事件: {"filterKey":"key","timeStamp":1760499338540,"message":"测试消息(主Topic: hello-unicast-dlq-no-partition)- 会触发死信","retryCount":3},时间戳:1760499338541,主题: hello-unicast-dlq-no-partition_dlq_topic, 分区: 0, 已重试次数: 3,最后一次异常信息:[消费失败] 模拟业务异常 [死信捕获] 死信Topic: hello-unicast-dlq-no-partition_dlq_topic, 消息: 测试消息(主Topic: hello-unicast-dlq-no-partition)- 会触发死信 2025-10-15 11:35:39.550 INFO 25208 --- [pool-2-thread-1] c.t.s.e.port.kafka.delay.DelayHandler : 延迟任务执行:targetTopic=delay_topic_level_1, currentTime=1760499339550 2025-10-15 11:35:40.052 INFO 25208 --- [r_group_level_1] c.t.s.e.p.k.c.GenericKafkaConsumerTask : 实际恢复成功,topic: delay_topic_level_1 2025-10-15 11:35:40.052 INFO 25208 --- [pool-2-thread-1] c.t.s.e.port.kafka.KafkaEventCenter : 恢复成功,topic: delay_topic_level_1 2025-10-15 11:35:40.052 INFO 25208 --- [pool-2-thread-1] c.t.s.e.port.kafka.delay.DelayHandler : 恢复目标topic消费:delay_topic_level_1 2025-10-15 11:35:40.053 INFO 25208 --- [pool-2-thread-1] c.t.s.e.port.kafka.KafkaEventCenter : 延迟事件已转发,targetTopic: hello-unicast-dlq-no-partition 消息: 测试消息(主Topic: hello-unicast-dlq-no-partition)- 会触发死信 2025-10-15 11:35:40.072 WARN 25208 --- [nPool-worker-18] c.t.s.e.p.k.d.DLQEventHandlerWrapper : Event handle failed (attempt 2/3): [消费失败] 模拟业务异常 2025-10-15 11:35:40.072 INFO 25208 --- [nPool-worker-18] c.t.s.e.port.kafka.KafkaEventCenter : level=2, expirationTime=1760499345072 2025-10-15 11:35:40.073 INFO 25208 --- [nPool-worker-18] c.t.s.e.p.k.d.DLQEventHandlerWrapper : 事件延时 5000ms 后重试 消息: 测试消息(主Topic: hello-unicast-dlq-no-partition)- 会触发死信 2025-10-15 11:35:40.073 WARN 25208 --- [nPool-worker-18] c.t.s.e.p.k.d.DLQEventHandlerWrapper : Event handle failed (attempt 3/3): [消费失败] 模拟业务异常 2025-10-15 11:35:40.073 ERROR 25208 --- [nPool-worker-18] c.t.s.e.p.k.d.DLQEventHandlerWrapper : Event failed after 3 retries, sent to DLQ 2025-10-15 11:35:40.076 INFO 25208 --- [ad | producer-1] c.t.s.e.p.k.d.DLQEventHandlerWrapper : 发送至死信队列!原始事件: {"filterKey":"key","timeStamp":1760499340073,"message":"测试消息(主Topic: hello-unicast-dlq-no-partition)- 会触发死信","retryCount":3},时间戳:1760499340073,主题: hello-unicast-dlq-no-partition_dlq_topic, 分区: 0, 已重试次数: 3,最后一次异常信息:[消费失败] 模拟业务异常 [死信捕获] 死信Topic: hello-unicast-dlq-no-partition_dlq_topic, 消息: 测试消息(主Topic: hello-unicast-dlq-no-partition)- 会触发死信 2025-10-15 11:35:43.550 INFO 25208 --- [pool-5-thread-1] c.t.s.e.port.kafka.delay.DelayHandler : 延迟任务执行:targetTopic=delay_topic_level_2, currentTime=1760499343550 2025-10-15 11:35:43.627 INFO 25208 --- [r_group_level_2] c.t.s.e.p.k.c.GenericKafkaConsumerTask : 实际恢复成功,topic: delay_topic_level_2 2025-10-15 11:35:43.627 INFO 25208 --- [pool-5-thread-1] c.t.s.e.port.kafka.KafkaEventCenter : 恢复成功,topic: delay_topic_level_2 2025-10-15 11:35:43.627 INFO 25208 --- [pool-5-thread-1] c.t.s.e.port.kafka.delay.DelayHandler : 恢复目标topic消费:delay_topic_level_2 2025-10-15 11:35:43.630 INFO 25208 --- [pool-5-thread-1] c.t.s.e.port.kafka.KafkaEventCenter : 延迟事件已转发,targetTopic: hello-unicast-dlq-no-partition 消息: 测试消息(主Topic: hello-unicast-dlq-no-partition)- 会触发死信 2025-10-15 11:35:43.635 WARN 25208 --- [nPool-worker-18] c.t.s.e.p.k.d.DLQEventHandlerWrapper : Event handle failed (attempt 3/3): [消费失败] 模拟业务异常 2025-10-15 11:35:43.635 ERROR 25208 --- [nPool-worker-18] c.t.s.e.p.k.d.DLQEventHandlerWrapper : Event failed after 3 retries, sent to DLQ 2025-10-15 11:35:43.636 INFO 25208 --- [r_group_level_2] c.t.s.e.p.k.c.GenericKafkaConsumerTask : 实际暂停成功,topic: delay_topic_level_2 2025-10-15 11:35:43.636 INFO 25208 --- [nPool-worker-22] c.t.s.e.port.kafka.KafkaEventCenter : 暂停成功,topic: delay_topic_level_2 2025-10-15 11:35:43.636 INFO 25208 --- [nPool-worker-22] c.t.s.e.port.kafka.delay.DelayHandler : 暂停目标topic:delay_topic_level_2 2025-10-15 11:35:43.644 INFO 25208 --- [ad | producer-1] c.t.s.e.p.k.d.DLQEventHandlerWrapper : 发送至死信队列!原始事件: {"filterKey":"key","timeStamp":1760499343635,"message":"测试消息(主Topic: hello-unicast-dlq-no-partition)- 会触发死信","retryCount":3},时间戳:1760499343635,主题: hello-unicast-dlq-no-partition_dlq_topic, 分区: 0, 已重试次数: 3,最后一次异常信息:[消费失败] 模拟业务异常 [死信捕获] 死信Topic: hello-unicast-dlq-no-partition_dlq_topic, 消息: 测试消息(主Topic: hello-unicast-dlq-no-partition)- 会触发死信 2025-10-15 11:35:45.079 INFO 25208 --- [pool-5-thread-1] c.t.s.e.port.kafka.delay.DelayHandler : 延迟任务执行:targetTopic=delay_topic_level_2, currentTime=1760499345079 2025-10-15 11:35:45.172 INFO 25208 --- [r_group_level_2] c.t.s.e.p.k.c.GenericKafkaConsumerTask : 实际恢复成功,topic: delay_topic_level_2 2025-10-15 11:35:45.172 INFO 25208 --- [pool-5-thread-1] c.t.s.e.port.kafka.KafkaEventCenter : 恢复成功,topic: delay_topic_level_2 2025-10-15 11:35:45.173 INFO 25208 --- [pool-5-thread-1] c.t.s.e.port.kafka.delay.DelayHandler : 恢复目标topic消费:delay_topic_level_2 2025-10-15 11:35:45.174 INFO 25208 --- [pool-5-thread-1] c.t.s.e.port.kafka.KafkaEventCenter : 延迟事件已转发,targetTopic: hello-unicast-dlq-no-partition 消息: 测试消息(主Topic: hello-unicast-dlq-no-partition)- 会触发死信 2025-10-15 11:35:45.192 WARN 25208 --- [nPool-worker-22] c.t.s.e.p.k.d.DLQEventHandlerWrapper : Event handle failed (attempt 3/3): [消费失败] 模拟业务异常 2025-10-15 11:35:45.193 ERROR 25208 --- [nPool-worker-22] c.t.s.e.p.k.d.DLQEventHandlerWrapper : Event failed after 3 retries, sent to DLQ 2025-10-15 11:35:45.206 INFO 25208 --- [ad | producer-1] c.t.s.e.p.k.d.DLQEventHandlerWrapper : 发送至死信队列!原始事件: {"filterKey":"key","timeStamp":1760499345192,"message":"测试消息(主Topic: hello-unicast-dlq-no-partition)- 会触发死信","retryCount":3},时间戳:1760499345193,主题: hello-unicast-dlq-no-partition_dlq_topic, 分区: 0, 已重试次数: 3,最后一次异常信息:[消费失败] 模拟业务异常 [死信捕获] 死信Topic: hello-unicast-dlq-no-partition_dlq_topic, 消息: 测试消息(主Topic: hello-unicast-dlq-no-partition)- 会触发死信@Slf4j @RequiredArgsConstructor public class DLQEventHandlerWrapper implements EventHandler { // 原事件处理器 private final EventHandler delegate; // DLQ配置 private final DLQConfig dlqConfig; // 事件中心(用于发送死信) private final String mainTopic; // 当前主Topic private final KafkaEventCenter eventCenter; private String lastException; /** * 处理事件,包含重试与死信发送逻辑。 * <p>核心逻辑: * 1. 若DLQ未启用,直接调用原始处理器; * 2. 若启用,按配置重试处理事件; * 3. 重试耗尽后发送事件到DLQ。 * * @param event 待处理的事件 */ @Override public void handleEvent(Event event) { if (!dlqConfig.isEnabled()) { delegate.handleEvent(event); // 未启用DLQ,直接执行原逻辑 return; } int retryCount = event.getRetryCount(); boolean success = false; while (retryCount < dlqConfig.getMaxRetries()) { try { delegate.handleEvent(event); // 执行原事件处理 success = true; break; } catch (Exception e) { retryCount++; event.setRetryCount(retryCount); log.warn("Event handle failed (attempt {}/{}): {}", retryCount, dlqConfig.getMaxRetries(), e.getMessage()); lastException=e.getMessage(); if (retryCount >= dlqConfig.getMaxRetries()) { // 达到最大重试次数,发送死信 break; } // 计算重试延时 long delay = dlqConfig.getRetryStrategy().getNextDelay(retryCount); eventCenter.sendDelay(mainTopic,event,delay,new FlexibleMatchStrategy( DelayQueueStrategy.ApproximationMode.UP)); sendDelay(event,delay); } } if (!success) { String dlqTopic = mainTopic + "_dlq_topic"; sendToDLQ(event, retryCount,lastException,dlqTopic); log.error("Event failed after {} retries, sent to DLQ" , dlqConfig.getMaxRetries()); } } /** * 将事件发送至死信队列 */ private void sendToDLQ(Event event,int retryCount,String lastException,String dlqTopic) { // 构造自定义EventFuture回调,捕获发送结果 EventFuture dlqEventFuture = new EventFuture() { @Override public void onSuccess(EventCenterSendResult result) { log.info("发送至死信队列!原始事件: {},时间戳:{},主题: {}, 分区: {}, 已重试次数: {},最后一次异常信息:{}", event.toString(),result.getTimestamp(),result.getTopic(), result.getPartition(), retryCount, lastException); } @Override public void onFailure(Throwable throwable) { // 关键:记录重试次数和发送异常 log.error("死信消息发送失败!原始事件: {}, 已重试次数: {}, 异常信息: {}", event.toString(), retryCount, throwable.getMessage(), throwable); } }; try { // 调用带回调的send方法(匹配参数:topic, event, eventFuture) eventCenter.send(dlqTopic, event, dlqEventFuture); } catch (Exception e) { // 处理send方法本身的异常(如参数错误) log.error("调用死信发送方法时发生异常,已重试次数: {}", retryCount, e); } } private void sendDelay(Event event, long delay) { log.info("事件延时 {}ms 后重试", delay); // TODO: 实际延时队列实现 } }@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class}) @ComponentScan(basePackages = { "com.tplink.nbu.demo.basicspringboot", "com.tplink.smb.eventcenter.port.kafka.deadletter", "com.tplink.smb.eventcenter.api.config" }) public class DelayDeadTest implements CommandLineRunner { @Autowired private KafkaEventCenter eventCenter; @Autowired private DLQConfig deadLetterConfig; // 所有测试主Topic(对应同重载方法) String mainTopic = "hello-unicast-dlq-no-partition"; // registerUnicast(DLQ, 无Partition) public static void main(String[] args) { SpringApplication.run(DelayDeadTest.class, args); } @Override public void run(String... args) throws Exception { eventCenter.registerDelayConsumer(); registerDLQConsumers(); // 注册所有带死信的消费者(模拟失败) registerDLQListeners(); // 注册所有死信Topic的监听 sendTestMessagesToAllTopics();// 发送测试消息触发死信 } /** * 注册所有带死信的消费者 */ private void registerDLQConsumers() { // 模拟消费失败的Handler(所有测试共用) EventHandler failingHandler = event -> { System.out.println(" 消息: " + event.getMessage()); throw new RuntimeException("[消费失败] 模拟业务异常 "); }; // -------------------------- 1. registerUnicast(DLQ, 无PartitionAssignorMode) -------------------------- eventCenter.registerUnicast( mainTopic, // 主Topic "group-unicast-dlq-no-part", // 消费者组(手动指定) failingHandler, ForkJoinPool.commonPool(), // 线程池 deadLetterConfig // 死信配置 ); } /** * 注册所有死信Topic的监听(死信Topic规则:主Topic + "_dlq_topic") */ private void registerDLQListeners() { String dlqTopic = mainTopic + "_dlq_topic"; // 死信Topic(与业务代码规则一致) eventCenter.registerUnicast( dlqTopic, "dlq-group-" + mainTopic, // 死信消费者组(唯一即可) event -> System.out.println("[死信捕获] 死信Topic: " + dlqTopic + ", 消息: " + event.getMessage()), ForkJoinPool.commonPool() ); } /** * 给所有主Topic发送测试消息(触发消费失败) */ private void sendTestMessagesToAllTopics() { Event event = new Event( "key", "测试消息(主Topic: " + mainTopic + ")- 会触发死信" ); eventCenter.send(mainTopic, event); System.out.println("[消息发送] 主Topic: " + mainTopic + ", 内容: " + event.getMessage()); } }请分析并解决,为什么只发送了一条消息,但死信队列中出现只一条消息
10-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值