Hi everybody, I’ve almost finished converting an existing client site to Kirby. Everything is working well, but I need to handle a simple user facing form.
The careful part
Before I continue I should say:
- I am aware of existing form plugins (thanks especially to @jenstornell’s plugin list and the various posts here on the forum). I have attempted to use them, but have not succeeded. So before you recommend that I use one, please keep this in mind.
- I would really like to learn how to do this using Kirby specifically, and thereby learn a little more about how to write and use PHP.
- My code works. I just don’t know how to validate the data and send messages back to the user looking at the form.
- I realize there’s a pretty good chance this may be a PHP coding question and not really a Kirby one, and if that’s the case, I’d love any suggestions of how to learn to tackle this.
What I have so far
A comment form
This is the snippet where I define my form ( in snippets/commentform.php
):
<?php if(!defined('KIRBY')) exit ?>
<div class="main" role="main">
<hr>
<h3>Leave your comment</h3>
<form id="commentform" method="post">
<div class="field">
<input type="text" id="name" name="name" placeholder="Name (required)">
</div>
<div class="field">
<input type="email" id="email" name="email" placeholder="Email (required)">
</div>
<div class="field">
<input type="url" id="website" name="website" placeholder="Website (optional)">
</div>
<div class="field">
<textarea id="comment" name="comment" placeholder="Your comment"></textarea>
</div>
<input type="submit" name="submit" value="Submit">
</form> </div>
A controller
I get the data and handle it in controllers/commentform.php
:
<?php if(!defined('KIRBY')) exit ?>
<?php
// If the form has been sent
if(r::method() === 'POST') {
// Do some useful things
return function($site, $pages, $page) {
// Build an array of the data from the fields
// get() fetches the form field value with that `name`
$data = array(
'name' => get('name'),
'email' => get('email'),
'website' => get('website'),
'comment' => get('comment')
);
// Get and store this moment's date and time for use in constructing the file on disk
$commentDate = $page->modified('Y-m-d-H-i-s');
// Assuming everything's OK, create a new page as child of the current page
// You can also use a different page by using `page('whatever')->children()->create()`
$p = $page->children()->create(($commentDate . '-'), 'formdata', $data);
}
};
A blueprint
There’s also blueprints/commentdata.yml
that serves as a pattern for the commentdata.txt file written into the system
<?php if(!defined('KIRBY')) exit ?>
# pattern defining the data captured from a reader comment form
title: Comment data
pages: false
files: false
fields:
username:
label: Your name
type: text
email:
label: Email
type: email
website:
label: Website
type: url
comment:
label: Comment
type: textarea
This is working great. It’s fantastic and writes a uniquely timestamped folder as a child to the blog article with a commentdata.txt in it containing the data.
It’s pretty neat to see it all go. Except the fact that a comment is posted even if every single field is empty.
What I need to do next
I need to validate this stuff before it gets posted.
I would like to step through each field and test its validity, presumably using Kirby’s validators. If something isn’t valid, I’d like to put a message back into the form that I can style and show the user.
A simple statement of rules would be:
name (required)
email (required, a valid email address)
website (entirely optional)
comment (required minimum length of 3 characters, maximum length of, say, 3000)
I’m happy to post more parts or answer questions.
Thanks in advance for your advice and any help.
Jon