Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
PHP _first_!

PHP First

Generally speaking, your PHP code can be sorted into two categories:

  • code which does work (processing input, controller logic, database access, error handling, etc.), and
  • code which produces output (echo, <?= $var ?>, plain <html>, etc.).

work goes FIRST. output goes LAST.


a bad example

<?php

$page["id"]    = 1;
$page["title"] = "Hello, World!";

?>
<!doctype html>
<html>
    <head>
      <meta charset="utf-8">
      <title><?= $page["title"] ?></title>
    </head>
    <body>
<?php

session_start();
if (isset($_SESSION["user"])) {
    echo '<p class="welcome">Welcome, '.$_SESSION["user"].'!';
} else {
    echo '<p class="welcome">Welcome, Guest!</p>';
    echo '<a href="/login.php">Click Here to log in</a>';
}

?>
        <h1><?= $page["title"] ?></h1>
<?php

$DB = new PDO( … );
$stmt = $DB->prepare("SELECT heading,body FROM content WHERE page=:page");
$stmt->execute(["page" => $page["id"]]);
while ($row = $stmt->fetch()) {
    echo "<h2>".htmlspecialchars($row["heading"], ENT_QUOTES, "UTF-8")."</h2>";
    echo "<p>".htmlspecialchars($row["body"], ENT_QUOTES, "UTF-8");
}

?>
    </body>
</html>

As you might have guessed, this won't even work. For example, you'd say, "everyone knows session_start() has to be at the top of your script!!" (ahh, but why?)

But there are probably more problems than you think. What happens if there's an error connection to the database?

"Welcome, Guest! Fatal Error: uncaught PDOException with message 'here's my DB password!' ..."?

You can't even show a nice error page, because you've already started outputting this page.


a better example

<?php
session_start();

$page["id"]    = 1;
$page["title"] = "Hello, World!";
$user = isset($_SESSION["user"]) ? $_SESSION["user"] : "Guest";

try{
    $DB = new PDO( … );
    $stmt = $DB->prepare("SELECT heading,body FROM content WHERE page=:page");
    $stmt->execute(["page" => $page["id"]]);
    foreach ($stmt as $row) {
        $contents[] = [
            htmlspecialchars($row["heading"], ENT_QUOTES, "UTF-8"),
            htmlspecialchars($row["body"], ENT_QUOTES, "UTF-8")
        ];
    }
} catch (PDOException $e) {
    log_error($e->getMessage());
    header("Location: http://example.com/error-message.html");
    exit;
}

?>
<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title><?= $page["title"] ?></title>
    </head>
    <body>
        <p class="welcome">Welcome, <?= $user ?>!
<?php if ($user === "Guest") : ?>
        <p><a href="/login.php">Click Here to log in</a>
<?php endif; ?>
        <h1><?= $page["title"] ?></h1>
<?php foreach ($contents as list($heading, $body)) : ?>
        <h2><?= $heading ?></h2>
        <p><?= $body ?>
<?php endforeach; ?>
    </body>
</html>

Just a little bit of reorganization, and all the problems are gone. See how there's a clear, dividing line that separates your "behind-the-scenes" work on the server from the body of your response?


"php FIRST" is really the least you should be doing; but it is a big, positive step. If you do this and nothing more, my rage will be quieted. However, it's a solid foundation for learning about:

  • templating
  • separation of concerns

have fun!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.