前提・実現したいこと
Laravel8でTODOリストアプリを作っています。
ルートモデルバインディングでコントローラーメソッドを使用する暗黙的な結合を実装中にエラーメッセージが発生しました。
発生している問題・エラーメッセージ
まずweb.phpのルート情報1つと関連するtaskController.phpを修正し、動作確認のためログインしてみると次のエラーが出ました。
Illuminate\Routing\Exceptions\UrlGenerationException Missing required parameters for [Route: tasks.index] [URI: folders/{folder}/tasks]. (View: /Applications/MAMP/htdocs/laraveltodolist/resources/views/tasks/index.blade.php)
該当のソースコード
//web.php <?php use Illuminate\Support\Facades\Route; use App\Http\Controllers\TaskController; use App\Http\Controllers\FolderController; use App\Http\Controllers\HomeController; Route::group(['middleware' => 'auth'], function() { Route::get('/', [HomeController::class, 'index'])->name('home'); Route::get('/folders/{folder}/tasks', [TaskController::class, 'index'])->name('tasks.index'); Route::get('/folders/create', [FolderController::class, 'showCreateForm'])->name('folders.create'); Route::post('/folders/create', [FolderController::class, 'create']); Route::get('/folders/{id}/tasks/create', [TaskController::class, 'showCreateForm'])->name('tasks.create'); Route::post('/folders/{id}/tasks/create', [TaskController::class, 'create']); Route::get('/folders/{id}/tasks/{task_id}/edit', [TaskController::class, 'showEditForm'])->name('tasks.edit'); Route::post('/folders/{id}/tasks/{task_id}/edit', [TaskController::class, 'edit']); }); Auth::routes();
//TaskController.php <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\Folder; use App\Models\Task; use App\Http\Requests\CreateTask; use App\Http\Requests\EditTask; use Illuminate\Support\Facades\Auth; class TaskController extends Controller { public function index(Folder $folder) { // ユーザーのフォルダを取得する $folders = Auth::user()->folders()->get(); //選ばれたフォルダに紐づくタスクを取得する $tasks = $folder->tasks()->get(); return view('tasks/index',[ 'folders' => $folders, 'current_folder_id' => $folder->id, 'tasks' => $tasks, ]); } public function showCreateForm(int $id) { return view('tasks/create',[ 'folder_id' => $id ]); } public function create(int $id,CreateTask $request) { $current_folder = Folder::find($id); $task = new Task(); $task->title = $request->title; $task->due_date = $request->due_date; $current_folder->tasks()->save($task); return redirect()->route('tasks.index',[ 'id' => $current_folder->id, ]); } public function showEditForm(int $id, int $task_id) { $task = Task::find($task_id); return view('tasks/edit',[ 'task' => $task, ]); } public function edit(int $id, int $task_id, EditTask $request) { //1 $task = Task::find($task_id); //2 $task->title = $request->title; $task->status = $request->status; $task->due_date = $request->due_date; $task->save(); //3 return redirect()->route('tasks.index',[ 'id' => $task->folder_id, ]); } }
//login.blade.php(参考) @extends('layout') @section('content') <div class="container"> <div class="row"> <div class="col col-md-offset-3 col-md-6"> <nav class="panel panel-default"> <div class="panel-heading">ログイン</div> <div class="panel-body"> @if($errors->any()) <div class="alert alert-danger"> @foreach($errors->all() as $message) <p>{{ $message }}</p> @endforeach </div> @endif <form action="{{ route('login') }}" method="POST"> @csrf <div class="form-group"> <label for="email">メールアドレス</label> <input type="text" class="form-control" id="email" name="email" value="{{ old('email') }}" /> </div> <div class="form-group"> <label for="password">パスワード</label> <input type="password" class="form-control" id="password" name="password" /> </div> <div class="text-right"> <button type="submit" class="btn btn-primary">送信</button> </div> </form> </div> </nav> <div class="text-center"> <a href="{{ route('password.request') }}">パスワードの変更はこちらから</a> </div> </div> </div> </div> @endsection
//LoginController.php(参考) <?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use App\Providers\RouteServiceProvider; use Illuminate\Foundation\Auth\AuthenticatesUsers; class LoginController extends Controller { use AuthenticatesUsers; /** * Where to redirect users after login. * * @var string */ protected $redirectTo = '/'; // protected $redirectTo = RouteServiceProvider::HOME; /** * Create a new controller instance. * * @return void */ public function __construct() { $this->middleware('guest')->except('logout'); } }
//HomeController.php(参考) <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class HomeController extends Controller { public function index() { // ログインユーザーを取得する $user = Auth::user(); // ログインユーザーに紐づくフォルダを一つ取得する $folder = $user->folders()->first(); // まだ一つもフォルダを作っていなければホームページをレスポンスする if (is_null($folder)) { return view('home'); } // フォルダがあればそのフォルダのタスク一覧にリダイレクトする return redirect()->route('tasks.index', [ 'id' => $folder->id, ]); } }
試したこと
ルートモデルバインディングでコントローラーメソッドを使用する暗黙的な結合を実装のために、まずweb.phpのルート情報を一つだけ次のようにしています。
Route::get('/folders/{folder}/tasks', [TaskController::class, 'index'])->name('tasks.index');
続きでTaskController.phpのindexアクションだけ次のようにしました。
public function index(Folder $folder) { // ユーザーのフォルダを取得する $folders = Auth::user()->folders()->get(); //選ばれたフォルダに紐づくタスクを取得する $tasks = $folder->tasks()->get(); return view('tasks/index',[ 'folders' => $folders, 'current_folder_id' => $folder->id, 'tasks' => $tasks, ]); }
ここで、動作確認のためブラウザを開き、ログインしてみると上記のエラーが出ました。
参考にしているサイトにも次のように書かれているため、何故エラーなのか分かりません。
Laravel は、ルーティング定義の URL の中括弧で囲まれたキーワード({folder})とコントローラーメソッドの仮引数名($folder)が一致していて、かつ引数が型指定(Folder)されていれば、URL の中括弧で囲まれた部分の値を ID とみなし、自動的に引数の型のモデルクラスインスタンスを作成します。
コントローラーメソッドを使用する場合でも暗黙的な結合は可能です。繰り返しになりますが、{user}URIセグメントはApp\Models\Userタイプヒントを含むコントローラーの$user変数と一致することに注意してください。
的外れかもしれませんが、TaskController.phpのretrunの配列に'folder' => $folder->id,や'folder' => $folder,を追加してみましたが解決できませんでした。
これも的外れかもしれませんが、ログイン後にエラーがでるためHomeController.phpが関係するのかもしれないと思い、use App\Models\Folder;を追加して、indexアクションの引数を(Folder $folder)にしてみましたがダメでした。
他に何が問題なのか分からなく、お力添えいただければ幸いです。
補足情報(FW/ツールのバージョンなど)
OS Mac
PHP 7.3.11
Laravel 8.18.1
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/12/28 13:22 編集