COMP3512
winter 2024
lec-php-03
Up and Coming

RECALL
- Where were some places PHP can get data to place into an HTML response?
- What kind of language would you expect to see the most of if you looked in a view file?
- What is <?= "foo" ?> shorthand for?
RECALL
$movies = [
[
"id" => "10775",
"title" => "Infernal Affairs"
],
[
"id" => "508883",
"title" => "The Boy and the Heron"
],
[
"id" => "940721",
"title" => "Godzilla Minus One"
]
];What value does $movies[1]["title"] have?
Write a partial that would create an ordered list of ids. Assume $movies is in scope.
RECALL
$books = [
9780 => [
"author" => "Ann Napolitano",
"title" => "Hello Beautiful: A Novel"
],
8950 => [
"author" => "Michael Finkel",
"title" => "The Art Thief"
],
];
$target = ???;Finish the code so that $target has the value "The Art Thief". You must use $books to do this.
Name 3 different keys in the associative array $books.
let's talk about these things today:
◉ Forms markup refresher
◉ What happens when we submit a form?
◉ How can we grab things from a form?
◉ How do we validate a form on the server side?
◉ How do we persist values on a form so that our users are happy?
Forms
◉ Lab-01 code observations
◉ Project admin pages layout
General Stuff
Lab-01 code observations
Avoid echoing markup
echo "<p>You are looking quite <span style='color: blue;'>
$randomAdjective</span>
this <span style='color: blue;'>
$greeting</span>, <span style='color: blue;'>
$name</span>.</p>";
echo "<h2>You are looking quite " .
random_adjective() . " " . "this " .
get_greetings() . "," . " " .
$name_of_person . "." . "</h1>";It's hard to read, hard to think about, hard to debug, hard to maintain, easy to make mistakes, and hides what's actually going on.
PHP naming conventions are...well, it depends on who you talk to
function timeOfDay() {
// OK? Or should use time_of_day?
}for ($i = 0; $i < $numImages; $++) {
// OK? Or should use $num_images?
}Be consistent. I lean toward snake_case, simply because the functions in the PHP standard library use_underscores.
Avoid echoing in functions
function time_of_day() {
$hour = date("G");
if ($hour >= 5 && $hour <= 11) {
echo "morning";
} else if ($hour >= 12 && $hour <= 16) {
echo "afternoon";
} else {
echo "evening";
}Leave the writing to the response to the view code. Functions that echo are less reusable...and will come back to bite you once we start playing with sessions.
I'm curious: what were your impressions of writing PHP?
Project admin pages layout
Forms markup refresher
MDN has a lovely tutorial on Web forms - and many useful form-related reference articles as well.
<form method="post">
<ul>
<li>
<label for="name">Name:</label>
<input type="text" id="name" name="user-name" />
</li>
<li>
<label for="pwd">Password:</label>
<input type="password" id="pwd" name="pwd" />
</li>
<li>
<label for="msg">Message:</label>
<textarea id="msg" name="user-message"></textarea>
</li>
<li>
<button type="submit">Submit It!</button>
</li>
</ul>
</form>If label's for matches an input's id, what benefit do we get?
Some basic text inputs.
01
What's happening in the network tab when we land on this page?
<form method="post">
<fieldset>
<legend>Confused?</legend>
<ul>
<li>
<label for="confused-1">
<input type="radio" id="confused-1" name="confused" value="y" />
yes
</label>
</li>
<li>
<label for="confused-2">
<input type="radio" id="confused-2" name="confused" value="n" checked />
no
</label>
</li>
</ul>
</fieldset>
<p>
<button type="submit">Submit It!</button>
</p>
</form>Using fieldsets with radios/checkboxes is a good idea.
Radio buttons.
What does the checked attribute do for radios/checkboxes?
02
What's happening in the network tab when we land on this page?
What other common form elements do you often come across?
What happens when we submit a form?
<form method="post">
<ul>
<li>
<label for="name">Name:</label>
<input type="text" id="name" name="user-name" />
</li>
<li>
<label for="pwd">Password:</label>
<input type="password" id="pwd" name="pwd" />
</li>
<li>
<label for="msg">Message:</label>
<textarea id="msg" name="user-message"></textarea>
</li>
<li>
<button type="submit">Submit It!</button>
</li>
</ul>
</form>If we don't supply an action, the current page handles the submission.
How does an input's name attribute relate to what happens on submission?
Submitting text.
01
What's happening in the network tab when we submit this form?
<form method="post">
<fieldset>
<legend>Confused?</legend>
<ul>
<li>
<label for="confused-1">
<input type="radio" id="confused-1" name="confused" value="y" />
yes
</label>
</li>
<li>
<label for="confused-2">
<input type="radio" id="confused-2" name="confused" value="n" />
no
</label>
</li>
</ul>
</fieldset>
<p>
<button type="submit">Submit It!</button>
</p>
</form>How does a radio button's value attribute relate to what happens on submission?
Submitting radios.
02
What's happening in the network tab when we submit this form?
How can we grab things from a form?
This is going to require some concentration.
Stay with me.
Dealing with a POSTed form
<?php
if ($_SERVER['REQUEST_METHOD'] === "GET") {
// We've just arrived. Show the form...how?
} else if ($_SERVER['REQUEST_METHOD'] === "POST") {
// Someone must have submitted the form!
// Grab form values and do stuff.
}There are quite a few HTTP request methods.
We only care about GET and POST in this course.
03
$_SERVER is an example of a superglobal.
Notice we're NOT using an else here! Why not?
Let's get those form values
<?php
if ($_SERVER['REQUEST_METHOD'] === "GET") {
require './views/form.view.php';
} else if ($_SERVER['REQUEST_METHOD'] === "POST") {
$name = $_POST['user-name'];
$password = $_POST[???];
$message = $_POST[???];
$break = "I'm just here to be a breakpoint!";
}03
$__POST is another superglobal - a very important one.
Let's react to the submission
Say we want to let the user know we've received their message - and if their password is too short (say 8 characters), we'll chastise them.
Because users like being chastised.
Our todo list:
- Make a confirmation view that displays what we want.
- Put the logic to check for the password length in form.php.
- Require the confirmation view.
One possible confirmation view
<!DOCTYPE html>
<html lang="en">
<head>
<title>Thank you!</title>
</head>
<body>
<h1>Thanks, <?= $name ?>!</h1>
<p>We received your message.</p>
<p><?= $password_warning ?></p>
</body>
</html>03
Notice our view is pretty darn "dumb" - not a lot of logic in here. That's a desirable trait for views!
Let's give the view what it needs
if ($_SERVER['REQUEST_METHOD'] === "GET") {
require './views/form.view.php';
} else if ($_SERVER['REQUEST_METHOD'] === "POST") {
$name = $_POST['user-name'];
$password = $_POST['pwd'];
$message = $_POST['user-message'];
$password_warning = "";
if (strlen($password) < 8) {
$password_warning = "Your password's a bit...short.";
}
require './views/form-confirmation.view.php';
}03
Don't forget to bring the view in!
What about a GET form submission?
We need to dive into query strings more for that...and that's a topic for Wednesday.
What about a login form?
We don't have all the pieces for that yet - and the Milestone that needs it (Milestone 3 onward) is still a ways away. Relaaaaaax.


BRAIN BREAK
How do we validate a form on the server side?
Though it's true you can do a lot of validation in the browser, you should ALWAYS have back-end validation as well.
Let's validate our form.
Let's assume that we want to make sure the name field isn't empty - or only whitespace.
If the name IS empty, we want to redisplay the form with an error message.
The Plan
- Create an empty validation error array.
- Validate the response, adding error messages to the error array for each error found.
- If the error array is still empty, things are cool - just respond as before. Buuuuut...
- ...if the error array is NOT empty, that means we've got validation errors, so we have to show the form again...and the form has to display error messages. This means we'll need to change our view to deal with its new responsibilities.
} else if ($_SERVER['REQUEST_METHOD'] === "POST") {
$name = $_POST['user-name'];
$password = $_POST['pwd'];
$message = $_POST['user-message'];
$errors = [];
if (strlen(trim($name)) === 0) {
$errors['user-name'] = "The name can't be empty.";
}
if (empty($errors)) {
$password_warning = "";
if (strlen($password) < 8) {
$password_warning = "Your password's a bit...short.";
}
require './views/form-confirmation.view.php';
} else {
require './views/form.view.php';
}
}Changes to our controller (form.php)
<li>
<label for="name">Name:</label>
<input type="text" id="name" name="user-name" />
<?php if (isset($errors['user-name'])) : ?>
<p class="error"><?= $errors['user-name'] ?></p>
<?php endif; ?>
</li>Changes to our view (form.view.php)
Use a conditional to add markup with the error message. Why do we need the isset?
How do we persist values on a form so that our users are happy?
With our previous validation, the user's password and message were lost if there was a validation error.
That's reeeeeeeeally annoying, especially for cases where you've done a lot of typing.
Fortunately, there's a way to deal with this.
We can use the value attribute of some form elements to help us out here.
<li>
<label for="pwd">Password:</label>
<input type="password" id="pwd" name="pwd" value="<?= $password ?>" />
</li>Add the value attribute with the info the user had filled in.
You might be tempted to try something like this:
This doesn't work! Why?
How can we fix this?
<textarea> is a little bit different.
<li>
<label for="msg">Message:</label>
<textarea id="msg" name="user-message"><?= $message ?></textarea>
</li>No value here! Just text between the tags.
Radio buttons and checkboxes are a bit different as well. Hint: use the checked attribute....
lec-php-03
By Jordan Pratt
lec-php-03
forms | GET | POST | superglobals
- 202