Search code examples
phplaravellaravel-livewirelaravel-jetstream

Laravel Jetstream Update not being triggered from form and instead redirecting to wrong page


I have been attempting to get a form to update the database that already exists. I have effectively copy and pasted the fully working code from my create blade to my edit blade and it has a weird issue where instead of editing the database it seems to run the wrong function.

When I click the button in my index.blade.php to navigate to the edit blade everything looks good but when I click the save button instead of it saving like it should and stop since I commented out the navigation line it instead seems to be running the controllers show function and navigating to the projects.courses.index.

I have read to make sure the form doesn't use POST for the update even though POST works fine on my create blade. When I left it as POST in the form tag and added a method to make it PUT later it throws a 403 error. I suspect that might actually be what I want it to do and then I would need to update my web.php routes but I'm not sure what I'd put there if that is what I'd need to do.

Thanks for any help you can offer.

This is the web.php

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProjectController;
use App\Http\Controllers\CourseController;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::middleware(['auth:sanctum', 'verified'])->get('/dashboard', function () {
    return view('dashboard');
})->name('dashboard');

Route::group(['middleware'=>'auth'], function() {
    Route::resource('projects', ProjectController::class);
    Route::resource('projects.courses', CourseController::class);
});

Here is the controller

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests\StoreProjectRequest;
use App\Http\Requests\UpdateProjectRequest;
use App\Models\Project;


class ProjectController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $projects = Project::all();

        return view('projects.index') -> with('name', 'Projects') -> with(compact('projects'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        return view('projects.create');
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(StoreProjectRequest $request)
    {
        $row = new Project;
        $row->code = $request->code;
        $row->code_full = $request->code_full;
        $row->title = $request->title;
        $row->description = $request->description;
        $row->save();

        return redirect()->route('projects.index');
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show(Project $project)
    {
        return redirect()->route('projects.courses.index', $project);
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit(Project $project)
    {
        return view('projects.edit') -> with('project', $project);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(UpdateProjectRequest $request, $id)
    {
        $row = Project::find($id);
        $row->code = $request->code;
        $row->code_full = $request->code_full;
        $row->title = $request->title;
        $row->description = $request->description;
        $row->save();

        //return redirect()->route('projects.index');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy(Project $project)
    {
        $project->delete();

        return redirect()->route('projects.index');
    }
}

Here is the edit blade

<x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
            {{ __('Edit Project') }}
        </h2>
    </x-slot>

    <div class="py-12">
      <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
        
        <div class="mt-10 sm:mt-0">
          <div class="md:grid md:grid-cols-3 md:gap-6">
            <div class="md:col-span-1">
              <div class="px-4 sm:px-0">
                <h3 class="text-lg font-medium leading-6 text-gray-900">Project Information</h3>
                <p class="mt-1 text-sm text-gray-600">
                  Please fill out this form to edit the project {{$project->title}}.
                </p>
              </div>
            </div>
            <div class="mt-5 md:mt-0 md:col-span-2">
              <form action="{{ route('projects.update', $project->id) }}" method="PUT" enctype="multipart/form-data">
                @csrf
                <div class="shadow overflow-hidden sm:rounded-md">
                  <div class="px-4 py-5 bg-white sm:p-6">
                    <div class="grid grid-cols-6 gap-6">
                      <div class="col-span-6 sm:col-span-3">
                        <label for="code" class="block text-sm font-medium text-gray-700">Project ID (4 digit code)</label>
                        <input type="text" name="code" id="code" autocomplete="" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md" placeholder="{{ $project->code }}" value="{{ old('code', '') }}">
                        @error('code')
                        <p class="text-sm text-red-600">{{$message}}</p>
                        @enderror
                      </div>

                      <div class="col-span-6 sm:col-span-3">
                        <label for="code_full" class="block text-sm font-medium text-gray-700">Project Code</label>
                        <input type="text" name="code_full" id="code_full" autocomplete="" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md" placeholder="{{ $project->code_full }}" value="{{ old('code_full', '') }}">
                        @error('code_full')
                        <p class="text-sm text-red-600">{{$message}}</p>
                        @enderror
                      </div>

                      <div class="col-span-6 sm:col-span-4">
                        <label for="title" class="block text-sm font-medium text-gray-700">Project Title</label>
                        <input type="text" name="title" id="title" autocomplete="" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md" placeholder="{{ $project->title }}" value="{{ old('title', '') }}">
                        @error('title')
                        <p class="text-sm text-red-600">{{$message}}</p>
                        @enderror
                      </div>

                      <div class="col-span-6">
                        <label for="description" class="block text-sm font-medium text-gray-700">Description</label>
                        <input type="text" name="description" id="description" autocomplete="" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md" placeholder="{{ $project->description }}" value="{{ old('description', '') }}">
                        @error('description')
                        <p class="text-sm text-red-600">{{$message}}</p>
                        @enderror
                      </div>

                    </div>
                  </div>
                  <div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
                    <button type="submit" class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
                      Save
                    </button>
                  </div>
                </div>
              </form>
            </div>
          </div>
        </div>

      </div>
    </div>
</x-app-layout>

Solution

  • I was right that the 403 error was what I should had been getting but it wasn't a routing issue. The following is how I ultimately solved it since it all boiled down to the code having a false where it needed to be a true.

    Step 1: in the edit blade the form method should be "POST" and under the @csrf I needed to put a @method('PUT') which I had tried once but got a 403 error and undid it.

    Step 2: Controller update should be changed a bit to be like

    public function update(UpdateProjectRequest $request, Project $project)
        {
            $row = Project::find($project->id);
    

    Step 3: To end the 403 error I needed to go to the UpdateProjectRequest and change a false to true.

    public function authorize()
        {
            return true;
        }