Laravel BotMan报错Call to a member function reply() on null
错误原因
你遇到的Call to a member function reply() on null错误根源有两个:
- BotMan的
Conversation对话类不能随意手动new实例化后直接调用类内方法,这类对话类需要依赖BotMan核心实例绑定消息上下文才能正常使用say()、ask()这类消息发送方法,手动new出来的实例内部持有的Bot实例为null,调用say()时自然会触发调用null成员方法的报错。 - 你的现有代码存在循环依赖逻辑:
TestConversation构造函数调用CheckSaved::hasDate(),hasDate()又反过来实例化TestConversation,会造成无限递归实例化的问题。
修复方案
按照以下步骤调整代码即可解决问题:
- 剥离模型层的对话调用逻辑,模型只负责数据校验返回结果,不要在模型中实例化、调用对话类方法:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class CheckSaved extends Model { /** * 校验传入的预约日期是否有效 * @param mixed $scheduled_date * @return bool */ public function hasDate($scheduled_date):bool { return !empty($scheduled_date); } }
- 调整对话类逻辑,构造函数仅做参数赋值,所有业务逻辑、消息发送逻辑放到
run()方法中执行——run()是BotMan启动对话的标准入口,执行到该方法时对话所需的Bot实例、上下文依赖已经完成绑定,可以正常调用消息发送方法:
<?php namespace App\Conversations; use BotMan\BotMan\Messages\Conversations\Conversation; use App\Models\CheckSaved; class TestConversation extends Conversation { protected $scheduled_date; public $is_saved; public function __construct($scheduled_date) { // 构造函数只做参数挂载,不执行业务调用 $this->scheduled_date = $scheduled_date; } public function sayHi() { $this->say("<input type='datetime-local' id='birthdaytime' name='birthdaytime'>"); $this->say("<button class='btn-date' onclick='test()'>Save</button>"); } public function showOther() { $this->say('Hi'); } public function run() { // 所有业务判断放到run方法中执行,此时依赖已全部就绪 $checkDate = new CheckSaved(); $this->is_saved = $checkDate->hasDate($this->scheduled_date); if ($this->is_saved) { $this->showOther(); return; } $this->sayHi(); } }
- 启动对话时必须使用BotMan官方提供的
startConversation()方法启动,禁止手动实例化后直接调用类方法,启动示例:
// BotMan路由定义示例 $botman = app('botman'); $botman->hears('预约', function($bot) { // 传入构造参数,通过BotMan核心方法启动对话,自动完成上下文绑定 $bot->startConversation(new TestConversation(request()->get('scheduled_date'))); }); $botman->listen();
内容的提问来源于stack exchange,提问作者Zeeshan Haider
相关产品推荐
相关产品推荐

