環境
Laravel 9.52.0 (新規作成したプロジェクト)
状況
下記のようなルーティングとコントローラを作成して、画面上にコントローラのURLを表示させようとしました。
Route::get('index', [HelloController::class, 'index']);
<?php
namespace App\Http\Controllers;
class HelloController extends Controller
{
public function index()
{
return view('index');
}
}
<p>{{ action('HelloController@index') }}</p>
すると、Action HelloController@index not defined.
というエラーが発生↓
原因
Laravelが7から8にバージョンアップした際に、ルーティングの記載方法が変更になったことが原因でした。Laravel 7まではRouteServiceProvider
の中に$namespaceプロパティが定義されており、このプロパティによって、action('HelloController@index')という書き方をした際に自動的に名前空間のプレフィックスがつき、'App\Http\Controllers\HelloController@index'
であると解釈してくれていたみたいです。
しかし、Laravel 8以降はRouteServiceProvider
から$namespaceプロパティが削除され、初期値としてnullを設定するようになりました。なので、action('HelloController@index')という書き方をすると、エラーが出てしまっていたみたいです。
解決方法
下記の方法でエラーを解消することができました。
・RouteServiceProvider
に$namespaceプロパティを設定する
・コントローラのパスを全て書く
・use を使ってコントローラのパスを読み込む
RouteServiceProviderに$namespaceプロパティを設定する
このようにRouteServiceProviderに$namespaceを追加して、対象のルーティングに適用してやります。
すると今までと同じようにaction('HelloController@index')
という書き方でaction()を使うことができます。
class RouteServiceProvider extends ServiceProvider
{
+ protected $namespace = 'App\Http\Controllers';
(中略)
public function boot()
{
$this->configureRateLimiting();
Route::middleware('web')
+ ->namespace($this->namespace)
->group(base_path('routes/web.php'));
});
}
<p>{{ action('HelloController@index') }}</p>
コントローラのパスを全て書く
Laravelのバージョンアップによって、コントローラの名前空間のプレフィックスが自動でつかなくなったことが原因でエラーが出ていたので、下のように手動でつけてやってもうまくいきます。
<p>{{ action('App\Http\Controllers\HelloController@index') }}</p>
use を使ってコントローラのパスを読み込む
この方法も基本的には2番目と同じ方法ですが、@phpを使いuseでコントローラを指定しています。
action()の中身は、[HelloController::class, 'index']
というようにweb.appと同じ書き方で書くことができます。
@php
use App\Http\Controllers\HelloController;
@endphp
<p>{{ action([HelloController::class, 'index']) }}</p>