在 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')