问题描述
我正在使用Laravel 8,当我将路由写入 __ invoke 控制器时,如下所示:
use App\Http\Controllers\PortfolioController;
Route::get('/portfolio','PortfolioController')->name('portfolio');
它显示此错误: 无效的路由操作:[PortfolioController]。 PortfolioController
无法使用。
所以它只能这样工作:
Route::get('/portfolio',[PortfolioController::class,'__invoke'])->name('portfolio');;
这对我没有意义,因为它应该找到 __ invoke ,这是 PortfolioController.php
中唯一的一个namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PortfolioController extends Controller
{
/**
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function __invoke(Request $request)
{
$portfolio = [
['title' => 'Project #1'],['title' => 'Project #2'],['title' => 'Project #3'],['title' => 'Project #4']
];
return view('portfolio',compact('portfolio'));
}
}
Laravel 8是否忽略了__invoke属性?
解决方法
TL; DR
这样做:
use App\Http\Controllers\PortfolioController;
Route::get('/portfolio',PortfolioController::class)->name('portfolio');
^^^^^^^^^^^^^^^^^^^^^^^^^^
说明
在Laravel 8之前,路由已在RouteServiceProvider.php
中命名:
protected $namespace = 'App\Http\Controllers';
// ...
protected function mapWebRoutes()
{
Route::middleware('web')
->namespace($this->namespace) // <----
->group(base_path('routes/web.php'));
}
因此,当您定义路线时,例如您的示例:
Route::get('/portfolio','PortfolioController')->name('portfolio');
^^^^^^^^^^^^^^^^^^^^^
PortfolioController
字符串用App\Http\Controllers
命名空间。
现在,在Laravel 8中,此行为已被修改。来自v8 relase note:
在Laravel 8.x中,此属性默认为null。这意味着没有 自动命名空间前缀将由Laravel完成。因此,在 新的Laravel 8.x应用程序,控制器路由定义应为 使用标准PHP可调用语法定义:
use App\Http\Controllers\UserController; Route::get('/users',[UserController::class,'index']);
现在,对于您提到的特殊情况,__invoke()
方法,这就是您应该如何处理它们的方法according to the docs:
,为单个动作控制器注册路由时,不需要 指定方法:
use App\Http\Controllers\ShowProfile; Route::get('user/{id}',ShowProfile::class);
另一种用法,您可以使用完整路径
Route::get('/portfolio','App\Http\Controllers\PortfolioController')->name('portfolio');
或调用特定方法
Route::get('/portfolio','App\Http\Controllers\PortfolioController@foo')->name('portfolio')