Hello there,
I am working on a fairly large project and figuring out how to approach the form validation with PHP. Stripped down to its bare essentials, it basically looks like this:
===
<?php
$fruit = array(
array('id' => '1', 'name' => 'apple'),
array('id' => '2', 'name' => 'pear'),
array('id' => '3', 'name' => 'plum'),
array('id' => '4', 'name' => 'strawberry'),
array('id' => '5', 'name' => 'gooseberry'),
array('id' => '6', 'name' => 'currant')
);
session_start();
if (isset($_GET['startover'])) {
if (isset($_SESSION['favoriteNumber'])) {
unset($_SESSION['favoriteNumber']);
}
if (isset($_SESSION['favoriteFruit'])) {
unset($_SESSION['favoriteFruit']);
}
header('Location: .');
exit();
}
if (isset($_POST['submitSelection'])) {
include 'confirmation.html.php';
exit();
}
if (isset($_POST['goToPreview'])) {
$favoriteFruitKeys = $_POST['favoriteFruitKeys'];
foreach ($favoriteFruitKeys as $id):
foreach ($fruit as $item):
if ($item['id'] == $id) {
$favoriteFruit[] = array(
'id' => $item['id'],
'name' => $item['name']
);
}
endforeach;
endforeach;
$_SESSION['favoriteFruit'] = $favoriteFruit;
include 'preview.html.php';
exit();
}
if (isset($_POST['goToInput2'])) {
$favoriteNumber = $_POST['favoriteNumber'];
$_SESSION['favoriteNumber'] = $favoriteNumber;
include 'input2.html.php';
exit();
}
if (empty($_GET)) {
include 'input1.html.php';
exit();
}
include 'error.html.php';
===
The tricky part is that I would like to keep each of those large “if” blocks intact: in the actual project, they contain a bunch of shuttling of material back and forth to a database. I came up with a solution that does what I want, but requires the “goto” statement.
===
<?php
$fruit = array(
array('id' => '1', 'name' => 'apple'),
array('id' => '2', 'name' => 'pear'),
array('id' => '3', 'name' => 'plum'),
array('id' => '4', 'name' => 'strawberry'),
array('id' => '5', 'name' => 'gooseberry'),
array('id' => '6', 'name' => 'currant')
);
session_start();
if (isset($_GET['startover'])) {
if (isset($_SESSION['favoriteNumber'])) {
unset($_SESSION['favoriteNumber']);
}
if (isset($_SESSION['favoriteFruit'])) {
unset($_SESSION['favoriteFruit']);
}
header('Location: .');
exit();
}
if (isset($_POST['submitSelection'])) {
include 'confirmation.html.php';
exit();
}
if (isset($_POST['goToPreview'])) {
if (isset($_POST['goToPreview']) and ($_POST['goToPreview'] == 'Clear')) {
$_POST['favoriteNumber'] = $_SESSION['favoriteNumber'];
goto validationInput2;
}
if (!empty($_POST['favoriteFruitKeys'])) {
$favoriteFruitKeys = $_POST['favoriteFruitKeys'];
foreach ($favoriteFruitKeys as $id):
foreach ($fruit as $item):
if ($item['id'] == $id) {
$favoriteFruit[] = array(
'id' => $item['id'],
'name' => $item['name']
);
}
endforeach;
endforeach;
$_SESSION['favoriteFruit'] = $favoriteFruit;
} else {
$_POST['favoriteNumber'] = $_SESSION['favoriteNumber'];
$favoriteFruitKeys = 0;
goto validationInput2;
}
include 'preview.html.php';
exit();
}
if (isset($_POST['goToInput2'])) {
validationInput2:
if ((isset($favoriteFruitKeys)) and ($favoriteFruitKeys == 0)) {
$notValidFruit = 'Please select at least one item.';
}
if (isset($_POST['goToInput2']) and ($_POST['goToInput2'] == 'Clear')) {
if (isset($_SESSION['favoriteNumber'])) {
unset($_SESSION['favoriteNumber']);
}
goto validationInput1;
}
if (!empty($_POST['favoriteNumber'])) {
$favoriteNumber = $_POST['favoriteNumber'];
$_SESSION['favoriteNumber'] = $favoriteNumber;
} else {
$favoriteNumber = 0;
goto validationInput1;
}
include 'input2.html.php';
exit();
}
if (empty($_GET)) {
validationInput1:
if ((isset($favoriteNumber)) and ($favoriteNumber == 0)) {
$notValidNumber = 'Please select a number.';
}
include 'input1.html.php';
exit();
}
include 'error.html.php';
===
It is not an elegant approach, but it works. However, I have read so much controversial material about “goto” that I am wondering if it will lead to problems down the road. Or perhaps there is another approach that I didn’t think of.
The only alternative that came to mind for me was to actually split the code blocks into separated PHP files and then jump around as needed with <form action=“input2.php” method=“post”> and so forth. And then if I need to go someplace else for validation, just use a header(‘Location:’) redirect of some sort.
That doesn’t seem too sleek either, but perhaps it is the most appropriate solution in this case.
Thoughts? Comments? Suggestions?
Any feedback would be greatly appreciated.
Many thanks.
P.S. Btw, the relevant HTML is here:
<h1>Input 1</h1>
<p>Pick your favorite number.</p>
<form action="" method="post">
<fieldset>
<legend>Numbers</legend>
<div class="notvalid"><?php if (isset($notValidNumber)) echo $notValidNumber; ?></div>
<ul>
<li><input type="radio" name="favoriteNumber" value="1" id="number1" />
<label for="number1">1</label></li>
<li><input type="radio" name="favoriteNumber" value="2" id="number2" />
<label for="number2">2</label></li>
<li><input type="radio" name="favoriteNumber" value="5" id="number5" />
<label for="number5">5</label></li>
</ul>
</fieldset>
<input type="submit" name="goToInput2" value="Clear" />
<input type="submit" name="goToInput2" value="Next" />
</form>
<h1>Input 2</h1>
<p>Pick your favorite fruit.</p>
<p>Check all that apply.</p>
<form action="" method="post">
<fieldset>
<legend>Fruit</legend>
<div class="notvalid"><?php if (isset($notValidFruit)) echo $notValidFruit; ?></div>
<ul>
<?php foreach ($fruit as $item): ?>
<li>
<input type="checkbox" name="favoriteFruitKeys[]" id="fruit<?php echo $item['id'];?>" value="<?php echo $item['id']; ?>" />
<label for="fruit<?php echo $item['id'];?>"><?php echo $item['name'];?></label>
</li>
<?php endforeach; ?>
</ul>
</fieldset>
<input type="submit" name="goToPreview" value="Clear" />
<input type="submit" name="goToPreview" value="Next" />
</form>
<h1>Preview</h1>
<p>Please proofread your selection.</p>
<form action="" method="post">
<fieldset>
<legend>Favorite Number</legend>
<?php echo $_SESSION['favoriteNumber'];?>
</fieldset>
<fieldset>
<legend>Favorite Fruit</legend>
<ul>
<?php foreach ($favoriteFruit as $item):?>
<li>
<?php echo $item['name'];?>
</li>
<?php endforeach;?>
</ul>
</fieldset>
<input type="submit" name="submitSelection" value="Submit" />
</form>
<h1>Confirmation</h1>
<p>Congratulations! Your selection has been added to our pretend database!</p>
<p><a href="?startover">Enter another</a>.</p>