PHP
02 / 06

Web Features, Database & Error Handling

PHP: Web Features, Database & Error Handling

Superglobals & Request Handling

<?php

// Input (always sanitize/validate before use)
$name = filter_input(INPUT_GET, 'name', FILTER_SANITIZE_SPECIAL_CHARS);
$age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT);
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);

// Raw access (validate before trusting)
$_GET['query'];          // URL params
$_POST['data'];          // POST body (form-encoded)
$_SERVER['REQUEST_METHOD'];
$_SERVER['HTTP_USER_AGENT'];
$_SERVER['REMOTE_ADDR'];
$_SERVER['REQUEST_URI'];

// JSON body (APIs)
$body = json_decode(file_get_contents('php://input'), associative: true);
$userId = $body['user_id'] ?? null;

// File uploads
if (isset($_FILES['photo']) && $_FILES['photo']['error'] === UPLOAD_ERR_OK) {
    $tmpPath = $_FILES['photo']['tmp_name'];
    $fileName = basename($_FILES['photo']['name']);
    // Validate MIME type!
    $mimeType = mime_content_type($tmpPath);
    if (in_array($mimeType, ['image/jpeg', 'image/png', 'image/webp'])) {
        move_uploaded_file($tmpPath, '/uploads/' . uniqid() . '_' . $fileName);
    }
}

// Sessions
session_start();
$_SESSION['user_id'] = 42;
$_SESSION['cart'] = [];
session_regenerate_id(delete_old_session: true);  // prevent fixation
session_destroy();

// Cookies
setcookie('remember_token', $token, [
    'expires' => time() + 86400 * 30,
    'path' => '/',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Lax',
]);

PDO — Database Access

<?php

// Connect
$pdo = new PDO(
    'mysql:host=localhost;dbname=myapp;charset=utf8mb4',
    'user',
    'password',
    [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES => false,
    ]
);

// Prepared statements (always use — prevents SQL injection)
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ? AND active = ?');
$stmt->execute([$email, true]);
$user = $stmt->fetch();

// Named placeholders
$stmt = $pdo->prepare('INSERT INTO users (name, email, created_at) VALUES (:name, :email, NOW())');
$stmt->execute(['name' => $name, 'email' => $email]);
$id = $pdo->lastInsertId();

// Fetch multiple rows
$stmt = $pdo->prepare('SELECT * FROM articles WHERE status = ? ORDER BY created_at DESC LIMIT ?');
$stmt->execute(['published', 10]);
$articles = $stmt->fetchAll();

// Single value
$count = $pdo->query('SELECT COUNT(*) FROM users')->fetchColumn();

// Transactions
try {
    $pdo->beginTransaction();
    $pdo->prepare('UPDATE accounts SET balance = balance - ? WHERE id = ?')
        ->execute([$amount, $fromId]);
    $pdo->prepare('UPDATE accounts SET balance = balance + ? WHERE id = ?')
        ->execute([$amount, $toId]);
    $pdo->commit();
} catch (\Exception $e) {
    $pdo->rollBack();
    throw $e;
}

Error Handling & Exceptions

<?php

// Custom exception hierarchy
class AppException extends \RuntimeException {}
class ValidationException extends AppException {
    public function __construct(private array $errors) {
        parent::__construct('Validation failed');
    }
    public function getErrors(): array { return $this->errors; }
}
class NotFoundException extends AppException {}

// Structured error handling
function findUser(int $id): array
{
    $user = $db->find($id);
    if ($user === null) {
        throw new NotFoundException("User $id not found");
    }
    return $user;
}

try {
    $user = findUser($id);
} catch (NotFoundException $e) {
    http_response_code(404);
    echo json_encode(['error' => $e->getMessage()]);
} catch (ValidationException $e) {
    http_response_code(422);
    echo json_encode(['errors' => $e->getErrors()]);
} catch (\Throwable $e) {  // catches Error + Exception
    error_log($e->getMessage());
    http_response_code(500);
    echo json_encode(['error' => 'Internal server error']);
} finally {
    // Always runs
}

// Global error handler
set_exception_handler(function (\Throwable $e) {
    error_log($e->getMessage() . '\n' . $e->getTraceAsString());
    http_response_code(500);
    echo json_encode(['error' => 'Unexpected error']);
});

// Error to exception conversion
set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline) {
    throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
});

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free