Fixing PHP 8 Deprecated: Required parameter follows optional parameter

beginner๐Ÿ˜ PHP2026-05-27| PHP 8.0, 8.1, 8.2, 8.3 on Linux (Ubuntu/CentOS), Docker (php-fpm), or Windows (XAMPP/WAMP)

Error Message

Deprecated: Required parameter $config follows optional parameter $options in /var/www/html/app.php on line 42
#php#php8#deprecated#function-signature#parameter

Context

Upgrading a legacy site to PHP 8.0 often feels like a game of whack-a-mole with deprecation warnings. One of the most common pests is the "Required parameter follows optional parameter" warning. While older versions of PHP (7.4 and below) tolerated ambiguous function signatures, the engine now demands more discipline. This change isn't just about being strict; it fixes a logical trap that has existed in the language for years.

The Error Message

You will likely see this warning pop up in your error logs or directly on the page during development:

Deprecated: Required parameter $config follows optional parameter $options in /var/www/html/app.php on line 42

Root Cause Analysis

An optional parameter has a default value, while a required one does not. Consider this problematic signature common in older codebases:

function processData($options = [], $data) {
    // logic here
}

The logic here is broken. To pass a string to $data, you are physically forced to provide something for $options first. If you try to call processData('my data'), PHP 7 would mistakenly assign your string to $options and then complain that $data is missing. The "optional" nature of that first argument was a lie. You couldn't actually skip it. PHP 8.0 resolves this confusion by requiring all mandatory parameters to sit at the front of the line.

Step-by-Step Fix

1. Locate the Function Definition

Head to the file and line number mentioned in your log. You'll find a function or method where a variable with a default value (like = [] or = null) appears before one that has no default.

// The broken signature
function initializeApp($options = ['debug' => true], $config) {
    $timeout = $config['timeout'];
}

2. Flip the Parameter Order

Move the mandatory variables to the left. This is the cleanest fix and makes the function's intent immediately clear to other developers.

// The corrected signature
function initializeApp($config, $options = ['debug' => true]) {
    $timeout = $config['timeout'];
}

3. Synchronize Call Sites

Changing the signature breaks every existing call to that function. You must find where initializeApp is used and swap the arguments. Modern IDEs like PhpStorm can handle this refactoring across 100+ files in seconds using the "Change Signature" tool.

// Old way (now triggers errors or logical bugs)
initializeApp(['debug' => false], ['timeout' => 30]);

// Corrected way
initializeApp(['timeout' => 30], ['debug' => false]);

4. The "API-Safe" Alternative: Nullable Types

Sometimes you can't reorder parameters because you're following a strict interface or working on a public library. In these cases, make the optional parameter required but nullable. This silences the warning without changing the argument order.

// Using nullability to keep the order
function initializeApp(?array $options, $config) {
    $options = $options ?? ['debug' => true];
}

Keep in mind that callers must now explicitly pass null if they want to use the default settings.

Leveraging PHP 8 Named Arguments

Once you've reordered your parameters, PHP 8's named arguments feature makes your code much more readable. It allows you to skip optional parameters entirely without worrying about their position in the list.

function createUser($name, $role = 'guest', $status = 'active') {
    // ...
}

// Skip $role and jump straight to $status
createUser(name: 'Jane Doe', status: 'pending');

Verification Steps

Check for syntax errors immediately after refactoring using the PHP lint command:

php -l /var/www/html/app.php

If the syntax is valid, monitor your logs in real-time while navigating the app. On Linux, you can run tail -f /var/log/php-fpm.log to ensure the Deprecated warning has vanished. If you are using Docker, check the container logs with docker logs -f [container_name].

Lessons Learned

- **Mandatory First:** Treat required-before-optional as a hard rule. It's a standard across Python, JavaScript, and Java for a reason.
- **Prepare for PHP 9:** Many behaviors that are "Deprecated" in 8.x will become fatal "Error" exceptions in PHP 9.0. Fix them now to save future-you a weekend of stress.
- **Static Analysis is King:** Use tools like PHPStan at level 5 or higher. It catches these signature mismatches during CI/CD before they ever reach your production logs.

Related Error Notes