Laravel5.8构造方法内$request->route()返回null报错问题
问题产生原因
核心原因是Laravel 5.8的控制器实例化时机和路由参数绑定时机不匹配:
- 执行
php artisan route:list时,框架需要遍历所有注册路由,实例化绑定的控制器来解析路由元信息,这个过程没有走完整的HTTP请求路由匹配流程,注入到控制器构造函数的Request对象上没有挂载匹配到的路由实例,$request->route()必然返回null。 - 就算是正常的HTTP请求,也不应该在控制器构造函数里直接读取路由参数:控制器构造函数执行时,路由还没完成最终的参数解析绑定,这时候取路由参数本来就拿不到有效值。把依赖路由参数的服务初始化逻辑写在构造函数里,本身就不符合Laravel的生命周期流程。
正确改法
两种方案都能解决问题:
- 最直接的:把
$oauthService的初始化逻辑挪到每个具体的控制器方法里,这时候路由已经匹配完成,$request->route()->parameter('provider')可以正常拿到值。 - 如果不想在每个方法里重复写初始化逻辑,就在控制器构造函数里用闭包中间件包裹相关逻辑,中间件会在路由匹配完成后才执行,不会提前触发报错,示例代码:
class TotersProviderLoginController extends Controller { private $oauthService; public function __construct() { // 不要在构造函数里直接注入Request读路由参数,放到中间件逻辑里 $this->middleware(function ($request, $next) { $provider = $request->route()->parameter('provider'); if($provider == 'google'){ $this->oauthService = new GoogleOauthService(); } else { throw new \Exception('Provider '.($provider ?? '').' not supported!'); } return $next($request); }); } // 后续控制器方法保持原有逻辑即可 }
这种写法下执行route:list时,框架只会实例化控制器、注册中间件,不会执行中间件内部的逻辑,自然不会触发报错。
问题复现素材
- 原控制器代码:
class TotersProviderLoginController extends Controller { private $oauthService; public function __construct(Request $request) { $provider = $request->route()->parameter('provider'); // 报错位置 if($provider == 'google') $this->oauthService = new GoogleOauthService(); else throw new \Exception('Provider '.($provider ?? '').' not supported!'); } }
- 原路由规则:
Route::get('login/toters/{provider}', 'Accounts\TotersProviderLoginController@redirectToProvider'); Route::get('login/toters/{provider}/redirect', 'Accounts\TotersProviderLoginController@handleProviderCallback'); Route::get('login/toters/{provider}/csrf', 'Accounts\TotersProviderLoginController@getCsrf'); Route::post('login/toters/{provider}/oauth', 'Accounts\TotersProviderLoginController@requestToken');
- 触发报错的命令:
php artisan route:list --verbose
- 报错信息:
In TotersProviderLoginController.php line 38: [Symfony\Component\Debug\Exception\FatalThrowableError] Call to a member function parameter() on null
内容的提问来源于stack exchange,提问作者abbood
相关产品推荐
相关产品推荐

