LEARN TO CODE | PHP | 01 SERVER-SIDE FOUNDATIONS

01 Server-side foundations: challenges

Build confidence with server-side PHP by completing focused tasks and a small data-driven webpage.

START HERE | INDEPENDENT PRACTICE

Use the local PHP server from 01.1. Save each solution in its own .php file inside myWebsite. Request it through http://127.0.0.1:8000/filename.php rather than double-clicking it.

Predict the browser output first. Run, compare and explain what happened. Open a hint only when needed; tick completion after checking. Ticks last while this page is open.

Complete code blocks are independent examples. Do not paste every PHP block into one file, particularly repeated function definitions.

CHALLENGE 01 | PROVE THE SERVER IS RUNNING

Create index.php with a PHP-generated welcome sentence. Load it using HTTP and explain why file:// is the wrong workflow.

Need a hint?

PHP needs an interpreter handling the request.

Reveal a possible solution
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My first PHP page</title>
</head>
<body>
    <h1>Welcome to my website</h1>
    <p><?php echo "PHP created this sentence."; ?></p>
</body>
</html>

Use http://127.0.0.1:8000/index.php with the development server running. View Page Source to see the generated HTML response.

CHALLENGE 02 | A PERSONALISED GREETING

Store a name and club in variables and output one readable greeting with spaces and punctuation.

Need a hint?

Use . to join text and escape variable text in HTML.

Reveal a possible solution
<?php
$name = 'Maya';
$club = 'Art & Design';
echo '<p>Hello, ' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8');
echo '! Welcome to ' . htmlspecialchars($club, ENT_QUOTES, 'UTF-8') . '.</p>';

CHALLENGE 03 | TYPE DETECTIVE

Create the values 12, '12', true and null. Show their types for debugging and explain why direct echo is unclear for the last two.

Need a hint?

var_dump shows both type and value.

Reveal a possible solution
<?php
var_dump(12);
var_dump('12');
var_dump(true);
var_dump(null);

The types are int, string, bool and NULL. Direct echo of true yields 1; null yields empty output. Use meaningful labels for users.

CHALLENGE 04 | PLACES AND BOUNDARIES

Calculate remaining places. Display Full at zero, Almost full at one or two, and Places available above two. Assume valid non-negative remaining values.

Need a hint?

Order the narrow zero case before the broader low range.

Reveal a possible solution
<?php
$capacity = 12;
$members = 10;
$remaining = $capacity - $members;
if ($remaining === 0) {
    echo 'Full';
} elseif ($remaining <= 2) {
    echo 'Almost full';
} else {
    echo 'Places available';
}

Test remaining values 0, 1, 2 and 3. Separately decide how an invalid negative result should be handled.

CHALLENGE 05 | EXACTLY FIVE ITEMS

Output one ordered HTML list containing Task 1 to Task 5.

Need a hint?

Put the list wrapper outside the loop body.

Reveal a possible solution
<?php
echo '<ol>';
for ($number = 1; $number <= 5; $number++) {
    echo '<li>Task ' . $number . '</li>';
}
echo '</ol>';

CHALLENGE 06 | TRACE THE TOTAL

Find the sum of integers 1 to 5 using a running total. Write each intermediate total before running.

Need a hint?

Read the old total, add the current number, store the new total.

Reveal a possible solution
<?php
$total = 0;
for ($number = 1; $number <= 5; $number++) {
    $total = $total + $number;
}
echo $total;

Intermediate totals: 1, 3, 6, 10, 15. Final output: 15. Resetting total inside the loop would lose earlier values.

CHALLENGE 07 | RETURN A REUSABLE RESULT

Define a function that receives two integers and returns remaining places. Demonstrate two calls without printing inside the function.

Need a hint?

Use return, then echo at the caller.

Reveal a possible solution
<?php
function placesLeft(int $capacity, int $members): int
{
    return $capacity - $members;
}
echo '<p>' . placesLeft(12, 10) . '</p>';
echo '<p>' . placesLeft(10, 6) . '</p>';

Outputs 2 and 4. The calculation and presentation are separate.

CHALLENGE 08 | LIST FROM AN ARRAY

Create a list of three clubs, append a fourth and generate the page list using foreach.

Need a hint?

Append with []; output one li for each value.

Reveal a possible solution
<?php
$clubs = ['Robotics', 'Art', 'Chess'];
$clubs[] = 'Coding';
echo '<ul>';
foreach ($clubs as $club) {
    echo '<li>' . htmlspecialchars($club, ENT_QUOTES, 'UTF-8') . '</li>';
}
echo '</ul>';

There should be four items without four manually copied output blocks.

CHALLENGE 09 | NAMED DATA

Store one club as an associative array with name, capacity and members. Explain why name is a key rather than a variable name.

Need a hint?

Keys label entries inside the array.

Reveal a possible solution
<?php
$club = ['name' => 'Robotics', 'capacity' => 12, 'members' => 10];
echo htmlspecialchars($club['name'], ENT_QUOTES, 'UTF-8');

$club is the variable. The string key name selects a value from that array.

CHALLENGE 10 | DEBUG THE BOUNDARY

A loop starts at 1 and uses $number < 5 but should show 1 through 5. Identify the error. A while loop never updates its counter: explain the result.

Need a hint?

Check the last test and the statement that changes the condition.

Reveal a possible solution

Use <= 5 to include 5. Without a counter update, a true while condition can stay true indefinitely. Stop the request/server if needed, then fix the update before repeating the test.

CHALLENGE 11 | CHECK OUTPUT AS TEXT

Display a club name containing & and another containing angle brackets. Make both appear as ordinary text, not HTML tags.

Need a hint?

Use HTML text escaping at output.

Reveal a possible solution
<?php
$clubs = ['Art & Design', '<Robotics>'];
foreach ($clubs as $club) {
    echo '<p>' . htmlspecialchars($club, ENT_QUOTES, 'UTF-8') . '</p>';
}

The browser displays literal characters. Inspect the response source for the escaped forms.

CHALLENGE 12 | CAPSTONE: A CLUB AVAILABILITY PAGE

Build a complete page from three nested club records. Use a function for remaining places, show Full at zero and a number otherwise, and total all membership counts. Escape club names.

Need a hint?

Combine data preparation, functions, foreach, selection and a running total.

Reveal a possible solution
<?php
function escapeHtml(string $text): string
{
    return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
}

function placesLeft(int $capacity, int $members): int
{
    return max(0, $capacity - $members);
}

$clubs = [
    ['name' => 'Robotics', 'capacity' => 12, 'members' => 10],
    ['name' => 'Game Design', 'capacity' => 16, 'members' => 16],
    ['name' => 'Art & Design', 'capacity' => 10, 'members' => 6],
];
$totalMembers = 0;
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>School clubs</title>
</head>
<body>
    <h1>School clubs</h1>
    <ul>
        <?php foreach ($clubs as $club): ?>
            <?php
            $remaining = placesLeft($club['capacity'], $club['members']);
            $totalMembers += $club['members'];
            ?>
            <li>
                <strong><?= escapeHtml($club['name']) ?></strong>:
                <?php if ($remaining > 0): ?>
                    <?= $remaining ?> places available
                <?php else: ?>
                    Full
                <?php endif; ?>
            </li>
        <?php endforeach; ?>
    </ul>
    <p>Total club memberships: <?= $totalMembers ?></p>
</body>
</html>

Expected: Robotics 2 places; Game Design Full; Art & Design 4 places; total club memberships 32. This total counts memberships, not necessarily unique students.

max(0, ...) clamps negative results for display in this sample; it does not validate the underlying data or enforce capacity. Add validation if you extend the requirements.

STRETCH | CHANGED DATA

Add a fourth club record without changing the foreach body. Test zero members, a full club and a name containing an ampersand. Predict the changed membership total.

Add a validation branch that reports invalid data if members exceeds capacity instead of only clamping the display. Explain why display formatting is different from data validation.

FINISH | EXPLAIN THE WHOLE REQUEST

Explain how a request reaches PHP, how data and functions create the response, and why refreshing does not automatically save changes to an array.

You should be able to identify a loop body, distinguish a parameter from an argument and explain return versus echo. Next, use these foundations in reusable page components, forms and sessions.

KEEP LEARNING

Previous page 02.1 Embedding PHP in HTML and reusable includes

References: PHP development server · Types · Arrays · HTML text escaping