In its own words, PHP is “a popular general-purpose scripting language that is especially suited to web development”.1 While PHP is indeed popular coming in 10th in the Stack Overflow Developer Survey, it was originally developed by a single guy, Rasmus Lerdorf, for use on his Personal Home Page (yes, that’s where the acronym comes from). It was therefore not written with great concern for security. This does not mean that PHP applications are inherently insecure, but rather that you should be especially careful when writing in PHP.

On the positive side, PHP is relatively easy to get started with and has many features that make it convenient for web development.

Okay, so how do we get started? To get started, create the file hello.php and add the following to it:

<?php
    echo 'Hello PHP!';
?>

Now go to http://localhost/hello.php in your browser. You should see the text “Hello PHP!” pop up on screen. We have just written out very first piece of PHP!

When our web server reads the file hello.php, it looks for the <?php and ?> opening and closing tags that we placed in the file. If it finds any, it will interpret everything in between as PHP code and replace it with the result of evaluating the code. We can have other stuff on the page as well:

<!DOCTYPE html>
<html>
    <head>
        <title> <?php echo 'Hello PHP!'; ?></title>
    </head>
    <body>
        <?php echo 'Cool!'; ?>
    </body>
</html>

If you reload the page, you should see that the title is “Hello PHP!” and the text “Cool!” in the body.

It is important to remember that the browser has nothing to do with evaluating the PHP code. In principle, it is completely unaware that php is being used. The web server evaluates the PHP code and replaces it with the result of the evaluation, which it then sends to the browser.

Now we can start adding the back end to our site! Let’s recall the features that we want to implement. We want users to be able to guess a number, so there should somehow be a number to guess. Multiple users might be using the site at the same time and we don’t want all of the to try and guess the same number. We also want the users to accumulate internet points but we certainly don’t want all users to have the same number of internet points. What we need is a way to store information local to the current “session”. This is such a common scenario that PHP has built in support for this. PHP does this by using session cookies. Basically, whenever we start a session (which we will see how to do in a minute) PHP sends a cookie containing and id to the user. When the user requests the page again the browser will include this cookie in the request and we can use the id to identify the user an retrieve any information that we associated with it. Let’s see how to do this in practice. Add the following to the top of index.html:

<?php
    //Start the session
    session_start();

    // We check if an "answer" is already associated with this session. 
    // If this is not the case, we geenrate one randomly.
    // You can read the documentation for isset here: https://www.php.net/manual/en/function.isset.php
    if (!isset($_SESSION["answer"])) {
        $_SESSION["answer"] = random_int(0,10);
    }

    // This is just to show what is actually stored in the $_SESSION variable.
    var_dump($_SESSION);
?>

If you reload the page you should see array(1) { ["answer"]=> int(4) } (possibly with a different number) in the top left corner of the page. If you reload the page, the number does not change. Cool right? This information is linked to the session and we can use it to personalize responses.

$_SESSION is a predefined variable in PHP. It is available in all scripts and automatically initialized with session data by PHP. Another predefined variable is $_GET. $_GET is automatically initialized with the GET parameters of the request. You can read more about predefined variables in the documentation.

Let’s use our newfound knowledge to implement accumulating internet points and guess-checking:

<?php
//Start the session
session_start();

// We check if an "answer" is already associated with this session. 
// If this is not the case, we geenrate one randomly.
// You can read the documentation for isset here: https://www.php.net/manual/en/function.isset.php
if (!isset($_SESSION["answer"])) {
    $_SESSION["answer"] = random_int(0,10);
}

// If "internet_points" is not set, we initialize it to 0.
if (!isset($_SESSION["internet_points"])) {
    $_SESSION["internet_points"] = 0;
}

// Generate a prompt to inform the user about the result of their guess.
// By default, we just tell the user to submit a guess.
$prompt = "Try to guess the number by entering it above and hitting submit";

// If the users submitted a guess
if (isset($_GET["guess"])) {
    $guess = $_GET["guess"];

    // Convert the answer to a string for comparison. GET parameters are always strings
    $answer = strval($_SESSION["answer"]);

    if ($guess == $answer) {
        $prompt = "You got it!";

        // Award the user with an internet point.
        $_SESSION["internet_points"]++;

        // Generate a new answer
        $_SESSION["answer"] = random_int(0, 10);
    } else {
        // If the user did not guess correctly, tell the user to try again.
        $prompt = "Oh no! Try again";
    }
}
?>

Now we just need to insert the prompt and the internet points in appropriate places on the page. The final result should look something like:

<?php
//Start the session
session_start();

// We check if an "answer" is already associated with this session. 
// If this is not the case, we geenrate one randomly.
// You can read the documentation for isset here: https://www.php.net/manual/en/function.isset.php
if (!isset($_SESSION["answer"])) {
    $_SESSION["answer"] = random_int(0,10);
}

// If "internet_points" is not set, we initialize it to 0.
if (!isset($_SESSION["internet_points"])) {
    $_SESSION["internet_points"] = 0;
}

// Generate a prompt to inform the user about the result of their guess.
// By default, we just tell the user to submit a guess.
$prompt = "Try to guess the number by entering it above and hitting submit";

// If the users submitted a guess
if (isset($_GET["guess"])) {
    $guess = $_GET["guess"];

    // Convert the answer to a string for comparison. GET parameters are always strings
    $answer = strval($_SESSION["answer"]);

    if ($guess == $answer) {
        $prompt = "You got it!";

        // Award the user with an internet point.
        $_SESSION["internet_points"]++;

        // Generate a new answer
        $_SESSION["answer"] = random_int(0, 10);
    } else {
        // If the user did not guess correctly, tell the user to try again.
        $prompt = "Oh no! Try again";
    }
}
?>
<!DOCTYPE html>
<html>
<head>
    <title>Guess the number</title>
    <style>
        html, body {
            margin: 0;
            height: 100%;
        }

        #wrapper {
            height: 100%;
            width: 100%;
            background: #ededed;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        
        #container {
            height: 500px;
            width: 300px;
            padding: 20px;
            background: white;
            top: 50%;
            box-shadow: 5px 5px 15px 5px rgba(0,0,0,0.25);
        }
    </style>
</head>
<body>
    <div id="wrapper">
        <!-- The if of this div was previously main-container. It has now been corrected to container to match the CSS selector -->
        <div id="container">
            <h2>Guess the number</h2>
            <form action="/">
                <input name="guess" type="number" autofocus />
                <input type="submit" />
            </form>
            <p><?php echo $prompt ?></p>
            <p>Internet points: <?php echo $_SESSION["internet_points"] ?></p>
        </div>
    </div>
</body>
</html>

We are almost there! Try to play around with it in your browser and convince yourself that it really does work as described.

You might notice that it can take some time to guess the number. In an attempt to fix this, we will add the possibility for the user to get hints. We cannot just send the answer to the browser and have it display some sort of hint. We must never send confidential information to clients, even though we do not actually show it on the page. Remember: we are just sending plain text to the browser. Nothing is preventing the user from inspecting the responses and reading any information that we might have hidden from the visual output produced by the browser. This is perhaps one of the most common mistakes that beginners make. As a general principle, we cannot rely on what the browser does for security purposes! If information should not be read by the user, we must not send it to them.

With this in mind, let’s implement the back end of the hint feature. Create a file named get_hint.php with the following content:

<?php
session_start();

if (!isset($_SESSION["answer"])) {
    http_response_code(302);
    header("Location: /index.php");
    exit;
}

$answer = $_SESSION["answer"];

if ($answer <= 5) {
    echo "The value is between 0 and 5";
} else {
    echo "The value is between 6 and 10";
}
?>

This page will simply return a hint of the form that we described on the welcome page.

PHP Documentation

The best place to find php documentation is the PHP Webpage. It has up-to-date documentation of all built in function and user-contributed examples for each one. Be careful copy-pasting PHP that you do not understand! Some of the user-contributed examples exhibit generally unsafe practices.

There is a large community of people using PHP and various frameworks based on PHP. There is almost always help to find on pages like stackoverflow.