1. INTRODUCTION
Forms let visitors send information to your website. Kristal Framework connects an HTML form to a method in App/Backend/Routes/FormRequests.php and checks its form token before calling the method.
Let’s create a form that saves a name for the current visit and displays a message afterwards.
2. CREATING A FORM
Add this form to a page template in App/templates/:
<form method="post">
<?php CSRF::create("display_name_form", "save_display_name"); ?>
<label for="display-name">Your name</label>
<input id="display-name" name="display-name" type="text"
required>
<button type="submit">Save name</button>
</form>
CSRF::create() adds the hidden fields needed by the framework. The first value names the form; the second names the method that handles it.
The form submits to the page it’s on. You don’t need to create a separate POST route.
3. HANDLING A SUBMISSION
Add this method inside your existing FormRequests class:
public function save_display_name(array $request): void
{
$name = $request["display-name"] ?? "";
if (!is_string($name) || trim($name) === "")
{
\Backend\Core\Session::add("name_feedback", "Please enter your name.");
return;
}
\Backend\Core\Session::add("display_name", trim($name));
\Backend\Core\Session::add("name_feedback", "Your name has been saved.");
}
The input’s name becomes a key in $request. Here, display-name holds the submitted name. The method checks that it is text and isn’t empty, then saves it with a feedback message.
After the method finishes, Kristal Framework returns the visitor to the previous page on your site, or / if no previous page is available. To choose another destination, call a redirect in your method:
redirect(route(""));
This sends the visitor to the homepage and ends the request.
Important!
A valid form token does not mean the fields are valid. Check submitted values in your method before using them.
4. DISPLAYING FEEDBACK
Add this above the form to show the saved message:
<?php $feedback = Session::get("name_feedback"); ?>
<?php if (is_string($feedback)): ?>
<p><?= esc_html($feedback); ?></p>
<?php Session::remove("name_feedback"); ?>
<?php endif; ?>
Submit the form to see your feedback. The message is removed after display, so it appears once.
You can use the same session approach to keep form values between requests. See Sessions for more examples.
5. PROTECTED FORM REQUESTS
The examples above use a public method. The framework can also call protected methods when allow_protected_calls is set to true in the FormRequests constructor.
This setting leaves protected calls disabled:
public function __construct()
{
parent::__construct([
"allow_protected_calls" => false,
]);
}
Private methods cannot be used as form handlers. Check submitted fields inside the handler whichever visibility you choose.
6. FILES AND CSRF TOKENS
Receiving a File
For a file input, add enctype=”multipart/form-data” to the form:
<form method="post" enctype="multipart/form-data">
<?php CSRF::create("attachment_form", "inspect_attachment"); ?>
<input type="file" name="attachment" accept="text/plain">
<button type="submit">Upload</button>
</form>
Create an inspect_attachment() method to handle this form. Its $request[”attachment”] value contains PHP’s upload details, including name, tmp_name, error and size. Check the upload error, size and file content before saving anything.
Give file inputs different names from other fields. If names overlap, the ordinary POST value takes priority.
Refreshing Form Tokens
Form tokens are normally reused during a session. To clear them:
\Backend\Core\CSRF::reset();
You can also enable REGENERATE_CSRF_ON_PAGE_REFRESH in config/config.php to reset tokens on GET requests.
Note!
Resetting tokens can make an already open form invalid. Invalid tokens stop the handler without showing an error message; reload the page to get a fresh form.
