Skip to main content

🐘 PHP for Backend Development

PHP is the quiet giant of the web — it runs WordPress, Wikipedia, and a huge chunk of every site you visit. Far from the messy language of its reputation, modern PHP 8 is fast, typed, and genuinely pleasant to write. This lesson gives you a working command of the language so you can build real server-side features.

🎯 Learning Objectives

By the end of this lesson, you will be able to:

  • Explain what server-side scripting is and how PHP fits into the request/response cycle
  • Write core PHP 8 syntax — variables, control structures, functions, and arrays — correctly
  • Build a small object-oriented program using classes, constructors, and inheritance
  • Weigh PHP's strengths and trade-offs against Node.js and Python for a given project
  • Run a PHP script locally with the built-in web server

Estimated Time: 35–45 minutes  •  Difficulty: Beginner

Hands-on: Build and run a tiny "greeting" script, then extend it into a small class.

In This Lesson

What Is PHP?

PHP (a recursive acronym for PHP: Hypertext Preprocessor) is an open-source scripting language designed from the ground up for the web. Where a language like Python is general-purpose and later grew web frameworks, PHP was born to generate web pages, and that focus still shows in how naturally it slots into HTML.

It was created by Rasmus Lerdorf in 1994 as a handful of C programs to track visits to his online résumé. Three decades later it powers roughly three-quarters of all websites whose server-side language is known — largely because WordPress alone runs more than 40% of the entire web.

💡 A useful analogy: If HTML is the printed page, PHP is the printing press that stamps out a fresh, personalized page for every visitor — inserting their name, their cart, today's date — before the paper ever reaches them.

📖 Key Terms

Interpreter: the PHP program that reads your .php files and executes the code inside them.

Server-side: code that runs on the web server, before the response is sent — the user never sees it.

Dynamic page: HTML that is generated fresh on each request rather than served from a static file.

PHP's evolution

PHP has improved dramatically. The jump to PHP 7 (2015) roughly doubled performance, and the PHP 8 line (2020 onward) added a JIT compiler, real type declarations, enums, and readonly properties. The syntax you'll learn here targets PHP 8.3+ — the modern, actively supported baseline.

timeline title The road to modern PHP 1995 : PHP/FI released publicly 1998 : PHP 3 — a real language with OOP basics 2004 : PHP 5 — Zend Engine 2, strong OOP 2015 : PHP 7 — ~2x faster, scalar type hints 2020 : PHP 8.0 — JIT, union types, named arguments 2023 : PHP 8.3 — typed constants, readonly refinements 2024 : PHP 8.4 — property hooks, asymmetric visibility

How Server-Side Scripting Works

The single most important thing to understand about PHP is where it runs. When a browser requests a .php page, the web server hands the file to the PHP interpreter, which executes any code and produces plain HTML. Only that finished HTML travels back to the browser — the PHP source never leaves the server.

The PHP request and response cycle A browser requests a PHP page; the web server passes it to the PHP interpreter, which may query a database, then returns finished HTML to the browser. Browser (the client) Web Server + PHP interpreter runs your .php Database MySQL / etc. 1. request 4. HTML 2. query 3. data
Figure 1 — PHP runs entirely on the server. The browser only ever receives the generated HTML, never the PHP code that produced it.

Because PHP was designed to mix with HTML, you can drop into and out of "PHP mode" using <?php ... ?> tags. Everything outside those tags is sent to the browser untouched:

<!DOCTYPE html>
<html>
<body>
    <h1>Welcome!</h1>

    <?php
    // Only this block is executed by PHP
    $hour = (int) date('H');
    if ($hour < 12) {
        echo '<p>Good morning.</p>';
    } elseif ($hour < 18) {
        echo '<p>Good afternoon.</p>';
    } else {
        echo '<p>Good evening.</p>';
    }
    ?>

    <p>This is plain HTML again.</p>
</body>
</html>

✅ Modern practice

In real applications you rarely sprinkle PHP throughout HTML like this. Instead you keep logic in .php classes and use a template engine (Twig, Blade) for the HTML. But understanding the embedded model explains why PHP works the way it does.

Core Syntax: Variables & Types

Every PHP variable starts with a $. PHP is dynamically typed — a variable's type is inferred from the value you assign — but modern PHP lets you add explicit type declarations where they matter (we'll see that with functions).

<?php
$name      = 'Ada';           // string
$age       = 36;              // int
$height    = 1.7;             // float
$isMember  = true;            // bool
$hobbies   = ['reading', 'chess'];  // array
$nickname  = null;            // null

// Double quotes interpolate variables; single quotes do not.
echo "Hi, {$name}. You are {$age}.";  // Hi, Ada. You are 36.
echo 'Hi, {$name}.';                   // Hi, {$name}.  (literal)

// The null coalescing operator supplies a fallback.
$display = $nickname ?? $name;         // 'Ada'

⚠️ Single vs. double quotes

This trips up newcomers constantly: only double quotes (and heredocs) expand variables. Use the {$var} brace form inside strings — it's unambiguous and works for array/object access too, e.g. "{$user['name']}".

Type juggling and strict types

PHP will happily convert types for you ("5" + 3 gives 8). That convenience can hide bugs, so professional projects turn on strict typing at the top of each file:

<?php
declare(strict_types=1);

// With strict_types on, passing a string where an int is
// declared throws a TypeError instead of silently converting.

Control Structures & Functions

PHP's control flow reads much like C, JavaScript, or Java — if/elseif/else, switch, and the usual loops. PHP 8 also added match, a stricter, expression-based cousin of switch.

<?php
$score = 82;

// match returns a value and uses strict (===) comparison
$grade = match (true) {
    $score >= 90 => 'A',
    $score >= 80 => 'B',
    $score >= 70 => 'C',
    default      => 'F',
};
echo $grade;  // B

// foreach is the workhorse loop for arrays
$colors = ['red', 'green', 'blue'];
foreach ($colors as $color) {
    echo $color . PHP_EOL;
}

// foreach with key => value
$person = ['name' => 'Ada', 'age' => 36];
foreach ($person as $key => $value) {
    echo "{$key}: {$value}" . PHP_EOL;
}

Functions with types

Modern PHP functions declare parameter and return types. This is the single biggest quality upgrade over old-style PHP — your editor and static analysers can catch mistakes before the code ever runs.

<?php
declare(strict_types=1);

// Typed parameters and a typed return value
function greet(string $name, string $greeting = 'Hello'): string
{
    return "{$greeting}, {$name}!";
}

echo greet('Ada');            // Hello, Ada!
echo greet('Bob', 'Hi');      // Hi, Bob!

// Variadic parameters collect extra arguments into an array
function total(float ...$amounts): float
{
    return array_sum($amounts);
}

echo total(1.5, 2.25, 3.0);   // 6.75

// Arrow functions (PHP 7.4+) capture outer scope automatically
$prices  = [10, 20, 30];
$withTax = array_map(fn ($p) => $p * 1.1, $prices);

Arrays — PHP's Swiss Army Knife

Arrays are everywhere in PHP. A single array type serves as both an ordered list (indexed) and a key/value map (associative), and the standard library ships hundreds of array_* helper functions.

<?php
// Indexed array (a list)
$fruits = ['apple', 'banana', 'orange'];
$fruits[] = 'grape';            // append
echo $fruits[0];                // apple

// Associative array (a map)
$user = [
    'name'  => 'Ada',
    'email' => 'ada@example.com',
];
echo $user['name'];             // Ada

// Nested / multidimensional
$users = [
    ['name' => 'Ada', 'admin' => true],
    ['name' => 'Bob', 'admin' => false],
];
echo $users[1]['name'];         // Bob

// Functional transforms
$numbers = [1, 2, 3, 4, 5];
$doubled = array_map(fn ($n) => $n * 2, $numbers);        // [2,4,6,8,10]
$evens   = array_filter($numbers, fn ($n) => $n % 2 === 0); // [2,4]
$sum     = array_reduce($numbers, fn ($c, $n) => $c + $n, 0); // 15

📖 The spaceship operator

PHP's <=> operator returns -1, 0, or 1 and makes custom sorting concise: usort($users, fn ($a, $b) => $a['name'] <=> $b['name']); sorts users alphabetically by name.

Object-Oriented PHP

Serious PHP is object-oriented. Classes bundle data (properties) with behaviour (methods), and PHP 8 makes classes remarkably compact with constructor property promotion — you declare and assign properties right in the constructor signature.

<?php
declare(strict_types=1);

class Person
{
    // Constructor property promotion: declares + assigns in one place
    public function __construct(
        public string $name,
        protected int $age,
        private string $email = ''
    ) {}

    public function greet(): string
    {
        return "Hi, I'm {$this->name}.";
    }

    public function getAge(): int
    {
        return $this->age;
    }
}

$ada = new Person('Ada', 36, 'ada@example.com');
echo $ada->greet();     // Hi, I'm Ada.
echo $ada->name;        // Ada  (public)
echo $ada->getAge();    // 36   (age is protected, reached via method)

Inheritance

A child class extends a parent, reusing its code and adding or overriding behaviour. Call the parent constructor with parent::__construct(...).

<?php
class Student extends Person
{
    public function __construct(
        string $name,
        int $age,
        public string $studentId = ''
    ) {
        parent::__construct($name, $age);
    }

    public function card(): string
    {
        return "{$this->name} (ID: {$this->studentId})";
    }
}

$bob = new Student('Bob', 20, 'S-12345');
echo $bob->card();      // Bob (ID: S-12345)
echo $bob->greet();     // Hi, I'm Bob.  (inherited)

💡 Visibility at a glance

public — reachable from anywhere. protected — this class and its subclasses. private — this class only. Default to the most restrictive level that still works; expose data through methods.

The Modern PHP Ecosystem

You rarely build PHP applications from scratch. A rich ecosystem of frameworks, tools, and a package manager sits on top of the language:

flowchart TD PHP[PHP 8] --> FW[Frameworks] PHP --> CMS[Content Systems] PHP --> COMP[Composer
+ Packagist] PHP --> QA[Quality & Testing] FW --> Laravel[Laravel] FW --> Symfony[Symfony] FW --> Slim[Slim] CMS --> WordPress[WordPress] CMS --> Drupal[Drupal] QA --> PHPUnit[PHPUnit / Pest] QA --> PHPStan[PHPStan]
ToolWhat it doesWhen you'll meet it
ComposerInstalls and manages library dependenciesEvery modern project (next lessons)
LaravelFull-featured web framework: routing, ORM, authMost new PHP web apps & APIs
SymfonyReusable components + enterprise frameworkLarge apps; powers parts of Laravel
PHPUnit / PestAutomated testingAny codebase you want to trust
PHPStanStatic analysis — finds bugs without running codeTeam & CI pipelines

PHP also excels at building JSON APIs. Here's a minimal REST-style endpoint in plain PHP using PDO (the safe, prepared-statement database layer):

<?php
declare(strict_types=1);
header('Content-Type: application/json');

$pdo = new PDO(
    'mysql:host=localhost;dbname=app;charset=utf8mb4',
    'user',
    'pass',
    [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);

// GET /users/42  -> fetch one user, safely (parameterised query)
$id   = (int) ($_GET['id'] ?? 0);
$stmt = $pdo->prepare('SELECT id, name, email FROM users WHERE id = ?');
$stmt->execute([$id]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);

echo json_encode($user ?: ['error' => 'Not found']);

⚠️ Always use prepared statements

Never build a query by pasting user input into a string — that's how SQL-injection attacks happen. The ? placeholder with execute([$id]) keeps data and code separate. This is non-negotiable in production PHP.

PHP vs. Node.js & Python

No backend language is "best" — each has a sweet spot. Knowing where PHP shines (and where it doesn't) helps you choose well.

AspectPHPNode.jsPython
Execution modelRequest-per-process (shared-nothing)Single-threaded event loopRequest-per-process (usually)
Sweet spotCMS, e-commerce, web apps & APIsReal-time apps, sockets, microservicesData science, ML, scripting, web
HostingSupported almost everywhere, cheaplyNeeds a Node runtimeWidely available
HTML integrationNative — the whole pointVia template librariesVia template engines
ConcurrencyHandled by the web server per requestExcellent, built inImproving (async/await)

✅ Reach for PHP when…

  • You're building or extending a CMS/e-commerce site (WordPress, Magento, Drupal).
  • You want to ship a database-backed web app or API quickly with Laravel.
  • Cheap, universal shared hosting matters.

💡 Consider alternatives when…

You need heavy real-time features (chat, live dashboards) — Node's event loop fits better — or your project is data-science/ML heavy, where Python's ecosystem is unmatched.

Hands-on Exercise

🏋️ From script to class

Objective: Write, run, and then refactor a small piece of PHP — no framework, no database.

Instructions:

  1. Create a folder and a file greet.php.
  2. Write a typed function greet(string $name): string that returns "Hello, NAME! Welcome to PHP."
  3. Call it for three different names and echo each result on its own line.
  4. Run it from the terminal with PHP's built-in server: php -S localhost:8000, then open http://localhost:8000/greet.php. (Or run php greet.php directly on the command line.)
  5. Refactor: wrap the behaviour in a Greeter class with a for($name) method, and produce the same output.
💡 Hint

Start the file with <?php declare(strict_types=1);. For the class version, use constructor property promotion to store a default greeting, e.g. public function __construct(private string $greeting = 'Hello') {}. Use PHP_EOL for line breaks so output looks right in both the terminal and the browser source.

✅ Sample solution
<?php
declare(strict_types=1);

// --- Function version ---
function greet(string $name): string
{
    return "Hello, {$name}! Welcome to PHP." . PHP_EOL;
}

foreach (['Ada', 'Bob', 'Cleo'] as $name) {
    echo greet($name);
}

// --- Class version (same output) ---
class Greeter
{
    public function __construct(private string $greeting = 'Hello') {}

    public function for(string $name): string
    {
        return "{$this->greeting}, {$name}! Welcome to PHP." . PHP_EOL;
    }
}

$greeter = new Greeter();
foreach (['Ada', 'Bob', 'Cleo'] as $name) {
    echo $greeter->for($name);
}

Both loops print the same three lines. The class version is easy to extend — change the greeting once in the constructor and every call updates.

🎯 Quick Quiz

Question 1: Where does PHP code execute in the request/response cycle?

Question 2: Which string will interpolate the variable $name?

Question 3: Why should database queries use prepared statements with placeholders?

Summary & Quiz

🎉 Key Takeaways

  • PHP is a server-side language built for the web; the browser only ever sees the HTML it generates.
  • Modern PHP 8 is fast and typed — use declare(strict_types=1), typed functions, and match.
  • Arrays serve as both lists and maps, backed by a huge array_* toolkit.
  • OOP with constructor property promotion keeps classes concise; respect public/protected/private.
  • Always use prepared statements for database access to prevent SQL injection.
  • PHP shines for CMS, e-commerce, and database-backed web apps & APIs.

📚 Further Reading

🚀 What's Next?

You can write PHP — now you need somewhere to run it. Next we'll set up a complete PHP development environment: the interpreter, a local server, a database, and an editor tuned for PHP with step-through debugging.

🎉 Great start!

You've got working PHP under your belt. Let's build the workshop you'll write it in.