I have a contact form with a privacy consent checkbox which the user has to check. If they don't, a required error message should appear, as it successfully does for the other fields.
The problem is that I'm getting an Undefined index: privacy
notice for the checkbox if it's unchecked. If I submit the form with it checked, then it works.
I understand that if the checkbox is unchecked, PHP basically doesn't know it exists, therefore it doesn't send the data to $_POST.
All the forum posts I read mention using isset()
or empty()
to fix this, but I'm already using it and used it in different ways to try things out.
It's probably something obvious, but I just can't figure it out for the past several hours.
Here's a part of the validation class:
class ValidateContactForm
{
private $data;
private $file;
private static $fields = [
'name',
'email',
'subject',
'message',
'privacy'
];
private static $fileInput = 'file';
private $errors = [];
public function __construct($postData, $fileData)
{
$this->data = $postData;
$this->file = $fileData;
}
public function validateForm()
{
// foreach (self::$fields as $field) {
// if (!array_key_exists($field, $this->data)) {
// trigger_error('An input key does not have a match in the array', E_USER_NOTICE);
// return;
// }
// }
if (!array_key_exists(self::$fileInput, $this->file)) {
trigger_error('The file input key does not match', E_USER_NOTICE);
}
$this->validateName();
$this->validateEmail();
$this->validateSubject();
$this->validateMessage();
$this->validatePrivacy();
$this->validateFile();
return $this->errors;
}
private function validatePrivacy()
{
$val = $this->data['privacy'];
if (empty($val)) {
$this->addError('privacy', 'The privacy checkbox is required.');
}
}
The validatePrivacy()
method checks if $_POST['privacy']
is empty.
Here's the part of the contact form class where I check if the fields are set:
class ContactForm
{
public function sendContactForm()
{
if ($_POST['name'] != ''
&& $_POST['email'] != ''
&& $_POST['message'] != ''
&& $_POST['subject'] != ''
&& !empty($_POST['privacy'])
) {
$name = $this->sanitize($_POST['name']);
$email = $this->sanitize($_POST['email']);
$message = $this->sanitize($_POST['message']);
$subject = $this->sanitize($_POST['subject']);
$privacy = $_POST['privacy'];
I also tried isset($_POST['privacy'])
and $_POST['privacy'] != ''
.
Here's a part of the file with the instantiation and HTML:
<?php
require_once 'includes/head.php';
require_once 'vendor/autoload.php';
use App\ContactForm;
use App\Validation\ValidateContactForm;
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$validation = new ValidateContactForm($_POST, $_FILES);
$errors = $validation->validateForm();
if (empty($errors)) {
$contactForm = new ContactForm;
$sendContactForm = $contactForm->sendContactForm();
if (!headers_sent()) {
header('Location:' . htmlspecialchars($_SERVER['PHP_SELF'], ENT_QUOTES) . '?' . 'sent');
exit;
}
}
}
?>
<div class="form-group form-check">
<input type="checkbox" name="privacy" class="form-check-input <?php echo isset($errors['privacy']) ? 'is-invalid' : ''; ?>" id="inputCheckbox" value="yes">
<label class="form-check-label" for="inputCheckbox">I understand that this information will be collected in order to be contacted and process a potential order. *</label>
<p class="invalid-feedback"><?php echo $errors['privacy'] ?? ''; ?></p>
</div>
If I use vard_dump
on it, it returns null
, but I assume it's expected behavior since it doesn't exist unless the checkbox is checked.
I know I can use the HTML required
attribute (and I will use that, too) or JavaScript, but I'd like to rely more on server validation. I also want to learn this stuff and not give in to workarounds.