-
-
Notifications
You must be signed in to change notification settings - Fork 126
Description
Tempest version
1.6.0
PHP version
8.4
Operating system
macOS
Description
This is kinda related to #856
I am creating a CRUD application, to better understand how Tempest would work in a actual application.
In line with Tempest examples / tests I created a application to manage books, authors and book chapters.
Creating, listing goes well, however when I want to edit or delete a record I run into issues. The route I want to use doesn't resolve. This route is marked with the #[Post(..)]
or #{Delete)
attribute.
Steps to reproduce
Example implementation
I think this all that is needed.
edit.view.php
<form action="/books/{{ $book->id }}" method="post">
<x-csrf-token />
<input type="hidden" name="_method" value="PUT" />
<h1 class="text-balance text-5xl font-semibold tracking-tight text-gray-800 sm:text-7xl">
Edit Book
</h1>
<p class="mt-8 text-pretty text-lg font-medium text-gray-500 sm:text-xl/8">
<input type="text" name="title" value="{{ $originalValues['title'] ?? ($book?->title ?? '') }}" placeholder="Title" class="border placeholder:px-2 px-2" />
<div :if="isset($errors['title'])" class="text-red-600 text-sm mt-1">
<div :foreach="$errors['title'] as $error">
{{ $error->message() }}
</div>
</div>
</p>
<p class="mt-8 text-pretty text-lg font-medium text-gray-500 sm:text-xl/8">
<select name="authorId" id="authorId" class="border px-2 py-1">
<option value="">Select Author</option>
<option :foreach="$this->authors as $author" :value="$author->id" :selected="($originalValues['authorId'] ?? ($book?->author?->id ?? '')) == $author->id">
{{ $author->name }}
</option>
</select>
<div :if="isset($errors['authorId'])" class="text-red-600 text-sm mt-1">
<div :foreach="$errors['authorId'] as $error">
{{ $error->message() }}
</div>
</div>
</p>
<p class="mt-8 text-pretty text-lg font-medium text-gray-500 sm:text-xl/8">
<input type="submit" value="Update" class="bg-blue-500 text-white px-4 py-0.5 rounded-lg" />
</p>
</form>
BookController::edit
#[Get('/books/{bookId}/edit')]
public function edit(int $bookId): View|Redirect
{
$book = Book::find(id: $bookId)
->with('author.publisher')
->first();
if ($book === null) {
return new Redirect('/');
}
// Get validation errors and original values from session with null safety
$sessionErrors = $this->session->get(Session::VALIDATION_ERRORS, []);
$sessionOriginalValues = $this->session->get(Session::ORIGINAL_VALUES, []);
// Ensure session data is always an array
$errors = is_array($sessionErrors) ? $sessionErrors : [];
$originalValues = is_array($sessionOriginalValues) ? $sessionOriginalValues : [];
return view('Views/Books/edit.view.php',
title: 'Edit Book',
book: $book,
authors: Author::select()->all() ?? [],
publishers: Publisher::select()->all() ?? [],
errors: $errors,
originalValues: $originalValues
);
}
BookController::update
#[Put('/books/{bookId}')]
public function update(int $bookId, UpdateBookRequest $request): Redirect
{
$book = Book::find(id: $bookId)->first();
// Ensure book exists
if ($book === null) {
return new Redirect('/');
}
$author = Author::find(id: $request->authorId)->first();
// Ensure author exists
if ($author === null) {
// Author not found - redirect back to edit form
return new Redirect('/books/' . $bookId . '/edit');
}
$book->title = $request->title;
$book->author = $author;
$book->save();
return new Redirect('/books/' . $bookId);
}
Steps:
- create a book record, with dependent records
- visit the edit route
- update something (without triggering a validation error)
- submit the form
Expectation
I expected the following things to happen upon submitting
- I would be redirected to the show book page/route
- the database record would have been updated
Result
The browser returns a 404 (outside of the Tempest application)
What I've worked out so far is that when resolving the request from the form it looks for a POST
route, ignoring the method="PUT"
form element.