Skip to content

Upgrading to PHPCompatibility 10.0

jrfnl edited this page Nov 15, 2025 · 2 revisions

Caution

PHPCompatibility 10.0.0 is currently in a pre-release phase. The information in this upgrade guide is subject to change until the final PHPCompatibility 10.0.0 version has been released.

If you find errors in this upgrade guide or would like to contribute improvements based on tests you've run with a PHPCompatibility 10.0.0 pre-release, please open an issue.

IMPORTANT: The PHPCompatibility 10.0 release contains breaking changes. Please read the below information carefully before upgrading!

Table of contents

Highlighted Changes

  • Policy change: As of this release, PHPCompatibility will no longer support a wide range of PHP_CodeSniffer versions. The minimum supported PHP_CodeSniffer version will be raised anytime syntax support for a new PHP feature is added to PHP_CodeSniffer and this syntax support is needed for the PHPCompatibility sniffs.
  • Policy change: As of this release, the only supported manner of installation of PHPCompatibility will be via Composer. Installation using git clones or with the PHP_CodeSniffer PHAR files is still possible, but no support will be provided for this.
  • New runtime dependencies:
  • All PHPCompatibility sniffs are now final classes.
  • All sniffs are now compatible with PHP_CodeSniffer 3.x as well as 4.0.

Please follow the below upgrade instructions carefully. This should be a one-time only action.

Updating your installation to PHPCompatibility 10.0.0

Composer project-based install

If you were already using a Composer project-based install, upgrade PHPCompatibility by running:

composer remove --dev dealerdirect/phpcodesniffer-composer-installer higidi/composer-phpcodesniffer-standards-plugin squizlabs/PHP_codesniffer
composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true
composer require --dev phpcompatibility/php-compatibility:"^10.0.0@dev" --update-with-dependencies

Composer global install

If you were already using a Composer global install, upgrade PHPCompatibility by running:

composer global remove --dev dealerdirect/phpcodesniffer-composer-installer higidi/composer-phpcodesniffer-standards-plugin squizlabs/PHP_codesniffer
composer global config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true
composer global require --dev phpcompatibility/php-compatibility:"^10.0.0@dev" --update-with-dependencies

Installs based on the old installation instructions

If you were using a Composer install which was created using the composer create-project command, had downloaded the release zip directly or were using a git clone-based install, please delete the directory in which you had PHPCompatibility installed and follow the new installation instructions in the Readme to install PHPCompatibility from scratch using Composer.

Other types of installs

If you were using a stand-alone install of PHP_CodeSniffer, like a git clone, PHAR, or PEAR install, with which you had registered PHPCompatibility using the installed_paths command, we strongly recommend you use a Composer based install instead. While installing PHPCompatibility without Composer is still possible, no support will be given anymore for such installs.

Removing artifacts from old installation methods

If you have a <config name="installed_paths" value="/path/to/phpcompatibility" /> directive in your [.]phpcs.xml[.dist] ruleset file, please remove it.

The Composer PHPCS plugin is now included by default and will take care of setting the installed paths for Composer based installs.

Along the same lines, if you had a Composer post-install-cmd (or similar) script which registered the installed_paths, please remove it as it will interfere/overwrite the installed paths which the Composer plugin sets.

You may need to re-run composer install after removing these artifacts.

CI integration

If necessary, also update your CI scripts to use a Composer based installation.

Updating your custom ruleset and PHPCS ignore annotations

A number of sniffs/error codes have different names in PHPCompatibility 10.0.0.

If you referred to any of these directly, either in your [.]phpcs.xml[.dist] ruleset file or in inline phpcs:ignore/disable/enable annotations, you will need to update the referenced name.

Removed Sniffs

The following sniffs have been removed without (direct) replacement:

  • PHPCompatibility.Keywords.ForbiddenNamesAsInvokedFunctions
  • PHPCompatibility.Keywords.ForbiddenNamesAsDeclared
  • PHPCompatibility.Upgrade.LowPHPCS

Any references to these sniffs, whether from within a ruleset or in ignore annotations, should be removed.

Renamed Sniffs

Old name New name
PHPCompatibility.Miscellaneous.ValidIntegers PHPCompatibility.Numbers.ValidIntegers
PHPCompatibility.Classes.ForbiddenAbstractPrivateMethods PHPCompatibility.FunctionDeclarations.AbstractPrivateMethods

Additionally, the check for the use of hexadecimal numeric strings has been moved from the PHPCompatibility.Miscellaneous.ValidIntegers sniff to a new stand-alone PHPCompatibility.Numbers.RemovedHexadecimalNumericStrings sniff.

This changes the error code from PHPCompatibility.Miscellaneous.ValidIntegers.HexNumericStringFound to PHPCompatibility.Numbers.RemovedHexadecimalNumericStrings.Found.

Changed Error Codes [1]

A number of error codes have changed due to PHP itself changing the name of function parameters in PHP 8.0.

Sniff name Old error code New error code
PHPCompatibility.FunctionUse.NewFunctionParameters array_filter_flag_* array_filter_mode_*
PHPCompatibility.FunctionUse.NewFunctionParameters array_unique_flags_* array_unique_sort_flags_*
PHPCompatibility.FunctionUse.NewFunctionParameters curl_multi_info_read_msgs_in_queue_* curl_multi_info_read_queued_messages_*
PHPCompatibility.FunctionUse.NewFunctionParameters date_time_set_microseconds_* date_time_set_microsecond_*
PHPCompatibility.FunctionUse.NewFunctionParameters file_get_contents_maxlen_* file_get_contents_length_*
PHPCompatibility.FunctionUse.NewFunctionParameters fputcsv_escape_char_* fputcsv_escape_*
PHPCompatibility.FunctionUse.NewFunctionParameters getopt_optind_* getopt_rest_index_*
PHPCompatibility.FunctionUse.NewFunctionParameters gettimeofday_return_float_* gettimeofday_as_float_*
PHPCompatibility.FunctionUse.NewFunctionParameters http_build_query_enc_type_* http_build_query_encoding_type_*
PHPCompatibility.FunctionUse.NewFunctionParameters imap_open_n_retries_* imap_open_retries_*
PHPCompatibility.FunctionUse.NewFunctionParameters imap_open_params_* imap_open_options_*
PHPCompatibility.FunctionUse.NewFunctionParameters imap_reopen_n_retries_* imap_reopen_retries_*
PHPCompatibility.FunctionUse.NewFunctionParameters iterator_to_array_use_keys_* iterator_to_array_preserve_keys_*
PHPCompatibility.FunctionUse.NewFunctionParameters json_decode_options_* json_decode_flags_*
PHPCompatibility.FunctionUse.NewFunctionParameters json_encode_options_* json_encode_flags_*
PHPCompatibility.FunctionUse.NewFunctionParameters ldap_add_serverctrls_* ldap_add_controls_*
PHPCompatibility.FunctionUse.NewFunctionParameters ldap_compare_serverctrls_* ldap_compare_controls_*
PHPCompatibility.FunctionUse.NewFunctionParameters ldap_delete_serverctrls_* ldap_delete_controls_*
PHPCompatibility.FunctionUse.NewFunctionParameters ldap_exop_serverctrls_* ldap_exop_controls_*
PHPCompatibility.FunctionUse.NewFunctionParameters ldap_exop_passwd_serverctrls_* ldap_exop_passwd_controls_*
PHPCompatibility.FunctionUse.NewFunctionParameters ldap_list_serverctrls_* ldap_list_controls_*
PHPCompatibility.FunctionUse.NewFunctionParameters ldap_mod_add_serverctrls_* ldap_mod_add_controls_*
PHPCompatibility.FunctionUse.NewFunctionParameters ldap_mod_del_serverctrls_* ldap_mod_del_controls_*
PHPCompatibility.FunctionUse.NewFunctionParameters ldap_mod_replace_serverctrls_* ldap_mod_replace_controls_*
PHPCompatibility.FunctionUse.NewFunctionParameters ldap_modify_batch_serverctrls_* ldap_modify_batch_controls_*
PHPCompatibility.FunctionUse.NewFunctionParameters ldap_parse_result_serverctrls_* ldap_parse_result_controls_*
PHPCompatibility.FunctionUse.NewFunctionParameters ldap_read_serverctrls_* ldap_read_controls_*
PHPCompatibility.FunctionUse.NewFunctionParameters ldap_rename_serverctrls_* ldap_rename_controls_*
PHPCompatibility.FunctionUse.NewFunctionParameters ldap_search_serverctrls_* ldap_search_controls_*
PHPCompatibility.FunctionUse.NewFunctionParameters mb_encode_numericentity_is_hex_* mb_encode_numericentity_hex_*
PHPCompatibility.FunctionUse.NewFunctionParameters nl2br_is_xhtml_* nl2br_use_xhtml_*
PHPCompatibility.FunctionUse.NewFunctionParameters openssl_open_method_* openssl_open_cipher_algo_*
PHPCompatibility.FunctionUse.NewFunctionParameters openssl_pkcs7_verify_p7bfilename_* openssl_pkcs7_verify_output_filename_*
PHPCompatibility.FunctionUse.NewFunctionParameters openssl_seal_method_* openssl_seal_cipher_algo_*
PHPCompatibility.FunctionUse.NewFunctionParameters openssl_verify_signature_alg_* openssl_verify_algorithm_*
PHPCompatibility.FunctionUse.NewFunctionParameters pg_fetch_all_result_type_* pg_fetch_all_mode_*
PHPCompatibility.FunctionUse.NewFunctionParameters pg_last_notice_option_* pg_last_notice_mode_*
PHPCompatibility.FunctionUse.NewFunctionParameters pg_lo_create_object_id_* pg_lo_create_oid_*
PHPCompatibility.FunctionUse.NewFunctionParameters pg_lo_import_object_id_* pg_lo_import_oid_*
PHPCompatibility.FunctionUse.NewFunctionParameters pg_select_result_type_* pg_select_mode_*
PHPCompatibility.FunctionUse.NewFunctionParameters sem_acquire_nowait_* sem_acquire_non_blocking_*
PHPCompatibility.FunctionUse.NewFunctionParameters str_word_count_charlist_* str_word_count_characters_*
PHPCompatibility.FunctionUse.NewFunctionParameters timezone_transitions_get_timestamp_begin_* timezone_transitions_get_timestampBegin_*
PHPCompatibility.FunctionUse.NewFunctionParameters timezone_transitions_get_timestamp_end_* timezone_transitions_get_timestampEnd_*
PHPCompatibility.FunctionUse.NewFunctionParameters timezone_identifiers_list_what_* timezone_identifiers_list_timezoneGroup_*
PHPCompatibility.FunctionUse.NewFunctionParameters timezone_identifiers_list_country_* timezone_identifiers_list_countryCode_*
PHPCompatibility.FunctionUse.NewFunctionParameters ucwords_delimiters_* ucwords_separators_*
PHPCompatibility.FunctionUse.OptionalToRequiredFunctionParameters openssl_seal_method_* openssl_seal_cipher_algo_*
PHPCompatibility.FunctionUse.OptionalToRequiredFunctionParameters openssl_open_method_* openssl_open_cipher_algo_*
PHPCompatibility.FunctionUse.RemovedFunctionParameters gmmktime_is_dst_* gmmktime_isDST_*
PHPCompatibility.FunctionUse.RemovedFunctionParameters mktime_is_dst_* mktime_isDST_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_diff_array2_* array_diff_arrays_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_diff_assoc_array2_* array_diff_assoc_arrays_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_diff_key_array2_* array_diff_key_arrays_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_diff_uassoc_array2_* array_diff_uassoc_rest_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_diff_ukey_array2_* array_diff_ukey_rest_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_intersect_array2_* array_intersect_arrays_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_intersect_assoc_array2_* array_intersect_assoc_arrays_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_intersect_key_array2_* array_intersect_key_arrays_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_intersect_uassoc_array2_* array_intersect_uassoc_rest_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_intersect_ukey_array2_* array_intersect_ukey_rest_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_merge_arrays_to_merge_* array_merge_arrays_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_merge_recursive_arrays_to_merge_* array_merge_recursive_arrays_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_push_element_to_push_* array_push_values_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_udiff_array2_* array_udiff_rest_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_udiff_assoc_array2_* array_udiff_assoc_rest_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_udiff_uassoc_array2_* array_udiff_uassoc_rest_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_uintersect_array2_* array_uintersect_rest_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_uintersect_assoc_array2_* array_uintersect_assoc_rest_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_uintersect_uassoc_array2_* array_uintersect_uassoc_rest_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters array_unshift_element_to_prepend_* array_unshift_values_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters getenv_varname_* getenv_name_*
PHPCompatibility.FunctionUse.RequiredToOptionalFunctionParameters stream_socket_enable_crypto_crypto_type_* stream_socket_enable_crypto_crypto_method_*

Changed Error Codes [2]

There have also been a few error code changes due to changes in sniff functionality.

Sniff name Old error code New error code
PHPCompatibility.FunctionDeclarations.NewReturnTypeDeclarations NullableMixed NonStandaloneMixed
PHPCompatibility.FunctionUse.OptionalToRequiredFunctionParameters *SoftRecommended *SoftRequired
PHPCompatibility.TypeCasts.RemovedTypeCasts t_unset_castDeprecatedRemoved unsetDeprecatedRemoved
PHPCompatibility.TypeCasts.RemovedTypeCasts t_double_castDeprecatedRemoved realDeprecatedRemoved

In addition to that, the following error codes have been split:

Sniff name Old error code New error codes
PHPCompatibility.FunctionNameRestrictions.RemovedMagicAutoload Found Deprecated and Removed
PHPCompatibility.FunctionNameRestrictions.RemovedNamespacedAssert Found Deprecated and Removed
PHPCompatibility.FunctionNameRestrictions.RemovedPHP4StyleConstructors Found Deprecated and Removed
PHPCompatibility.Operators.RemovedTernaryAssociativity Found Deprecated and Removed
PHPCompatibility.Syntax.RemovedCurlyBraceArrayAccess Found Deprecated and Removed
PHPCompatibility.Syntax.NewFlexibleHeredocNowdoc ClosingMarkerNoNewLine ClosingMarkerNoNewLine and CloserFoundInBody
PHPCompatibility.FunctionDeclarations.NewParamTypeDeclarations InvalidTypeHintFound InvalidTypeHintFound and InvalidLongTypeFound
PHPCompatibility.Classes.NewTypedProperties InvalidType InvalidType and InvalidLongType

All classes are now final

All non-abstract classes, including the sniffs, in the PHPCompatibility package are now declared as final.

The PHP_CodeSniffer autoloader does not always play nice with sniffs which extend other sniffs, especially if both sniffs (parent and child) are included in the same standard.

To discourage sniffs extending each other, all non-abstract classes have been made final.

If needs be, a sniff in an external standard can still use logic used in the PHPCompatibility sniffs. On the one hand, the sniff can use utility methods from PHPCSUtils. On the other hand, the sniff can do a preliminary check on certain data and defer to a new or pre-instantiated instance of a PHPCompatibility sniff for everything else.

If this change causes you insurmountable problems, please open an issue in the repo to request for a class to become non-final and explain your use case. Each such issue will be evaluated on its own merits.

Other

Please read the changelog carefully before upgrading.

This release contains lots of bugfixes, so if you'd previously ignored certain issues, either from the ruleset or using the PHPCS selective ignore annotations, because of bugs in sniffs, please review your ignore annotations using the --ignore-annotations CLI option and/or re-enable those sniffs.