Introduction

PHP 8 introduced numerous breaking changes and deprecation warnings that cause existing PHP 7.x code to emit warnings or fail entirely. Common issues include implicit nullable type deprecation, str functions becoming strict, removed functions like create_function(), changed error levels for many notices, and the introduction of named arguments that conflict with positional argument usage. While warnings do not stop execution in PHP 8, they fill error logs, can be promoted to exceptions in error handlers, and signal code that will break entirely in PHP 9.

Symptoms

bash
Deprecated: Implicit conversion from float 3.14 to int loses precision in /app/code.php on line 42

Or:

bash
Deprecated: str_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated

Or:

bash
Deprecated: Return type of ArrayIterator::current() should either be compatible with Iterator::current(): mixed

Or fatal errors:

bash
Fatal error: Uncaught Error: Call to undefined function create_function()

Common Causes

  • Implicit nullable types: Parameter typed as string but default null
  • Null passed to non-nullable internal functions: str_replace, trim, etc.
  • Removed functions: create_function(), each(), __autoload()
  • Changed error levels: Many notices promoted to warnings
  • Resource to object migration: Functions now return objects instead of resources
  • Named arguments conflict: Using positional args where named args expected

Step-by-Step Fix

Step 1: Fix implicit nullable types

```php // PHP 7 style - deprecated in PHP 8.4+ function greet(string $name = null) { } // Implicit nullable

// PHP 8 style - explicit nullable function greet(?string $name = null) { }

// Or use union type (PHP 8.0+) function greet(string|null $name = null) { } ```

Step 2: Handle null in internal function calls

```php // PHP 7 - null silently converted $result = str_replace('foo', 'bar', null); // Returns null

// PHP 8 - deprecation warning $result = str_replace('foo', 'bar', $subject ?? ''); // Explicit null handling

// Helper function for safe string operations function str(string|null $value): string { return $value ?? ''; }

$result = str_replace('foo', 'bar', str($subject)); ```

Step 3: Replace removed functions

```php // create_function() removed in PHP 8.0 // OLD: $fn = create_function('$a', 'return $a * 2;');

// NEW: Use anonymous functions $fn = fn($a) => $a * 2;

// each() removed in PHP 8.0 // OLD: while (list($key, $val) = each($array)) { }

// NEW: Use foreach foreach ($array as $key => $val) { }

// __autoload() removed in PHP 8.0 // OLD: function __autoload($class) { require $class . '.php'; }

// NEW: Use spl_autoload_register spl_autoload_register(function ($class) { require str_replace('\\', '/', $class) . '.php'; }); ```

Prevention

  • Run code through PHP compatibility checker: composer require php-parallel-lint/php-parallel-lint
  • Test on PHP 8.x in CI before deploying
  • Fix deprecation warnings, not just fatal errors -- they indicate future breakage
  • Use PHPStan at level 8+ to catch type incompatibilities before runtime
  • Update dependencies to versions compatible with your target PHP version
  • Document minimum and maximum supported PHP versions in composer.json
  • Plan for PHP 9 compatibility by fixing all PHP 8 deprecations