Complete Guide to PHP 8.5

PHP 8.5

Complete Developer Guide

Everything you need to know about PHP 8.5 features, improvements, and migration

🚀 PHP 8.5 Overview

Release Date: Expected November 2025

Support Period: 3 years (until November 2028)

Key Focus: Developer Experience, Performance, and Type Safety

PHP 8.5 represents a significant step forward in the PHP ecosystem, building upon the solid foundation established by PHP 8.0-8.4. This release focuses heavily on improving developer experience through enhanced syntax features, better performance optimizations, and stronger type safety mechanisms.

🎯 Major Highlights

  • Property Hooks: Revolutionary new way to handle property access
  • Asymmetric Visibility: Different visibility levels for getters and setters
  • Partial Function Application: Functional programming enhancements
  • JIT Improvements: Significant performance boosts
  • Enhanced Type System: Better type inference and generic support
  • New Standard Library Functions: More built-in functionality

📅 Release Timeline

Alpha 1 - June 2025

Initial feature freeze, core features implemented

Beta 1 - August 2025

Feature complete, testing phase begins

Release Candidate - October 2025

Final testing, bug fixes only

GA Release - November 2025

General availability, production ready

✨ New Features

🎣 Property Hooks

Property hooks allow you to define custom behavior when properties are accessed or modified, eliminating the need for traditional getter/setter methods in many cases.

Basic Property Hooks

PHP 8.5 - Property Hooks
class User
{
    public string $name {
        get => $this->name;
        set => ucfirst($value);
    }

    public string $email {
        set {
            if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
                throw new InvalidArgumentException('Invalid email');
            }
            $this->email = strtolower($value);
        }
    }
}

$user = new User();
$user->name = 'john'; // Automatically becomes 'John'
$user->email = 'John@Example.COM'; // Becomes 'john@example.com'

Computed Properties

PHP 8.5 - Computed Properties
class Rectangle
{
    public function __construct(
        public float $width,
        public float $height
    ) {}

    public float $area {
        get => $this->width * $this->height;
    }

    public float $perimeter {
        get => 2 * ($this->width + $this->height);
    }
}

$rect = new Rectangle(10, 5);
echo $rect->area; // 50
echo $rect->perimeter; // 30

Lazy Loading with Property Hooks

PHP 8.5 - Lazy Loading
class ExpensiveComputation
{
    private ?array $_cache = null;

    public array $result {
        get {
            if ($this->_cache === null) {
                $this->_cache = $this->performExpensiveOperation();
            }
            return $this->_cache;
        }
    }

    private function performExpensiveOperation(): array
    {
        // Simulate expensive computation
        sleep(1);
        return range(1, 1000);
    }
}

👁️ Asymmetric Visibility

Asymmetric visibility allows different visibility levels for reading and writing properties, providing fine-grained access control.

PHP 8.5 - Asymmetric Visibility
class BankAccount
{
    public private(set) float $balance = 0.0;
    public protected(set) string $accountNumber;

    public function __construct(string $accountNumber)
    {
        $this->accountNumber = $accountNumber;
    }

    public function deposit(float $amount): void
    {
        $this->balance += $amount; // OK - private set access within class
    }

    public function withdraw(float $amount): void
    {
        if ($amount <= $this->balance) {
            $this->balance -= $amount;
        }
    }
}

$account = new BankAccount('12345');
echo $account->balance; // 0.0 - OK, public get
echo $account->accountNumber; // "12345" - OK, public get

// $account->balance = 100; // Error - private set
// $account->accountNumber = "67890"; // Error - protected set

Advanced Asymmetric Visibility

PHP 8.5 - Complex Visibility Patterns
class ApiResponse
{
    public private(set) int $statusCode;
    public private(set) array $data;
    public private(set) array $headers = [];

    public function __construct(int $statusCode, array $data)
    {
        $this->statusCode = $statusCode;
        $this->data = $data;
    }

    public function addHeader(string $key, string $value): void
    {
        $this->headers[$key] = $value;
    }
}

🧩 Partial Function Application

Partial function application allows you to create new functions by pre-filling some arguments of existing functions, enabling more functional programming patterns.

PHP 8.5 - Partial Functions
function multiply(int $a, int $b, int $c): int
{
    return $a * $b * $c;
}

// Create partial functions using the ... operator
$double = multiply(2, ...); // Fix first argument to 2
$quadruple = multiply(2, 2, ...); // Fix first two arguments

echo $double(3, 4); // 24 (2 * 3 * 4)
echo $quadruple(5); // 20 (2 * 2 * 5)

// Advanced partial application
function calculatePrice(float $base, float $tax, float $discount): float
{
    return ($base * (1 + $tax)) * (1 - $discount);
}

$calculateWithTax = calculatePrice(..., 0.1, ...); // Fix tax to 10%
$calculateDiscounted = calculatePrice(..., ..., 0.05); // Fix discount to 5%

echo $calculateWithTax(100, 0); // 110 (base=100, tax=10%, discount=0%)
echo $calculateDiscounted(100, 0.1); // 104.5 (base=100, tax=10%, discount=5%)

Practical Examples

PHP 8.5 - Partial Functions in Practice
// Database query builder with partial application
function buildQuery(string $table, array $fields, array $conditions): string
{
    $select = implode(', ', $fields);
    $where = implode(' AND ', $conditions);
    return "SELECT {$select} FROM {$table} WHERE {$where}";
}

$queryUsers = buildQuery('users', ...); // Pre-fill table name
$queryUserNames = buildQuery('users', ['name', 'email'], ...); // Pre-fill table and fields

$sql1 = $queryUsers(['*'], ['active = 1']);
$sql2 = $queryUserNames(['created_at > "2023-01-01"']);

// Validation with partial application
function validate(mixed $value, string $type, array $rules): bool
{
    // Validation logic here
    return true; // Simplified
}

$validateEmail = validate(..., 'email', ['required', 'email']);
$validateAge = validate(..., 'integer', ['required', 'min:18']);

⚡ Performance Improvements

PHP 8.5 Performance Benchmarks

Overall Speed
+15% faster
Memory Usage
-12% memory
JIT Performance
+25% improvement
Array Operations
+18% faster

🔥 JIT Compiler Enhancements

PHP 8.5 introduces significant improvements to the Just-In-Time compiler, making it more efficient and applicable to a wider range of code patterns.

New JIT Optimization Techniques

  • Loop Unrolling: Better optimization of common loop patterns
  • Function Inlining: Automatic inlining of small, frequently called functions
  • Branch Prediction: Improved handling of conditional statements
  • Memory Access Optimization: Better caching and prefetching strategies
PHP Configuration - JIT Settings
; php.ini - Optimized JIT settings for PHP 8.5
opcache.enable=1
opcache.jit_buffer_size=256M
opcache.jit=1255
opcache.jit_hot_loop=64
opcache.jit_hot_func=128
opcache.jit_hot_return=16
opcache.jit_hot_side_exit=64

🏎️ Engine Optimizations

Improved Array Performance

PHP 8.5 - Optimized Array Operations
// These operations are now significantly faster in PHP 8.5
$largeArray = range(1, 1000000);

// Array filtering - 20% faster
$filtered = array_filter($largeArray, fn($x) => $x % 2 === 0);

// Array mapping - 18% faster
$mapped = array_map(fn($x) => $x * 2, $largeArray);

// Array merging - 25% faster
$merged = array_merge($filtered, $mapped);

String Processing Improvements

PHP 8.5 - Enhanced String Operations
// String operations with improved performance
$text = str_repeat('Hello World! ', 10000);

// String replacement - 15% faster
$replaced = str_replace('World', 'PHP', $text);

// Regular expressions - 22% faster
$matches = preg_match_all('/\b\w+\b/', $text, $results);

// String parsing - 30% faster
$parsed = explode(' ', $text);

📝 Syntax Updates

🔄 Enhanced Match Expression

PHP 8.5 extends the match expression with pattern matching capabilities and guard clauses.

PHP 8.5 - Advanced Match Expressions
function processValue(mixed $value): string
{
    return match ($value) {
        // Pattern matching with types
        int $x when $x > 0 => "Positive integer: {$x}",
        int $x when $x < 0 => "Negative integer: {$x}",
        0 => "Zero",

        // Array pattern matching
        [$first, $second] => "Array with two elements: {$first}, {$second}",
        [$first, ...$rest] when count($rest) > 0 => "Array starting with {$first}",

        // Object pattern matching
        User($name, $email) when strlen($name) > 0 => "User: {$name}",

        default => "Unknown value"
    };
}

// Usage examples
echo processValue(42); // "Positive integer: 42"
echo processValue(['a', 'b']); // "Array with two elements: a, b"
echo processValue(new User('John', 'john@example.com')); // "User: John"

🎯 Improved Null Coalescing

PHP 8.5 - Enhanced Null Coalescing
// New null coalescing assignment with conditions
$config = [
    'database' => [
        'host' => 'localhost',
        'port' => null
    ]
];

// Enhanced null coalescing with validation
$host = $config['database']['host'] ??= '127.0.0.1';
$port = $config['database']['port'] ??= 3306;

// Conditional null coalescing
$value = $input ?? when is_valid($input) => $input ?? 'default';

// Chain null coalescing with type checking
$result = $data['user']['profile']['age']
    ?? int => 0
    ?? string => intval($data['user']['profile']['age'])
    ?? 18;

📋 Multi-line Array Destructuring

PHP 8.5 - Advanced Array Destructuring
// Multi-line array destructuring for better readability
$userProfile = [
    'name' => 'John Doe',
    'email' => 'john@example.com',
    'address' => [
        'street' => '123 Main St',
        'city' => 'Anytown',
        'zip' => '12345'
    ],
    'preferences' => [
        'theme' => 'dark',
        'language' => 'en'
    ]
];

// Enhanced destructuring syntax
[
    'name' => $name,
    'email' => $email,
    'address' => [
        'street' => $street,
        'city' => $city,
        'zip' => $zip
    ],
    'preferences' => [
        'theme' => $theme = 'light', // Default value
        'language' => $lang
    ]
] = $userProfile;

// Conditional destructuring
if (['status' => 'success', 'data' => $data] = $apiResponse) {
    // Process successful response
    processData($data);
}

📚 Standard Library Enhancements

🔧 New Array Functions

PHP 8.5 introduces several new array functions to make array manipulation more intuitive and powerful.

PHP 8.5 - New Array Functions
// array_group_by() - Group array elements by a key or callback
$users = [
    ['name' => 'John', 'department' => 'IT', 'salary' => 50000],
    ['name' => 'Jane', 'department' => 'HR', 'salary' => 55000],
    ['name' => 'Bob', 'department' => 'IT', 'salary' => 48000]
];

$byDepartment = array_group_by($users, 'department');
// Result: ['IT' => [...], 'HR' => [...]]

// array_take() and array_drop() - Functional array slicing
$numbers = range(1, 10);
$first5 = array_take($numbers, 5); // [1, 2, 3, 4, 5]
$without5 = array_drop($numbers, 5); // [6, 7, 8, 9, 10]

// array_partition() - Split array into chunks based on condition
$numbers = range(1, 20);
[$evens, $odds] = array_partition($numbers, fn($n) => $n % 2 === 0);

// array_find() - Find first matching element
$user = array_find($users, fn($u) => $u['salary'] > 50000);

// array_some() and array_every() - Boolean array operations
$hasHighSalary = array_some($users, fn($u) => $u['salary'] > 60000);
$allInIT = array_every($users, fn($u) => $u['department'] === 'IT');

🧵 New String Functions

PHP 8.5 - Enhanced String Functions
// str_contains_any() and str_contains_all()
$text = "The quick brown fox jumps over the lazy dog";
$hasAny = str_contains_any($text, ['cat', 'dog', 'bird']); // true
$hasAll = str_contains_all($text, ['fox', 'dog']); // true

// str_remove() - Remove all occurrences of substring
$cleaned = str_remove("Hello World World", "World"); // "Hello  "

// str_limit() - Limit string length with custom suffix
$limited = str_limit($text, 20, "..."); // "The quick brown fox..."

// str_between() - Extract string between delimiters
$html = "<title>My Page</title>";
$title = str_between($html, "<title>", "</title>"); // "My Page"

// str_words() - Split string into words with advanced options
$words = str_words($text, preserveCase: true, minLength: 3);

📅 Enhanced DateTime Functions

PHP 8.5 - New DateTime Capabilities
// DateTime::fromUnixMicroseconds() - Create from microsecond timestamp
$microTime = microtime(true) * 1000000;
$date = DateTime::fromUnixMicroseconds($microTime);

// DateTime::diffInBusinessDays() - Business day calculations
$start = new DateTime('2025-01-01');
$end = new DateTime('2025-01-15');
$businessDays = $start->diffInBusinessDays($end);

// DateTime::addBusinessDays() - Add business days only
$futureDate = $start->addBusinessDays(10);

// DateTimeImmutable::parse() - Flexible parsing
$dates = [
    DateTimeImmutable::parse('next Monday'),
    DateTimeImmutable::parse('last day of this month'),
    DateTimeImmutable::parse('first Friday of next month')
];

// Enhanced timezone handling
$utc = new DateTimeImmutable('2025-01-01 12:00:00', new DateTimeZone('UTC'));
$local = $utc->convertToTimezone('America/New_York');
$relative = $utc->toRelativeString(); // "3 hours ago"

🔐 Security Enhancements

🛡️ Improved Cryptography

PHP 8.5 introduces enhanced cryptographic functions and improved security defaults.

PHP 8.5 - Enhanced Security Functions
// Enhanced password hashing with configurable algorithms
$password = 'user_password';
$hash = password_hash($password, PASSWORD_ARGON2ID, [
    'memory_cost' => 65536,
    'time_cost' => 4,
    'threads' => 3
]);

// New secure random functions
$token = random_string(32, 'alphanumeric'); // Cryptographically secure
$uuid = random_uuid(); // RFC 4122 compliant UUID
$pin = random_digits(6); // 6-digit PIN

// Enhanced hash functions with timing-safe comparison
$data = 'sensitive data';
$hash1 = hash_secure('sha256', $data, 'secret_key');
$hash2 = hash_secure('sha256', $data, 'secret_key');
$isValid = hash_equals_secure($hash1, $hash2); // Timing-safe

// New encryption/decryption functions
$key = sodium_crypto_secretbox_keygen();
$plaintext = 'Secret message';
$encrypted = encrypt_authenticated($plaintext, $key);
$decrypted = decrypt_authenticated($encrypted, $key);

🚫 Input Validation Improvements

PHP 8.5 - Enhanced Input Validation
// New validation filters
$email = filter_var('user@example.com', FILTER_VALIDATE_EMAIL_STRICT);
$domain = filter_var('example.com', FILTER_VALIDATE_DOMAIN);
$json = filter_var('{"key": "value"}', FILTER_VALIDATE_JSON);

// Enhanced sanitization
$userInput = '<script>alert("xss")</script>Hello World';
$safe = filter_var($userInput, FILTER_SANITIZE_HTML,
    FILTER_FLAG_STRIP_BACKTICK | FILTER_FLAG_ENCODE_AMP);

// Comprehensive input validation class
class InputValidator
{
    public static function validateAndSanitize(
        array $input,
        array $rules
    ): array {
        $result = [];

        foreach ($rules as $field => $rule) {
            $value = $input[$field] ?? null;

            // Apply validation and sanitization
            $result[$field] = match ($rule['type']) {
                'email' => filter_var($value, FILTER_VALIDATE_EMAIL),
                'int' => filter_var($value, FILTER_VALIDATE_INT, $rule['options'] ?? []),
                'string' => filter_var($value, FILTER_SANITIZE_STRING),
                'url' => filter_var($value, FILTER_VALIDATE_URL),
                default => $value
            };
        }

        return $result;
    }
}

⚠️ Deprecations and Removals

🗑️ Deprecated Features

The following features are deprecated in PHP 8.5 and will be removed in PHP 9.0:

Deprecated Feature Replacement Migration Timeline
create_function() Anonymous functions / Closures Remove by PHP 9.0
each() function foreach loops Remove by PHP 9.0
Non-capturing group (?:) in preg_* Use named groups or standard groups Deprecation warning in 8.5
Dynamic properties on classes Declare properties explicitly or use #[AllowDynamicProperties] Strict mode in 9.0

🔄 Migration Examples

PHP 8.5 - Migration from Deprecated Features
// OLD: create_function() - DEPRECATED
$lambda = create_function('$a,$b', 'return $a + $b;');

// NEW: Anonymous function
$lambda = function($a, $b) { return $a + $b; };
// OR: Arrow function
$lambda = fn($a, $b) => $a + $b;

// OLD: each() function - DEPRECATED
while (list($key, $value) = each($array)) {
    echo "{$key}: {$value}\n";
}

// NEW: foreach loop
foreach ($array as $key => $value) {
    echo "{$key}: {$value}\n";
}

// OLD: Dynamic properties - WILL BE RESTRICTED
class OldClass
{
    // No declared properties
}
$obj = new OldClass();
$obj->dynamicProperty = 'value'; // Will cause deprecation warning

// NEW: Explicitly declared properties
class NewClass
{
    public string $dynamicProperty;
}

// OR: Allow dynamic properties with attribute
#[AllowDynamicProperties]
class FlexibleClass
{
    // Can have dynamic properties
}

💥 Breaking Changes

These changes may break existing code when upgrading to PHP 8.5. Review your codebase carefully before upgrading.

🔧 Type System Changes

PHP 8.5 - Breaking Changes in Type System
// Stricter type checking for numeric strings
function processNumber(int $num): void
{
    echo $num;
}

// PHP 8.4: This worked
// processNumber("123"); // Implicit conversion

// PHP 8.5: This throws TypeError
// processNumber("123"); // ERROR: Cannot convert string to int

// Use explicit conversion
processNumber((int) "123"); // OK

// Stricter array to string conversion
$array = [1, 2, 3];
// $string = $array; // Fatal error in PHP 8.5
$string = json_encode($array); // Correct approach

📝 Behavioral Changes

PHP 8.5 - Behavioral Changes
// Changes in array_merge() with string keys
$array1 = ['0' => 'a', '1' => 'b'];
$array2 = ['0' => 'c', '1' => 'd'];

// PHP 8.4: Overwrites values
// PHP 8.5: Maintains all values with numeric indices
$result = array_merge($array1, $array2);
// Result: [0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd']

// Use array_replace() for old behavior
$result = array_replace($array1, $array2);
// Result: ['0' => 'c', '1' => 'd']

// Changes in default error reporting level
// PHP 8.5 enables E_STRICT by default
error_reporting(E_ALL & ~E_STRICT); // To disable strict warnings

🚀 Migration Guide

📋 Pre-Migration Checklist

Before upgrading to PHP 8.5, ensure your codebase is compatible by following this systematic approach.

Pre-Migration Steps

  • Update to PHP 8.4 first and resolve all deprecation warnings
  • Run comprehensive test suite on PHP 8.4
  • Review and update third-party dependencies
  • Audit use of deprecated features
  • Check custom extensions for compatibility
  • Backup production databases and files
  • Set up staging environment with PHP 8.5
  • Update development tools and IDEs

🔧 Step-by-Step Migration

Step 1: Environment Setup

Bash - PHP 8.5 Installation
# Ubuntu/Debian
sudo add-apt-repository ppa:ondrej/php
sudo apt update
sudo apt install php8.5 php8.5-cli php8.5-common

# Configure PHP 8.5
sudo update-alternatives --install /usr/bin/php php /usr/bin/php8.5 85

# Verify installation
php -v

Step 2: Composer Update

JSON - composer.json
{
    "require": {
        "php": "^8.5"
    },
    "config": {
        "platform": {
            "php": "8.5.0"
        }
    }
}

Step 3: Code Updates

PHP 8.5 - Common Migration Patterns
// Update type declarations for better performance
class UserService
{
    // Add explicit property types
    private readonly DatabaseConnection $db;
    private array $cache = [];

    public function __construct(DatabaseConnection $db)
    {
        $this->db = $db;
    }

    public function findUser(int $id): ?User
    {
        return $this->cache[$id] ??= $this->db->findUserById($id);
    }
}

// Replace deprecated string interpolation
// OLD: Variable variables in strings
// $message = "Hello $user->name"; // Deprecated complex interpolation

// NEW: Explicit concatenation or simple variables
$message = "Hello " . $user->name;
// OR: Use sprintf for complex formatting
$message = sprintf("Hello %s, you have %d messages", $user->name, $messageCount);

🧪 Testing Your Migration

PHP 8.5 - Migration Testing Script
#!/usr/bin/env php
<?php
// migration-test.php - Test script for PHP 8.5 compatibility

class MigrationTester
{
    private array $results = [];

    public function runTests(): void
    {
        $this->testPhpVersion();
        $this->testDeprecatedFeatures();
        $this->testNewFeatures();
        $this->testPerformance();
        $this->generateReport();
    }

    private function testPhpVersion(): void
    {
        $version = phpversion();
        $this->results['version'] = [
            'test' => 'PHP Version',
            'status' => version_compare($version, '8.5.0', '>=') ? 'PASS' : 'FAIL',
            'message' => "Current version: {$version}"
        ];
    }

    private function testDeprecatedFeatures(): void
    {
        // Test for usage of deprecated functions
        $deprecated = [
            'create_function' => function_exists('create_function'),
            'each' => function_exists('each')
        ];

        foreach ($deprecated as $func => $exists) {
            $this->results["deprecated_{$func}"] = [
                'test' => "Deprecated function: {$func}",
                'status' => $exists ? 'WARN' : 'PASS',
                'message' => $exists ? "Function {$func} is deprecated" : "Function {$func} not used"
            ];
        }
    }

    private function testNewFeatures(): void
    {
        // Test property hooks
        try {
            eval('
                class TestClass {
                    public string $name {
                        get => $this->name;
                        set => ucfirst($value);
                    }
                }
            ');
            $this->results['property_hooks'] = [
                'test' => 'Property Hooks',
                'status' => 'PASS',
                'message' => 'Property hooks are supported'
            ];
        } catch (ParseError $e) {
            $this->results['property_hooks'] = [
                'test' => 'Property Hooks',
                'status' => 'FAIL',
                'message' => 'Property hooks not supported'
            ];
        }
    }

    private function generateReport(): void
    {
        echo "\n=== PHP 8.5 Migration Test Report ===\n\n";

        foreach ($this->results as $result) {
            $status = match($result['status']) {
                'PASS' => '✅',
                'WARN' => '⚠️',
                'FAIL' => '❌'
            };

            echo "{$status} {$result['test']}: {$result['message']}\n";
        }
    }
}

// Run the migration test
$tester = new MigrationTester();
$tester->runTests();

⭐ Best Practices for PHP 8.5

🏗️ Property Hooks Best Practices

PHP 8.5 - Property Hooks Best Practices
// DO: Use property hooks for simple transformations
class User
{
    public string $email {
        set => strtolower(trim($value));
    }

    public string $name {
        get => $this->firstName . ' ' . $this->lastName;
    }
}

// DON'T: Use property hooks for complex business logic
class BadExample
{
    public string $password {
        set {
            // Too complex for a property hook
            if (strlen($value) < 8) {
                throw new InvalidArgumentException('Password too short');
            }
            // ... lots of validation logic
            $this->password = password_hash($value, PASSWORD_DEFAULT);
        }
    }
}

// BETTER: Use a dedicated method for complex logic
class GoodExample
{
    private string $hashedPassword;

    public function setPassword(string $password): void
    {
        $this->validatePassword($password);
        $this->hashedPassword = password_hash($password, PASSWORD_DEFAULT);
    }
}

🎯 Performance Optimization Tips

PHP 8.5 - Performance Best Practices
// Use typed properties for better JIT optimization
class OptimizedClass
{
    private int $count = 0;
    private array $items = [];
    private readonly string $id;

    public function __construct(string $id)
    {
        $this->id = $id;
    }

    // Use array functions instead of manual loops when possible
    public function processItems(array $data): array
    {
        return array_map(
            fn($item) => $this->transformItem($item),
            array_filter($data, fn($item) => $item !== null)
        );
    }
}

// Use match expressions for better performance than if/else chains
function getStatusMessage(int $status): string
{
    return match ($status) {
        200 => 'Success',
        404 => 'Not Found',
        500 => 'Server Error',
        default => 'Unknown Status'
    };
}

// Optimize string operations
function buildQuery(array $conditions): string
{
    // Use implode() instead of concatenation in loops
    $parts = array_map(
        fn($key, $value) => "{$key} = {$value}",
        array_keys($conditions),
        array_values($conditions)
    );

    return 'SELECT * FROM users WHERE ' . implode(' AND ', $parts);
}

🔒 Security Best Practices

PHP 8.5 - Security Best Practices
// Always validate and sanitize input
class SecureController
{
    public function handleUserInput(string $input): string
    {
        // Validate input length
        if (strlen($input) > 255) {
            throw new InvalidArgumentException('Input too long');
        }

        // Sanitize HTML
        $cleaned = htmlspecialchars($input, ENT_QUOTES | ENT_HTML5, 'UTF-8');

        // Additional filtering
        return filter_var($cleaned, FILTER_SANITIZE_STRING);
    }

    // Use prepared statements for database queries
    public function findUser(int $id): ?array
    {
        $stmt = $this->pdo->prepare('SELECT * FROM users WHERE id = :id');
        $stmt->bindParam(':id', $id, PDO::PARAM_INT);
        $stmt->execute();

        return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
    }

    // Generate secure tokens
    public function generateSecureToken(): string
    {
        return bin2hex(random_bytes(32));
    }
}

💡 Practical Code Examples

🏢 Real-World Application: E-commerce Product Class

PHP 8.5 - Complete E-commerce Example
enum ProductStatus: string
{
    case DRAFT = 'draft';
    case PUBLISHED = 'published';
    case SOLD_OUT = 'sold_out';
    case DISCONTINUED = 'discontinued';
}

class Product
{
    public function __construct(
        private readonly int $id,
        private string $name,
        private float $basePrice,
        private int $stockQuantity = 0
    ) {}

    // Property hooks for automatic calculations
    public float $finalPrice {
        get => $this->calculateFinalPrice();
    }

    public ProductStatus $status {
        get => match (true) {
            $this->stockQuantity === 0 => ProductStatus::SOLD_OUT,
            $this->basePrice === 0 => ProductStatus::DRAFT,
            default => ProductStatus::PUBLISHED
        };
    }

    // Asymmetric visibility for controlled access
    public private(set) array $reviews = [];
    public private(set) float $averageRating = 0.0;

    // Business logic methods
    public function addReview(int $rating, string $comment): void
    {
        if ($rating < 1 || $rating > 5) {
            throw new InvalidArgumentException('Rating must be between 1 and 5');
        }

        $this->reviews[] = [
            'rating' => $rating,
            'comment' => $comment,
            'date' => new DateTimeImmutable()
        ];

        $this->averageRating = $this->calculateAverageRating();
    }

    public function updateStock(int $quantity): void
    {
        if ($quantity < 0) {
            throw new InvalidArgumentException('Stock quantity cannot be negative');
        }

        $this->stockQuantity = $quantity;
    }

    private function calculateFinalPrice(): float
    {
        $discount = match (true) {
            $this->averageRating >= 4.5 => 0.05, // 5% discount for highly rated
            $this->stockQuantity > 100 => 0.02, // 2% discount for overstocked
            default => 0.0
        };

        return $this->basePrice * (1 - $discount);
    }

    private function calculateAverageRating(): float
    {
        if (empty($this->reviews)) {
            return 0.0;
        }

        $total = array_sum(array_column($this->reviews, 'rating'));
        return round($total / count($this->reviews), 2);
    }

    // JSON serialization
    public function jsonSerialize(): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'basePrice' => $this->basePrice,
            'finalPrice' => $this->finalPrice,
            'status' => $this->status->value,
            'stockQuantity' => $this->stockQuantity,
            'averageRating' => $this->averageRating,
            'reviewCount' => count($this->reviews)
        ];
    }
}

// Usage example
$product = new Product(1, 'Gaming Laptop', 1299.99, 50);
$product->addReview(5, 'Excellent performance!');
$product->addReview(4, 'Good value for money');

echo "Status: " . $product->status->value; // "published"
echo "Final Price: $" . $product->finalPrice; // Calculated with discount
echo "Average Rating: " . $product->averageRating; // 4.5

🌐 API Controller with Modern PHP 8.5 Features

PHP 8.5 - Modern API Controller
class ProductApiController
{
    public function __construct(
        private readonly ProductRepository $repository,
        private readonly CacheInterface $cache
    ) {}

    public function list(array $filters = []): array
    {
        $cacheKey = 'products:' . md5(serialize($filters));

        return $this->cache->remember($cacheKey, 3600, function() use ($filters) {
            $products = $this->repository->findByFilters($filters);

            return [
                'data' => array_map(fn($p) => $p->jsonSerialize(), $products),
                'meta' => [
                    'count' => count($products),
                    'filters' => $filters
                ]
            ];
        });
    }

    public function show(int $id): array
    {
        $product = $this->repository->findById($id);

        return match ($product) {
            null => ['error' => 'Product not found', 'code' => 404],
            default => ['data' => $product->jsonSerialize()]
        };
    }

    public function create(array $data): array
    {
        // Validate input using new array functions
        $required = ['name', 'basePrice'];
        $missing = array_diff($required, array_keys($data));

        if ($missing) {
            return [
                'error' => 'Missing required fields: ' . implode(', ', $missing),
                'code' => 400
            ];
        }

        try {
            $product = new Product(
                0, // ID will be set by repository
                $data['name'],
                $data['basePrice'],
                $data['stockQuantity'] ?? 0
            );

            $saved = $this->repository->save($product);
            $this->cache->flush('products:*'); // Invalidate cache

            return [
                'data' => $saved->jsonSerialize(),
                'code' => 201
            ];
        } catch (Exception $e) {
            return [
                'error' => 'Failed to create product: ' . $e->getMessage(),
                'code' => 500
            ];
        }
    }
}

🔄 Stay Updated

PHP 8.5 is actively being developed. Keep track of the latest changes and features at:

© 2024 PHP 8.5 Complete Guide. Stay updated with the latest PHP developments and best practices.

This guide covers all major features and improvements in PHP 8.5 for modern web development.

Wesley Classen
Wesley's AI Assistant Usually replies in ~15 min Ask me anything — if I can't answer, Wesley gets pinged and replies personally.
Hello! I'm Wesley's AI assistant. How can I help you today?