Learn PHP Programming
Master PHP programming from basics to advanced concepts with our comprehensive tutorial series. Perfect for beginners and web developers.
PHP Error Handling
Robust error handling is critical for production applications. PHP provides exceptions, try/catch/finally blocks, custom exception classes, and global handlers. Since PHP 7, both errors and exceptions implement the Throwable interface, giving you a unified way to handle all runtime failures.
1. Try/Catch/Finally with Multiple Catch Blocks
<?php
declare(strict_types=1);
function fetchUserData(int $userId): array {
// Simulate different failure scenarios
if ($userId <= 0) {
throw new \InvalidArgumentException("User ID must be positive, got: {$userId}");
}
if ($userId > 1000) {
throw new \OverflowException('User ID exceeds maximum range');
}
if ($userId === 999) {
throw new \RuntimeException('Database connection timeout');
}
return ['id' => $userId, 'name' => 'User ' . $userId];
}
function getUserSafely(int $id): ?array {
$dbConnection = null;
try {
$dbConnection = 'connected'; // Simulate resource acquisition
$user = fetchUserData($id);
echo "Found: {$user['name']}\n";
return $user;
} catch (\InvalidArgumentException $e) {
// Handle validation errors specifically
echo "Validation Error: {$e->getMessage()}\n";
echo "Fix: Provide a valid positive user ID\n";
return null;
} catch (\OverflowException $e) {
// Handle range errors
echo "Range Error: {$e->getMessage()}\n";
return null;
} catch (\RuntimeException $e) {
// Handle infrastructure errors
echo "System Error: {$e->getMessage()}\n";
echo "File: {$e->getFile()}, Line: {$e->getLine()}\n";
error_log($e->getTraceAsString()); // Log full trace
return null;
} finally {
// ALWAYS executes - whether exception was thrown or not
// Perfect for cleanup: closing connections, releasing locks
if ($dbConnection !== null) {
$dbConnection = null; // Release resource
echo "Connection cleaned up\n";
}
}
}
// Test different scenarios
getUserSafely(42); // Found: User 42 + cleanup
getUserSafely(-1); // Validation Error + cleanup
getUserSafely(999); // System Error + cleanup
// PHP 8.0+ multi-catch with union types
try {
fetchUserData(0);
} catch (\InvalidArgumentException | \OverflowException $e) {
echo "Input Error: {$e->getMessage()}\n";
}
?>
2. Custom Exception Classes with Typed Properties
<?php
// Base application exception
class AppException extends \Exception {
private string $errorCode;
private array $context;
public function __construct(
string $message,
string $errorCode = 'APP_ERROR',
array $context = [],
int $httpStatus = 500,
?\Throwable $previous = null
) {
parent::__construct($message, $httpStatus, $previous);
$this->errorCode = $errorCode;
$this->context = $context;
}
public function getErrorCode(): string {
return $this->errorCode;
}
public function getContext(): array {
return $this->context;
}
public function toArray(): array {
return [
'error' => $this->errorCode,
'message' => $this->getMessage(),
'context' => $this->context,
'status' => $this->getCode()
];
}
}
// Specific exception types
class ValidationException extends AppException {
private array $errors;
public function __construct(array $errors, array $context = []) {
$this->errors = $errors;
$message = 'Validation failed: ' . implode(', ', $errors);
parent::__construct($message, 'VALIDATION_ERROR', $context, 422);
}
public function getErrors(): array {
return $this->errors;
}
}
class NotFoundException extends AppException {
public function __construct(string $resource, string|int $id) {
parent::__construct(
"{$resource} with ID '{$id}' not found",
'NOT_FOUND',
['resource' => $resource, 'id' => $id],
404
);
}
}
class AuthenticationException extends AppException {
public function __construct(string $reason = 'Invalid credentials') {
parent::__construct($reason, 'AUTH_FAILED', [], 401);
}
}
// Usage in application code
function findProduct(int $id): array {
$products = [1 => ['name' => 'Laptop'], 2 => ['name' => 'Phone']];
if (!isset($products[$id])) {
throw new NotFoundException('Product', $id);
}
return $products[$id];
}
function createOrder(array $data): array {
$errors = [];
if (empty($data['product_id'])) $errors[] = 'product_id is required';
if (empty($data['quantity'])) $errors[] = 'quantity is required';
if ($errors) {
throw new ValidationException($errors, ['input' => $data]);
}
return ['order_id' => 1, 'status' => 'created'];
}
// Catching custom exceptions
try {
$product = findProduct(99);
} catch (NotFoundException $e) {
echo $e->getMessage(); // Product with ID '99' not found
echo $e->getErrorCode(); // NOT_FOUND
echo $e->getCode(); // 404
$response = $e->toArray(); // Structured error response
}
?>
3. Global Exception Handler (set_exception_handler)
<?php
// Global handler catches any unhandled exceptions
set_exception_handler(function (\Throwable $e): void {
// Log the full error details
$logEntry = sprintf(
"[%s] %s: %s in %s:%d\nTrace: %s\n",
date('Y-m-d H:i:s'),
get_class($e),
$e->getMessage(),
$e->getFile(),
$e->getLine(),
$e->getTraceAsString()
);
error_log($logEntry);
// Show user-friendly response based on exception type
if ($e instanceof AppException) {
http_response_code($e->getCode());
echo json_encode($e->toArray());
} else {
// Generic error - never expose internals to users
http_response_code(500);
echo json_encode([
'error' => 'INTERNAL_ERROR',
'message' => 'An unexpected error occurred'
]);
}
});
// Convert PHP errors to exceptions
set_error_handler(function (
int $severity,
string $message,
string $file,
int $line
): bool {
// Don't handle suppressed errors (@operator)
if (!(error_reporting() & $severity)) {
return false;
}
throw new \ErrorException($message, 0, $severity, $file, $line);
});
// Register shutdown function for fatal errors
register_shutdown_function(function (): void {
$error = error_get_last();
if ($error !== null && in_array($error['type'], [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR])) {
error_log("FATAL: {$error['message']} in {$error['file']}:{$error['line']}");
http_response_code(500);
echo json_encode(['error' => 'FATAL_ERROR', 'message' => 'A fatal error occurred']);
}
});
// Now any unhandled exception gets caught gracefully
// throw new \RuntimeException('Unhandled!'); // Caught by global handler
?>
4. Error vs Exception Hierarchy (PHP 7+ Throwable)
<?php
/*
* PHP 7+ Throwable Hierarchy:
*
* Throwable (interface)
* ├── Error (internal engine errors)
* │ ├── TypeError
* │ ├── ValueError (PHP 8.0+)
* │ ├── ArithmeticError
* │ │ └── DivisionByZeroError
* │ ├── ParseError
* │ └── CompileError
* └── Exception (application-level errors)
* ├── LogicException
* │ ├── InvalidArgumentException
* │ ├── OutOfRangeException
* │ └── LengthException
* └── RuntimeException
* ├── OverflowException
* ├── UnderflowException
* └── UnexpectedValueException
*/
// Catching both Errors and Exceptions
function safeDivide(mixed $a, mixed $b): float|string {
try {
// TypeError if non-numeric, DivisionByZeroError if $b is 0
return $a / $b;
} catch (\TypeError $e) {
return "Type error: both arguments must be numeric";
} catch (\DivisionByZeroError $e) {
return "Cannot divide by zero";
} catch (\Throwable $e) {
// Catches ANYTHING - both Error and Exception subclasses
return "Unexpected error: {$e->getMessage()}";
}
}
echo safeDivide(10, 2); // 5
echo safeDivide(10, 0); // Cannot divide by zero
echo safeDivide('abc', 2); // Type error (in strict mode)
// Catching Error types that would previously be fatal
function loadClass(string $className): object {
try {
return new $className();
} catch (\Error $e) {
echo "Fatal error caught: {$e->getMessage()}\n";
return new \stdClass();
}
}
$obj = loadClass('NonExistentClass'); // Fatal error caught gracefully
// Exception chaining - preserve the original cause
function processFile(string $path): string {
try {
if (!file_exists($path)) {
throw new \RuntimeException("File not found: {$path}");
}
$content = file_get_contents($path);
return strtoupper($content);
} catch (\RuntimeException $e) {
// Wrap in domain-specific exception, preserve original
throw new AppException(
'Failed to process file',
'FILE_PROCESSING_ERROR',
['path' => $path],
500,
$e // Previous exception preserved
);
}
}
try {
processFile('/nonexistent.txt');
} catch (AppException $e) {
echo $e->getMessage(); // Failed to process file
echo $e->getPrevious()->getMessage(); // File not found: /nonexistent.txt
}
?>
Key Takeaways
- try/catch/finally: Use
tryfor risky code, multiplecatchblocks ordered from specific to general, andfinallyfor cleanup that must always run. - Custom exceptions add domain context (error codes, structured data, HTTP status) making error handling meaningful to your application.
- set_exception_handler provides a safety net for uncaught exceptions — log details internally, show safe messages externally.
- set_error_handler converts legacy PHP warnings/notices into exceptions for consistent handling.
- Throwable hierarchy: Since PHP 7, both
Error(engine) andException(application) implementThrowable. Catch\Throwableto handle everything. - Exception chaining: Pass the original exception as the
$previousparameter to preserve the full error trail for debugging. - Union catch: PHP 8.0+ supports
catch (TypeA | TypeB $e)for handling multiple exception types identically.
display_errors = Off and log_errors = On. Use structured logging (JSON format) for error details, and never expose stack traces, file paths, or database errors to end users. Implement a global exception handler that returns consistent error response formats (especially for APIs), and use exception chaining to preserve the root cause while presenting user-friendly messages.
Frequently Asked Questions
PHP Programming Tutorial — Learn PHP from Scratch
PHP (PHP: Hypertext Preprocessor) is the most widely-used server-side scripting language for web development. It powers over 77% of all websites with known server-side languages, including WordPress, Facebook, Wikipedia, and Slack. This comprehensive tutorial series takes you from complete beginner to confident PHP developer with hands-on examples you can run and modify.
Each topic in this tutorial includes multiple runnable code examples with line-by-line explanations, best practice tips, and navigation to the next logical concept. Whether you are learning PHP for the first time or refreshing your knowledge of a specific feature, every page is designed to give you practical, immediately-usable code.
What You Will Learn in This PHP Tutorial
- Basics: Syntax, variables, constants, data types, operators
- Strings & Arrays: Manipulation, searching, sorting, multidimensional arrays
- Control Flow: if/else, switch, for, while, foreach loops
- Functions: Parameters, return values, scope, anonymous functions
- Superglobals: $_GET, $_POST, $_SESSION, $_COOKIE, $_SERVER
- Forms: Handling user input, validation, file uploads
- File Handling: Reading, writing, and manipulating files
- Sessions & Cookies: User state management across requests
- OOP: Classes, objects, inheritance, interfaces, traits
- Error Handling: try/catch, custom exceptions, error reporting
- Database: MySQL connection, CRUD operations, prepared statements
- Security: SQL injection prevention, XSS, CSRF, password hashing
Why Learn PHP in 2026?
Despite the rise of Node.js and Python, PHP remains the backbone of web development for compelling reasons:
- Job market demand: Thousands of PHP developer positions available globally. WordPress alone powers 43% of all websites and requires PHP.
- Framework ecosystem: Laravel (the most popular web framework), Symfony, CodeIgniter, and Slim provide professional-grade tooling.
- Low barrier to entry: Shared hosting supports PHP out of the box. No complex server configuration needed to get started.
- PHP 8.x improvements: JIT compiler, named arguments, match expressions, union types, fibers — modern PHP is fast and expressive.
- CMS dominance: WordPress, Drupal, Joomla, Magento, WooCommerce all run on PHP. Knowing PHP gives you access to this entire ecosystem.
- Freelancing opportunities: PHP projects dominate freelance platforms. Many small businesses need WordPress customisation and PHP-based solutions.
PHP Version History (Key Milestones)
| Version | Year | Key Features |
|---|---|---|
| PHP 5.0 | 2004 | Full OOP support, PDO, improved XML |
| PHP 7.0 | 2015 | 2x speed improvement, scalar type declarations, null coalesce operator |
| PHP 7.4 | 2019 | Arrow functions, typed properties, preloading |
| PHP 8.0 | 2020 | JIT compiler, named arguments, match expression, union types, attributes |
| PHP 8.1 | 2021 | Enums, fibers, readonly properties, intersection types |
| PHP 8.2 | 2022 | Readonly classes, DNF types, deprecate dynamic properties |
| PHP 8.3 | 2023 | Typed class constants, json_validate(), #[Override] attribute |
How to Get Started with PHP
- Install a local environment — download XAMPP (Windows/Mac/Linux) or Laravel Valet (Mac). This gives you Apache, PHP, and MySQL in one package.
- Create your first file — make a file called
index.phpin your web root and add:<?php echo "Hello, World!"; ?> - Run it in browser — start Apache and visit
http://localhost/index.phpto see output. - Follow this tutorial series — work through each topic in order, running every example on your local setup.
- Build a project — after completing basics through OOP, build a simple CRUD app (todo list, blog, or contact form) to solidify your knowledge.
Frequently Asked Questions
Basic HTML knowledge is helpful since PHP is often embedded in HTML pages. You do not need to be an HTML expert — understanding tags, forms, and page structure is enough to start.
Yes. PHP and React serve different roles. React is frontend; PHP is backend. Laravel (PHP) is often used as the API backend for React frontends. WordPress (PHP) powers 43% of the web. The job market for PHP developers remains strong.
Laravel is the most popular and has the best documentation, ecosystem, and community. Learn core PHP first (this tutorial), then move to Laravel. Other options: Symfony (enterprise), CodeIgniter (lightweight), Slim (microframework for APIs).
Yes. Use our free online code editors to write and execute PHP code directly in your browser. This is perfect for learning and testing snippets without local setup.
Who Is This Tutorial For?
Complete beginners who want to learn their first programming language for web development. Self-taught developers filling gaps in their PHP knowledge. Students preparing for web development courses or exams. WordPress developers who want to understand the PHP underneath themes and plugins. Backend developers from other languages (Python, Node.js) learning PHP for a new project. Anyone preparing for PHP developer job interviews.
Master PHP Programming with Our Comprehensive Tutorial
Our PHP programming tutorial is designed to take you from a complete beginner to an advanced PHP developer. Whether you're looking to build dynamic websites, create web applications, or start a career in web development, this tutorial series provides everything you need to succeed.
What You'll Learn
- PHP fundamentals and syntax
- Variables, data types, and operators
- Control structures and loops
- Functions and arrays
- Object-oriented programming
- Database integration with MySQL
- Web forms and user input handling
- Security best practices
PHP remains one of the most popular programming languages for web development, powering millions of websites worldwide. Our tutorial includes practical examples, real-world projects, and best practices to ensure you learn not just the syntax, but how to write clean, efficient, and secure PHP code.