在 Laravel 8 中路由到控制器

Jot*_*ota 6 php laravel laravel-routing laravel-controller laravel-8

我正在使用 Laravel 8,当我__invoke像这样编写控制器的路由时:

use App\Http\Controllers\PortfolioController;

Route::get('/portfolio', 'PortfolioController')->name('portfolio');
Run Code Online (Sandbox Code Playgroud)

它显示此错误:

无效的路由操作:[PortfolioController]。PortfolioController不可调用

所以它只能这样工作:

Route::get('/portfolio', [PortfolioController::class, '__invoke'])->name('portfolio');;
Run Code Online (Sandbox Code Playgroud)

这对我来说没有意义,因为它应该找到__invokewhich 中唯一的一个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'));
    }
}
Run Code Online (Sandbox Code Playgroud)

Laravel 8 是否忽略了__invoke属性???

Ken*_*rna 16

TL; 博士

这样做:

use App\Http\Controllers\PortfolioController;

Route::get('/portfolio', PortfolioController::class)->name('portfolio');
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

解释

在 Laravel 8 之前,路由的命名空间为RouteServiceProvider.php

protected $namespace = 'App\Http\Controllers';

// ...

protected function mapWebRoutes()
{
    Route::middleware('web')
        ->namespace($this->namespace) // <----
        ->group(base_path('routes/web.php'));
}
Run Code Online (Sandbox Code Playgroud)

因此,当您定义路由时,例如在您的示例中:

Route::get('/portfolio', 'PortfolioController')->name('portfolio');
                         ^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

PortfolioController字符串的命名空间为App\Http\Controllers.

在 Laravel 8 中,此行为已被修改。从v8 发行说明

在 Laravel 8.x 中,这个属性是null默认的。这意味着 Laravel 不会自动添加命名空间前缀。因此,在新的 Laravel 8.x 应用程序中,控制器路由定义应该使用标准的 PHP 可调用语法来定义:

use App\Http\Controllers\UserController;

Route::get('/users', [UserController::class, 'index']);
Run Code Online (Sandbox Code Playgroud)

现在,对于您提到的特殊情况,__invoke()方法,这是您应该根据文档处理它们的方式

为单个动作控制器注册路由时,不需要指定方法:

use App\Http\Controllers\ShowProfile;

Route::get('user/{id}', ShowProfile::class);
Run Code Online (Sandbox Code Playgroud)