Laravel多方法控制器需__invoke()?报错原因及解决方法
Laravel路由报错:控制器非可调用的原因与修复
问题场景
报错信息:
UnexpectedValueException Invalid route action: [App\Http\Controllers\LoginController]. at vendor\laravel\framework\src\Illuminate\Routing\RouteAction.php:92 88▕ */ 89▕ protected static function makeInvokable($action) 90▕ { 91▕ if (! method_exists($action, '__invoke')) { ➜ 92▕ throw new UnexpectedValueException("Invalid route action: [{$action}]."); 93▕ } 94▕ 95▕ return $action.'@__invoke'; 96▕ } i `App\Http\Controllers\LoginController` is not invokable: The controller class `App\Http\Controllers\LoginController` is not invokable. Did you forget to add the `__invoke` method or is the controller's method missing in your routes file? 1 vendor\laravel\framework\src\Illuminate\Routing\RouteAction.php:47 Illuminate\Routing\RouteAction::makeInvokable("App\Http\Controllers\LoginController") 2 vendor\laravel\framework\src\Illuminate\Routing\Route.php:191 Illuminate\Routing\RouteAction::parse("login", ["App\Http\Controllers\LoginController", "App\Http\Controllers\LoginController"])
当前路由配置(web.php):
use App\Http\Controllers\HomeController; use App\Http\Controllers\LoginController; use App\Http\Controllers\RegisterController; use Illuminate\Support\Facades\Route; Route::get('/', HomeController::class, 'home')->name('home'); Route::get('/login', LoginController::class, 'login')->name('login'); Route::get('/register', RegisterController::class, 'register')->name('register');
控制器示例(LoginController):
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class LoginController extends Controller { public function login() { return view('home'); } }
报错原因
路由写法不符合Laravel规则:
Route::get()方法参数格式错误,你将控制器类名和方法名作为两个独立参数传递(第二个参数是控制器类名,第三个是方法名)。- Laravel会把第二个参数的类名识别为单动作控制器(仅处理一个动作的控制器,必须实现
__invoke()方法),但你的控制器是多方法结构,没有__invoke()方法,因此触发报错。
修复方法
需要将控制器和方法合并为一个参数传递,两种正确写法如下:
写法1:数组格式(Laravel 8+推荐写法)
use App\Http\Controllers\HomeController; use App\Http\Controllers\LoginController; use App\Http\Controllers\RegisterController; use Illuminate\Support\Facades\Route; Route::get('/', [HomeController::class, 'home'])->name('home'); Route::get('/login', [LoginController::class, 'login'])->name('login'); Route::get('/register', [RegisterController::class, 'register'])->name('register');
写法2:字符串@符号格式
use Illuminate\Support\Facades\Route; Route::get('/', 'App\Http\Controllers\HomeController@home')->name('home'); Route::get('/login', 'App\Http\Controllers\LoginController@login')->name('login'); Route::get('/register', 'App\Http\Controllers\RegisterController@register')->name('register');
这两种写法都会明确告知Laravel调用指定控制器下的对应方法,而非将控制器视为单动作控制器。
内容的提问来源于stack exchange,提问作者lolich
相关产品推荐
相关产品推荐

