在 Laravel 8 中路由到控制器
Route to controller in Laravel 8
我正在使用 Laravel 8,当我像这样将路由写入 __invoke
控制器时:
use App\Http\Controllers\PortfolioController;
Route::get('/portfolio', 'PortfolioController')->name('portfolio');
显示此错误:
Invalid route action: [PortfolioController]. PortfolioController
is not invokable
所以它只能这样工作:
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 release note:
In Laravel 8.x, this property is null
by default. This means that no
automatic namespace prefixing will be done by Laravel. Therefore, in
new Laravel 8.x applications, controller route definitions should be
defined using standard PHP callable syntax:
use App\Http\Controllers\UserController;
Route::get('/users', [UserController::class, 'index']);
现在,对于您提到的特定情况,__invoke()
方法,您应该如何处理它们 according to the docs:
When registering routes for single action controllers, you do not need
to specify a method:
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')
我正在使用 Laravel 8,当我像这样将路由写入 __invoke
控制器时:
use App\Http\Controllers\PortfolioController;
Route::get('/portfolio', 'PortfolioController')->name('portfolio');
显示此错误:
Invalid route action: [PortfolioController].
PortfolioController
is not invokable
所以它只能这样工作:
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 release note:
In Laravel 8.x, this property is
null
by default. This means that no automatic namespace prefixing will be done by Laravel. Therefore, in new Laravel 8.x applications, controller route definitions should be defined using standard PHP callable syntax:use App\Http\Controllers\UserController; Route::get('/users', [UserController::class, 'index']);
现在,对于您提到的特定情况,__invoke()
方法,您应该如何处理它们 according to the docs:
When registering routes for single action controllers, you do not need to specify a method:
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')