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