PHP Tutorial

PHP (PHP: Hypertext Preprocessor) is a widely-used server-side scripting language for building dynamic websites. It powers WordPress, Laravel, Drupal, and millions of websites.

What is PHP?

  • Server-side language - code runs on the server, outputs HTML to the browser.
  • Easy to embed inside HTML using <?php ... ?> tags.
  • Works with Apache/Nginx (XAMPP, WAMP, LAMP stacks).
  • Current version: PHP 8.x (with JIT compilation, named args, enums, fibers).
PHP
<!DOCTYPE html>
<html><body>

<?php
  echo "<h1>Hello, World!</h1>";
  echo "PHP version: " . phpversion();
?>

</body></html>
► Try It Yourself

Variables

PHP
<?php
// Variables start with $
$name    = "Alice";
$age     = 25;
$height  = 5.9;
$isAdmin = true;
$nothing = null;

// Variable variables
$varName = "greeting";
$$varName = "Hello!";   // creates $greeting = "Hello!"

// Constants (no $, no reassignment)
define("MAX_SIZE", 100);
const PI = 3.14159;

// Type checking
var_dump($age);        // int(25)
gettype($name);        // "string"
is_int($age);          // true
is_string($name);      // true
is_null($nothing);     // true
isset($name);          // true (exists and not null)
empty("");             // true (empty string/0/null/false)

// Type casting
$str  = (string) 42;    // "42"
$num  = (int) "42px";   // 42
$bool = (bool) "";      // false
?>
► Try It Yourself

Strings

PHP
<?php
$s = "Hello, World!";

// Functions
strlen($s);                   // 13
strtoupper($s);               // "HELLO, WORLD!"
strtolower($s);               // "hello, world!"
ucfirst("hello world");       // "Hello world"
ucwords("hello world foo");   // "Hello World Foo"
trim("  hello  ");            // "hello"
ltrim(" hello"); rtrim("hello ");

str_replace("World", "PHP", $s);      // "Hello, PHP!"
str_contains($s, "World");            // true  (PHP 8+)
str_starts_with($s, "Hello");         // true  (PHP 8+)
str_ends_with($s, "!");               // true  (PHP 8+)
strpos($s, "o");              // 4 (first occurrence)
strrpos($s, "o");             // 8
substr($s, 7, 5);             // "World"
str_repeat("ha", 3);          // "hahaha"
str_pad("5", 3, "0", STR_PAD_LEFT);   // "005"
str_split("hello", 2);        // ["he","ll","o"]
explode(", ", "a, b, c");     // ["a","b","c"]
implode(", ", ["a","b","c"]); // "a, b, c"
sprintf("Name: %s, Age: %d", "Alice", 25); // formatted string
number_format(1234567.891, 2, ".", ",");    // "1,234,567.89"

// Heredoc (multi-line)
$message = <<<EOT
Dear $name,
  Welcome to EduSmartUp!
EOT;

// Nowdoc (no variable interpolation)
$raw = <<<'EOT'
No $variable interpolation here.
EOT;
?>
► Try It Yourself

Arrays

PHP
<?php
// Indexed array
$fruits = ["apple", "banana", "cherry"];
$same   = array("apple", "banana");  // old syntax

// Associative array
$user = [
  "name"  => "Alice",
  "age"   => 25,
  "email" => "alice@example.com"
];

// Access
$fruits[0];          // "apple"
$user["name"];       // "Alice"
$user["age"];        // 25

// Modify
$fruits[] = "date";                  // append
$fruits[0] = "avocado";             // modify
$user["phone"] = "+91-999";         // add key

// Array functions
count($fruits);                      // 3
array_push($fruits, "elderberry");
array_pop($fruits);
array_shift($fruits);               // remove first
array_unshift($fruits, "avocado");  // add to front
array_merge($fruits, ["fig"]);      // merge arrays
array_slice($fruits, 1, 2);        // subset
array_splice($fruits, 1, 1);       // remove in place
in_array("banana", $fruits);       // true
array_key_exists("name", $user);   // true
array_keys($user);                  // ["name","age","email"]
array_values($user);                // ["Alice",25,"alice@..."]
array_flip($user);                  // swap keys and values
sort($fruits);                      // sort indexed (in-place)
asort($user);                       // sort assoc by value
ksort($user);                       // sort assoc by key
array_unique([1,2,2,3]);            // [1,2,3]
array_reverse($fruits);
array_map('strtoupper', $fruits);   // apply to each
array_filter($fruits, fn($f) => strlen($f) > 5);
array_search("banana", $fruits);    // returns key

// Loop
foreach ($user as $key => $value) {
  echo "$key: $value<br>";
}
?>
► Try It Yourself

Functions

PHP
<?php
// Function declaration
function greet(string $name, string $greeting = "Hello"): string {
  return "$greeting, $name!";
}
echo greet("Alice");        // "Hello, Alice!"
echo greet("Bob", "Hi");    // "Hi, Bob!"

// Variadic (PHP 5.6+)
function sum(int ...$nums): int {
  return array_sum($nums);
}
echo sum(1, 2, 3, 4);  // 10

// Return multiple (via array)
function minmax(array $arr): array {
  return [min($arr), max($arr)];
}
[$lo, $hi] = minmax([3, 1, 4, 1, 5]);

// Anonymous function (closure)
$square = function(int $n): int { return $n * $n; };
echo $square(5);  // 25

// Arrow function (PHP 7.4+)
$double = fn($n) => $n * 2;

// Use parent scope in closure
$multiplier = 3;
$fn = function($n) use ($multiplier) { return $n * $multiplier; };

// Built-in functions
abs(-5);         floor(4.9);       ceil(4.1);
round(4.567, 2); pow(2, 10);       sqrt(16);
rand(1, 100);    mt_rand(1, 1000); // faster random
date("Y-m-d");   time();          mktime(0,0,0,12,25,2024);
?>
► Try It Yourself

Forms & GET/POST

PHP
<!-- HTML Form -->
<form method="POST" action="process.php">
  <input type="text"  name="name" required />
  <input type="email" name="email" required />
  <input type="submit" value="Submit" />
</form>

<?php // process.php
// ALWAYS sanitize user input!
$name  = htmlspecialchars(trim($_POST["name"]  ?? ""));
$email = htmlspecialchars(trim($_POST["email"] ?? ""));

if (empty($name)) {
  echo "Name is required!";
  exit;
}

if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
  echo "Invalid email!";
  exit;
}

echo "Welcome, $name!";

// GET parameters (from URL like ?id=5&page=2)
$id   = filter_input(INPUT_GET, "id",   FILTER_VALIDATE_INT);
$page = filter_input(INPUT_GET, "page", FILTER_VALIDATE_INT) ?? 1;

// File upload
if ($_SERVER["REQUEST_METHOD"] === "POST") {
  $file    = $_FILES["upload"];
  $allowed = ["image/jpeg", "image/png", "image/gif"];
  if (in_array($file["type"], $allowed) && $file["size"] < 2_000_000) {
    move_uploaded_file($file["tmp_name"], "uploads/" . basename($file["name"]));
  }
}
?>
► Try It Yourself

Sessions & Cookies

PHP
<?php
// Sessions - stored server-side
session_start(); // MUST be called before any output

$_SESSION["user_id"]   = 42;
$_SESSION["user_name"] = "Alice";
$_SESSION["role"]      = "admin";

echo $_SESSION["user_name"]; // "Alice"

// Destroy session (logout)
session_unset();    // clear all session variables
session_destroy();  // destroy session

// Cookies - stored client-side (avoid storing sensitive data)
setcookie("theme", "dark", time() + 86400 * 30, "/"); // expires in 30 days
echo $_COOKIE["theme"];

// Delete cookie
setcookie("theme", "", time() - 3600, "/");
?>
► Try It Yourself

PDO - Database Access

PHP
<?php
// Connect using PDO (supports MySQL, PostgreSQL, SQLite)
try {
  $pdo = new PDO(
    "mysql:host=localhost;dbname=shop;charset=utf8mb4",
    "db_user",
    "db_password",
    [PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
     PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
     PDO::ATTR_EMULATE_PREPARES   => false]
  );
} catch (PDOException $e) {
  die("Connection failed: " . $e->getMessage());
}

// SELECT (prepared statement prevents SQL injection)
$stmt = $pdo->prepare("SELECT * FROM products WHERE category = ? AND price < ?");
$stmt->execute(["Electronics", 50000]);
$products = $stmt->fetchAll();

foreach ($products as $p) {
  echo $p["name"] . " - ?" . $p["price"] . "<br>";
}

// Named placeholders
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email");
$stmt->execute([":email" => "alice@example.com"]);
$user = $stmt->fetch();

// INSERT
$stmt = $pdo->prepare(
  "INSERT INTO users (name, email, password) VALUES (:name, :email, :password)"
);
$stmt->execute([
  ":name"     => "Alice",
  ":email"    => "alice@example.com",
  ":password" => password_hash("secret123", PASSWORD_BCRYPT)
]);
$newId = $pdo->lastInsertId();

// UPDATE
$pdo->prepare("UPDATE users SET city = ? WHERE id = ?")->execute(["Delhi", $id]);

// DELETE
$pdo->prepare("DELETE FROM users WHERE id = ?")->execute([$id]);

// Verify password
$hash = $user["password"];
if (password_verify($inputPassword, $hash)) {
  echo "Login successful!";
}
?>
► Try It Yourself
Security: Always use prepared statements with PDO. Never concatenate user input into SQL queries - that causes SQL Injection attacks.

Security Basics

PHP is powerful, but beginner apps often become insecure because input is trusted too early. Treat every request value as untrusted data.

  • Use prepared statements for database queries to stop SQL injection.
  • Escape output with htmlspecialchars() to reduce XSS risk.
  • Hash passwords with password_hash() and verify with password_verify().
  • Regenerate session IDs after login with session_regenerate_id(true).
  • Protect forms with CSRF tokens for state-changing requests.
PHP
<?php
$pdo = new PDO($dsn, $user, $pass);
$stmt = $pdo->prepare('SELECT id, email FROM users WHERE email = :email');
$stmt->execute(['email' => $_POST['email'] ?? '']);

$safeName = htmlspecialchars($user['name'], ENT_QUOTES, 'UTF-8');
echo "<h2>Welcome, {$safeName}</h2>";
?>

Validation & Sanitization

Validation checks whether data is acceptable. Sanitization transforms data into a safer format. You usually need both.

TaskExample
Validate emailfilter_var($email, FILTER_VALIDATE_EMAIL)
Convert to integerfilter_var($id, FILTER_VALIDATE_INT)
Escape outputhtmlspecialchars($text)
Trim whitespacetrim($_POST['name'] ?? '')

Composer

Composer is PHP's dependency manager. It lets you install packages, define autoloading, and keep environments consistent.

Terminal + JSON
composer init
composer require vlucas/phpdotenv

{
  "require": {
    "vlucas/phpdotenv": "^5.6"
  },
  "autoload": {
    "psr-4": {
      "App\\": "src/"
    }
  }
}