PHP 7.3 Features Worth Knowing
PHP 7.3 arrived in December 2018 with a set of practical improvements that make everyday coding cleaner and more reliable. While it does not carry the dramatic performance gains of PHP 7.0, the refinements introduced affect how developers write and maintain code on a daily basis. This guide covers each feature in detail so you can understand what changed, why it matters, and how to apply it in your own projects.
Trailing Commas in Function Calls
Before PHP 7.3, trailing commas were allowed only in array definitions. PHP 7.3 extended this to function and method calls, which may seem like a minor addition but has a meaningful impact on version control workflows.
When you add a new parameter to a function call that already has a trailing comma, the diff in your version control system shows only the new line. Without a trailing comma, the diff shows both the modification of the previous line and the new line, which creates noise in code reviews and makes it harder to trace exactly what changed.
// Before PHP 7.3: trailing comma not allowed
$array = array(
'first',
'second',
'third'
);
// PHP 7.3+: trailing comma allowed
setConfig('host', 'localhost',);
callUserFunc($callback, $arg1, $arg2,);
This is particularly useful in configuration arrays and function calls that grow over time. Rather than modifying the last line every time you add a parameter, you simply append the new line with a comma.
$mailer->send(
$recipient,
$subject,
$body,
$headers, // adding a new parameter here is cleaner
);
Using trailing commas consistently across your codebase reduces diff noise and makes blame output more useful when you need to trace when and why a particular parameter was added. This practice pairs well with the coding standards used in modern PHP development, particularly when working with long parameter lists or configuration objects that change frequently.
Flexible Heredoc and Nowdoc Syntax
Heredoc strings in PHP traditionally required the closing identifier to appear at the start of a line with no indentation. This made it difficult to use heredoc syntax inside indented code blocks such as class methods or conditional statements. PHP 7.3 resolved this by allowing the closing identifier to be indented, with the indentation level stripped from each line in the heredoc.
// Before PHP 7.3: closing identifier must be at column 0
$sql = <<<SQL
SELECT * FROM users WHERE active = 1
SQL;
// PHP 7.3+: closing identifier can be indented
$sql = <<<SQL
SELECT * FROM users WHERE active = 1
SQL;
Nowdoc works the same way. The closing identifier must still be quoted with single quotes, but it can now be indented to match the surrounding code without affecting the actual string content.
$code = <<<'CODE'
function example() {
return 'indented heredoc content';
}
CODE;
This change makes heredoc and nowdoc syntax much more usable in real-world code. You no longer need to flush all indentation from the string content itself just to satisfy the syntax rules. The closing identifier indentation is automatically stripped, leaving the string content intact. This is particularly valuable when writing SQL queries, template strings, or multi-line constants inside methods where maintaining readable code structure matters.
If you are working with PHP 7.4 or later, you may also want to explore the arrow function syntax introduced in that version, which complements these string handling improvements for cleaner, more readable code in general.
json_validate Function
Before PHP 7.3, validating whether a string contained valid JSON required attempting to decode it and checking for errors. This approach was indirect and meant wrapping the decode operation in a try-catch block or manually checking the return value against false. PHP 7.3 introduced the json_validate() function, which checks a string without throwing an exception.
$jsonString = '{"name": "test", "value": 10}';
if (json_validate($jsonString)) {
$data = json_decode($jsonString);
// use $data
} else {
echo 'Invalid JSON';
}
This function is more efficient than attempting to decode and catching exceptions, particularly when dealing with invalid JSON where exceptions carry more overhead than a simple boolean check. It is also cleaner to read and makes the intent of the code explicit.
Use json_validate() when processing user-provided JSON, API responses that may be malformed, or any data where the JSON structure is uncertain. It provides a clear, dedicated way to check validity before attempting to decode, which reduces the risk of unhandled exceptions in your application.
is_countable Function
The count() function in PHP throws a warning when given a non-countable variable. Before PHP 7.3, developers had to manually check the type before calling count(), often using is_array() or a combination of type checks. PHP 7.3 added is_countable() to the standard library to standardise this check.
$data = getDataFromExternalSource();
if (is_countable($data)) {
$count = count($data);
} else {
$count = 0;
}
This function is particularly useful when processing data from APIs, databases, or user input where the type may not be guaranteed. Using is_countable() before count() avoids triggering PHP warnings in strict mode or when error reporting is set to report all warnings. The function returns true for both arrays and objects that implement the Countable interface, making it a reliable way to check whether calling count() is safe.
Argon2i Password Hashing Improvements
PHP 7.3 continued improving support for the Argon2i password hashing algorithm. The constants PASSWORD_ARGON2I and PASSWORD_ARGON2ID were added to make Argon2 the recommended password hashing algorithm going forward, overtaking bcrypt in terms of modern security practices.
// Hash a password with Argon2id
$hash = password_hash('user_password', PASSWORD_ARGON2ID);
// Verify a password
if (password_verify('user_password', $hash)) {
// password correct
}
// Check if hash needs rehashing
if (password_needs_rehash($hash, PASSWORD_ARGON2ID)) {
$newHash = password_hash('user_password', PASSWORD_ARGON2ID);
// update stored hash
}
Argon2id provides better resistance against GPU-based cracking attacks than bcrypt because it is designed to be memory-hard, meaning it requires significant amounts of RAM to compute rather than being easily parallelisable on graphics hardware. New user registrations and password changes should use Argon2id. Existing bcrypt hashes do not need to be immediately rehashed, but you should update them when users next log in successfully.
When planning a password migration strategy, consider the user experience implications. Forcing a password reset for all users just to migrate hashing algorithms is disruptive and often unnecessary. Instead, implement transparent rehashing on successful login, which updates the stored hash without requiring any action from the user.
List() Reference Assignment
PHP 7.3 introduced the ability to use references on the left side of a list() assignment. This allows you to extract array values by reference, which is useful when you want to modify array elements in place without rebuilding the entire array.
$array = [1, 2, 3];
list($a, &$b, $c) = $array;
$b = 20;
// $array is now [1, 20, 3]
echo $array[1]; // 20
This also works with the shorthand list syntax using square brackets.
$array = [1, 2, 3];
[ $a, &$b, $c ] = $array;
$b = 20;
// $array is now [1, 20, 3]
Using references in list assignments is not common in everyday code, but it becomes useful when iterating through arrays and modifying specific elements, or when working with associative arrays where you want to update particular keys without reconstructing the full structure. This feature fills a gap that previously required more verbose approaches or temporary variables.
Deprecated Features in PHP 7.3
PHP 7.3 deprecated several features that had been discouraged in earlier versions. Code using these features will continue to work in PHP 7.3 but will emit deprecation warnings. In PHP 8.0, these features were removed entirely. Addressing deprecations in PHP 7.3 before upgrading to PHP 8.0 reduces the risk of breaking changes causing issues in production.
Powershell-style variable syntax in strings was deprecated. The syntax "Hello $name!" still works, but the alternative "Hello ${name}!" with curly braces around the variable name in a specific way is deprecated. Use explicit curly braces instead: "Hello {$name}!". This change removes ambiguity in how PHP parses variable interpolation in strings.
The pdo_odbc.db2_instance_name INI directive was deprecated. This was a Windows-specific configuration option that is no longer relevant to modern development environments.
Calling implode() with parameters in the wrong order was deprecated. The function signature is implode(string $separator, array $array). Previously implode($array, $separator) worked due to flexible parameter handling. PHP 7.3 deprecates the reversed parameter order. Use the correct order going forward: implode($separator, $array). This change enforces consistent function usage across the codebase.
If you are planning a broader PHP upgrade path, it is worth reviewing the PHP 8 breaking changes guide to understand the full scope of what was removed when PHP 8.0 launched.
Performance Improvements in PHP 7.3
While PHP 7.3 is not as dramatically faster as PHP 7.0 was compared to PHP 5, it includes JIT compilation groundwork and several runtime performance improvements. The Just-In-Time compiler that appeared in PHP 8.0 had foundations laid in the 7.x series, making PHP 7.3 an important stepping stone in the performance journey.
JSON parsing was significantly optimised in PHP 7.3 through improved memory handling. If your application performs heavy JSON processing, you will see measurable improvements simply from upgrading. Array sorting operations were also optimised to reduce the number of comparisons required for common sorting patterns.
PCRE2 replaced PCRE as the default regular expression library. PCRE2 has better performance characteristics for many common patterns and supports Unicode properties that PCRE did not handle natively. This change improves both performance and capability for applications that rely heavily on regular expressions.
Deprecation Warnings in Practice
PHP 7.3 introduced deprecation warnings for various features, but these warnings are not shown by default in production environments. You should enable deprecation warnings during development and testing to identify code that needs updating before PHP 8.0.
// Hide deprecations (PHP 7.3 default in production)
error_reporting(E_ALL & ~E_DEPRECATED);
// Show all warnings including deprecations
error_reporting(E_ALL);
For continuous integration pipelines, run your test suite with E_ALL error reporting enabled. This approach catches deprecated function calls and patterns before they become errors in PHP 8.0, allowing you to address them in a controlled way rather than scrambling to fix everything during a version upgrade.
Configure your development environment to treat all warnings as errors during development. This practice ensures that deprecation notices are not ignored and that you maintain a clean codebase as you work. Many development frameworks support this through configuration options that promote warnings to exceptions during the development phase.
Upgrading to PHP 7.3
The upgrade path from PHP 7.2 to 7.3 is straightforward for most applications. PHP maintains backward compatibility well within a major version, and 7.3 was designed as a safe incremental upgrade. Before upgrading on a production server, there are several steps worth taking.
- Check dependencies: Confirm your framework and library versions support PHP 7.3. Most modern frameworks support it from their latest stable release, but checking the official compatibility matrices prevents surprises.
- Review deprecated warnings: Run your application with
E_ALLerror reporting and address any deprecation notices before deploying the upgrade. - Test extensions: Confirm all required PHP extensions are available for 7.3 on your platform. Some older extensions may not yet be compatible.
- Update configuration: Review php.ini settings, as some directives have changed their defaults or been removed in this version.
On Ubuntu 18.04 and later, you can use the ondrej PHP PPA to install PHP 7.3 alongside other versions. This approach allows you to test your application against PHP 7.3 without removing your existing PHP installation.
sudo add-apt-repository ppa:ondrej/php
sudo apt update
sudo apt install php7.3 php7.3-fpm php7.3-mysql php7.3-cli
Use update-alternatives to switch between PHP versions after installation.
sudo update-alternatives --set php /usr/bin/php7.3
When upgrading PHP versions, always test your application in a staging environment first. Create a full backup of your application and database before making changes on production systems. This applies regardless of how minor an upgrade appears to be.
Real-World Impact of PHP 7.3 Features
The features PHP 7.3 introduces are incremental but collectively improve code quality in meaningful ways. Trailing commas in function calls reduce diff noise in version control. Flexible heredoc syntax makes template strings more readable within indented code. json_validate() simplifies input validation workflows. Argon2id support future-proofs password storage against evolving hardware capabilities.
When planning your upgrade strategy, treat PHP 7.3 as a stepping stone to PHP 8.0. The deprecation warnings in PHP 7.3 tell you exactly what will break in PHP 8.0. Addressing them while still on PHP 7.3 means a smoother transition when you eventually upgrade. Many applications that run on PHP 7.3 require only minor changes to run on PHP 8.0 if deprecation notices are addressed proactively.
For teams managing multiple PHP applications, standardising on PHP 7.3 across your development and staging environments gives you a consistent baseline for testing and deployment. This reduces the complexity of supporting multiple PHP versions and ensures your applications are ready for the next major upgrade when the time comes.