Laravel 8中的路由到控制器

10

我正在使用Laravel 8,在编写 __invoke 控制器路由时如下:

use App\Http\Controllers\PortfolioController;

Route::get('/portfolio', 'PortfolioController')->name('portfolio');

它显示以下错误:

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

所以只有这样才能正常工作:

Route::get('/portfolio', [PortfolioController::class, '__invoke'])->name('portfolio');;

这对我来说没有意义,因为它应该找到 PortfolioController.php 中唯一的 __invoke 函数:
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'));
    }
}

拉拉维尔8是否忽略__invoke属性?
2个回答

25

简而言之

就这样做:

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版本说明

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

use App\Http\Controllers\UserController;

Route::get('/users', [UserController::class, 'index']);
现在,针对你提到的特定情况,即__invoke()方法,以下是你应该按照文档处理它们的方式:

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

use App\Http\Controllers\ShowProfile;

Route::get('user/{id}', ShowProfile::class);

1
非常感谢您提供这个精彩的解释。 - Jota
1
如果您不想在路由文件中导入所有控制器,也可以像这样使用:$router->group([ 'namespace' => '\App\Http\Controllers'], function ($router) { $router->get('portfolio', [ 'as' => 'portfolio', 'uses' => 'PortfolioController::class', ]); }); - svikramjeet

0

另一种用法是,您可以使用完整路径


Route::get('/portfolio', 'App\Http\Controllers\PortfolioController')->name('portfolio');

或者调用特定的方法

Route::get('/portfolio', 'App\Http\Controllers\PortfolioController@foo')->name('portfolio')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接