Upgrading old PHP code to the new 8 series could be a very difficult task, but its absolutely necessary. Main reasons are security, performance and compatibility. I will try to document here things I haven't found in other places.

Here are the steps I have been using to upgrade old codebases:

Step 1. Code written in PHP versions older than 5.x upgrade first to PHP 7.4:

In the early beginning of Object Oriented Programming in PHP, Classes were used to encapsulate properties and methods, but as class constructor, we were using a function called the same name as the class:

class OA_Sync
{
    var $aConf;
    var $aPref;
    var $_conf;

    /**
     * @var MDB2_Driver_Common
     */
    var $oDbh;

    /**
     * Constructor
     *
     * @param array $conf array, if null reads the global variable
     * @param array $pref array, if null reads the global variable
     */
    function OA_Sync($conf = null, $pref = null)
    {
        $this->aConf = is_null($conf) ? $GLOBALS['_MAX']['CONF'] : $conf;
        $this->aPref = is_null($pref) ? $GLOBALS['_MAX']['PREF'] : $pref;

        $this->_conf = $this->aConf['oacSync'];

        $this->oDbh =& OA_DB::singleton();
    }

This is no longer valid, and you need to replace this function by the actual class constructor:

class OA_Sync
{
    var $aConf;
    var $aPref;
    var $_conf;

    /**
     * @var MDB2_Driver_Common
     */
    var $oDbh;

    /**
     * Constructor
     *
     * @param array $conf array, if null reads the global variable
     * @param array $pref array, if null reads the global variable
     */
    function __construct($conf = null, $pref = null)
    {
        $this->aConf = is_null($conf) ? $GLOBALS['_MAX']['CONF'] : $conf;
        $this->aPref = is_null($pref) ? $GLOBALS['_MAX']['PREF'] : $pref;

        $this->_conf = $this->aConf['oacSync'];

        $this->oDbh =& OA_DB::singleton();
    }

You need to search all codebase to make sure there is no static call to the replaced function. If so, you need to preserve it and declare it static:

class OA_Sync
{
    var $aConf;
    var $aPref;
    var $_conf;

    /**
     * @var MDB2_Driver_Common
     */
    var $oDbh;

    /**
     * Constructor
     *
     * @param array $conf array, if null reads the global variable
     * @param array $pref array, if null reads the global variable
     */
    function __construct($conf = null, $pref = null)
    {
        $this->aConf = is_null($conf) ? $GLOBALS['_MAX']['CONF'] : $conf;
        $this->aPref = is_null($pref) ? $GLOBALS['_MAX']['PREF'] : $pref;

        $this->_conf = $this->aConf['oacSync'];

        $this->oDbh =& OA_DB::singleton();
    }


    public static function OA_Sync($conf = null, $pref = null)
    {
        $this->aConf = is_null($conf) ? $GLOBALS['_MAX']['CONF'] : $conf;
        $this->aPref = is_null($pref) ? $GLOBALS['_MAX']['PREF'] : $pref;

        $this->_conf = $this->aConf['oacSync'];

        $this->oDbh =& OA_DB::singleton();
    }

Another malpractice from earlier versions of PHP was to make function calls with no exact argument matching. For example, you may have this Class Method:

    function getConfigVersion($version)
    {
        $a = array(
            'dev'     => -0.001,
            'beta-rc' => 0.1,
            'beta'    => 0.2,
            'rc'      => 0.3,
            'stable'  => 0.4
        );
        
        //...

And from other part of the code a call to this method was done using 2 arguments:

//...

$getVersion = $oaSync->getConfigVersion($version, $subversion);

In the past, PHP discarded the second parameter and only used the first one. This is no longer valid and throws error, stopping code execution.

This malpractice could be present in arrays as well, and when trying to execute a foreach over a not set array key, older versions of PHP just discarded did nothing in the foreach and continue execution. This is also no longer valid, and if you try to foreach over a not set array key or the key is not an array or object, it throws exception:

//>>> Before

foreach ($insight['topics'] as $t) {
                    $t = ucwords($t);
                    if (!isset($topics[$t])) {
                        $topics[$t] = 0;
                    }
                    $topics[$t]++;
                }
//...


//>>> After-> Need to implement something like this:
if (isset($insight['topics']) &&  is_array($insight['topics'])) {
                foreach ($insight['topics'] as $t) {
                    $t = ucwords($t);
                    if (!isset($topics[$t])) {
                        $topics[$t] = 0;
                    }
                    $topics[$t]++;
                }
            }
//...

 In many cases, this malpractice was used to echo array keys, and if the array key was not present, PHP just discarded it without throwing exception:

//>>> Before
echo "<h3>Hello from this World called:" . $arr['world-name'] . "</h3>";


//>>> After upgrading:
echo "<h3>Hello from this World called:" . $arr['world-name'] ?? 'n/a' . "</h3>";

 There are a few more things that you may want to check on php's website

Once you have made it to upgrade to PHP 7.4, then you need to upgrade to PHP 8.2, where many deprecations turned into errors. One way for checking on this is to configure your php.ini 8.2 file to display all errors:

[PHP]
;;;;;;;;;;;;;;;;;;;;
; Language Options ;
;;;;;;;;;;;;;;;;;;;;

engine = On
short_open_tag = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = -1
disable_functions =
disable_classes =
zend.enable_gc = On
zend.exception_ignore_args = On
expose_php = Off
max_execution_time = 180
max_input_time = 60
memory_limit = 256M
error_reporting = E_ALL
display_errors = On
display_startup_errors = Off
log_errors = On
error_log = /tmp/var/local/log/php_errors.log
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On
html_errors = On
variables_order = "GPCS"
request_order = "GP"
register_argc_argv = Off
auto_globals_jit = On
post_max_size = 128M
auto_prepend_file =
auto_append_file =
default_mimetype = "text/html"
default_charset = "UTF-8"
doc_root =
user_dir =
enable_dl = Off
file_uploads = On
upload_max_filesize = 20M
max_file_uploads = 20
allow_url_fopen = On
default_socket_timeout = 60

...

Then start hitting as many endpoints you can in your php application to try to get errors, notices and warnings to work on.

Also, if you have a modern PHP IDE like PHPStorm then you can use tools such like Code Sniffer to run inspections in your code. The analysis may help you identify most errors that need to get fixed in order to have your code run smoothly.

 

It is very important that you keep you code up to date with all deprecations worked out, as when PHP 9 arrives it will turn all these ones into errors, preventing your code from running.