cv.cm

Coding · Programming languages

PHP tutorial for beginners

6 min read

Short answer

PHP is a server-side scripting language built for the web: a PHP file runs on the server and sends HTML or JSON to the browser. Install PHP, save <?php echo "Hello, world"; as hello.php and run php hello.php, or start a local server with php -S localhost:8000. The core ideas are $ variables, flexible arrays, functions with type declarations, classes, exceptions, and safe handling of user input.

Open JSON formatter

What PHP is and what it is used for

PHP was created by Rasmus Lerdorf in 1994; the name now stands for "PHP: Hypertext Preprocessor". It runs on almost every web host and powers a large share of websites, including WordPress, Drupal and Wikipedia's MediaWiki. Developers use it for content sites, online shops, REST APIs and full web applications with frameworks such as Laravel and Symfony. Modern PHP 8 has a type system, a JIT compiler, enums, attributes and much better performance than older versions.

Install PHP and run Hello, world

Install PHP from php.net or a package manager (brew install php, sudo apt install php-cli, or a bundle such as XAMPP on Windows). Check it with php -v. PHP code goes between <?php and an optional closing ?> tag.

<?php
echo "Hello, world\n";
php hello.php
# Hello, world
php -S localhost:8000    # serve the current folder at http://localhost:8000

In files that contain only PHP code, leave out the closing ?> tag, so no stray whitespace is sent to the browser by accident.

Variables and basic types

Variable names start with $. Types are dynamic, but you can declare parameter and return types, and declare(strict_types=1); at the top of a file stops automatic conversions in function calls.

TypeExampleNotes
int$n = 42;64-bit on most systems
float$x = 3.14;Double precision
string$s = "hi $name";Double quotes interpolate, single quotes do not
bool$ok = true;Case-insensitive keyword
array$a = [1, 2];Ordered map: list and dictionary in one
null$v = null;No value
<?php
$name = "Ada";
$count = 7;
echo "$name has $count items\n";        // Ada has 7 items
echo 'No $interpolation here' . "\n";   // No $interpolation here
echo intdiv($count, 2), " ", $count / 2, "\n";  // 3 3.5
var_dump((int) "12" + 1);                // int(13)

The . operator joins strings; + is only for numbers.

Control flow

<?php
$score = 72;
if ($score >= 90) {
    echo "A\n";
} elseif ($score >= 70) {
    echo "B\n";                   // B
} else {
    echo "C\n";
}

for ($i = 0; $i < 3; $i++) {
    echo $i, " ";                 // 0 1 2
}
echo "\n";

foreach (["apple", "pear"] as $fruit) {
    echo $fruit, "\n";
}

$kind = match ($day = "SAT") {   // match is strict and returns a value
    "SAT", "SUN" => "weekend",
    default => "weekday",
};
echo $kind, "\n";                 // weekend

match (PHP 8.0 and later) compares with === and throws an error when no arm matches, unlike the older switch, which compares loosely and falls through without break.

Functions

<?php
declare(strict_types=1);

function greet(string $name, string $greeting = "Hello"): string
{
    return "$greeting, $name!";
}

echo greet("Lin"), "\n";                    // Hello, Lin!
echo greet(greeting: "Hi", name: "Lin"), "\n"; // Hi, Lin!  (named arguments)

$square = fn(int $x): int => $x * $x;       // arrow function
echo $square(5), "\n";                      // 25

function total(int ...$nums): int           // variadic
{
    return array_sum($nums);
}
echo total(1, 2, 3), "\n";                  // 6

Signature feature: arrays

The PHP array is one flexible type that works as a list, a dictionary, a stack or a queue. Keys are integers or strings, and insertion order is kept. A large set of built-in functions works on arrays.

<?php
$nums = [3, 1, 2];
$nums[] = 5;                       // append
sort($nums);
echo implode(", ", $nums), "\n";   // 1, 2, 3, 5

$ages = ["ann" => 31, "bob" => 25];
$ages["cy"] = 40;
foreach ($ages as $person => $age) {
    echo "$person is $age\n";
}
echo $ages["zed"] ?? 0, "\n";      // 0  (null coalescing)

$evens = array_filter($nums, fn($n) => $n % 2 === 0);
$squares = array_map(fn($n) => $n * $n, $nums);
echo json_encode(array_values($evens)), " ", json_encode($squares), "\n";  // [2] [1,4,9,25]
echo count($ages), " ", array_key_exists("bob", $ages) ? "yes" : "no", "\n"; // 3 yes

Arrays are copied on assignment (copy-on-write), unlike objects, which are passed by handle.

Classes, constructor promotion and enums

<?php
declare(strict_types=1);

enum Role: string
{
    case Admin = "admin";
    case Viewer = "viewer";
}

final class User
{
    public function __construct(
        public readonly string $name,
        public readonly Role $role = Role::Viewer,
    ) {}

    public function label(): string
    {
        return "{$this->name} ({$this->role->value})";
    }
}

$u = new User("Ann", Role::Admin);
echo $u->label(), "\n";               // Ann (admin)
echo Role::from("viewer")->name, "\n"; // Viewer

Constructor promotion (PHP 8.0) declares and assigns properties in the constructor signature. readonly properties (8.1) can be set once, and backed enums (8.1) map cases to strings or integers. Interfaces, abstract classes and traits are also available.

Error handling

Modern PHP throws exceptions for most errors. Catch Exception subclasses for expected failures; Throwable also covers engine errors such as TypeError.

<?php
function parseAge(string $text): int
{
    if (!ctype_digit($text)) {
        throw new InvalidArgumentException("invalid age: $text");
    }
    return (int) $text;
}

try {
    echo parseAge("41"), "\n";   // 41
    echo parseAge("abc"), "\n";
} catch (InvalidArgumentException $e) {
    echo $e->getMessage(), "\n"; // invalid age: abc
} finally {
    echo "done\n";
}

A small complete program: a JSON API endpoint

Save this as api.php, run php -S localhost:8000, and open http://localhost:8000/api.php?name=Ann. It reads a query parameter, validates it and returns JSON.

<?php
declare(strict_types=1);

header("Content-Type: application/json; charset=utf-8");

$name = trim($_GET["name"] ?? "");
if ($name === "" || mb_strlen($name) > 50) {
    http_response_code(400);
    echo json_encode(["error" => "name must be 1 to 50 characters"]);
    exit;
}

$response = [
    "message" => "Hello, $name!",
    "length" => mb_strlen($name),
    "time" => date(DATE_ATOM),
];
echo json_encode($response, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);

$_GET, $_POST and $_COOKIE hold request data. Treat every value in them as untrusted.

Common beginner mistakes

  • Comparing with ==, which converts types; use === and !==.
  • Forgetting the $ on a variable name, or the semicolon at the end of a statement.
  • Storing passwords with md5 or sha1. Use password_hash and password_verify.
  • Using strlen on UTF-8 text; it counts bytes. Use mb_strlen for characters.
  • Running an old PHP version. Use a supported PHP 8 release for security fixes and modern features.

Where to go next

The official PHP Manual on php.net documents every function, with a language reference and user notes. Learn Composer, the package manager, and PSR coding standards, then try a framework: Laravel or Symfony for applications, or Slim for small APIs. PHPUnit is the standard testing tool.

FAQ

Is PHP still worth learning?

Yes. It runs a large part of the web, including WordPress sites, and modern PHP 8 with Laravel or Symfony is a productive way to build web applications. Jobs maintaining and building PHP systems are common.

Is PHP a frontend or backend language?

Backend. PHP runs on the server and sends the finished HTML, JSON or files to the browser, which never sees the PHP code.

What is the difference between echo and print?

Both output text. echo can take several comma-separated arguments and returns nothing; print takes one argument and returns 1. In practice most code uses echo.

What does declare(strict_types=1) do?

It makes scalar type declarations strict for function calls made from that file, so passing the string "5" to an int parameter throws a TypeError instead of being converted.

All coding tutorials