PHP项目从 php5.3 版本升级到 php8.3 版本时的一些问题和解决方法记录

一个原来的项目,因为业务需要,进行了PHP版本升级,从php5.3直接升级到php8.3。变化挺大的,原程序中有很多不再兼容,在此处进行一下记录。

一、Deprecated: 显式转换问题

报错内容:Deprecated: Implicit conversion from float 173387987633874.1 to int loses precision in

之前运行正常的一段代码(印象中还是原百度公司中生成日志的一个方法),切换PHP环境从5.3至8.3时报了些错误,因为是很久前的代码了,我就简单看了一下并作一下记录。

php 复制代码
    private function __initLogID()
    {

		if(defined('LOG_ID')) return LOG_ID;
		
		$arr = gettimeofday();
		
		$t = ($arr['sec']*100000 + $arr['usec']/10) & 0x7FFFFFFF;

		define('LOG_ID', $t);

		return LOG_ID;

	}

这个PHP警告是关于隐式转换的。在PHP 7及以上版本中,当将一个浮点数(float)转换为整数时,如果不显式指定转换类型,PHP会进行截断操作,即直接去掉小数点后的数字,而不是四舍五入。如果转换后的整数超出了整数的表示范围,PHP会发出一个警告信息。

报错中的数字173387987633874.1被隐式转换成了173387987633874,这个数字在转换过程中没有超出整数的范围,但在后续的代码中可能会导致不正确的行为。

所以解决方法就是:进行显式转换类型:使用intval()或(int)来进行强制转换,并指定正确的进制,如下即可。

php 复制代码
$t = intval($arr['sec']*100000 + $arr['usec']/10) & 0x7FFFFFFF;

二、Deprecated: 动态属性问题

Deprecated: Creation of dynamic property XXXController::$xxx is deprecated in

底层程序框架中有很多地方使用了动态属性的设置,这是PHP的一个很好用的功能。动态属性是 PHP 元编程的重要组成部分------许多框架都依赖它!

php 复制代码
	/***********************************
			全局核心设置方法
	 ***********************************/
	 
	public function __set($key, $value)
    {
		
		$this->$key=$value;
	
	}

不过版本升级以后,发现在 PHP 8.2对这个进行了弃用。特别是弃用了这个动态属性。什么是动态属性?就是直接给类定义不存在的属性,但在运行时动态设置在这些类的对象上。自 PHP 8.2 起,这个动态属性被弃用。

不过呢,也不要气馁。对类进行 __get并且__set仍然有效!所以呢,不用担心。增加一些方法,可以使这个新的弃用不会影响任何实现__get 和类 __set。

php 复制代码
class Test
{
    private array $properties = [];
    
    public function __set(string $name, mixed $value)
    {
        $this->properties[$name] = $value;
    }

}

当然,此处进行了修改之后,也需要对 __get 进行适应的修改,才能正常运行。代码我就不贴了,一看就懂。

三、Deprecated: key方法过时

报错内容:Deprecated: key(): Calling key() on an object is deprecated

在PHP中,当你尝试使用key()函数来获取数组中当前元素的键名,但是你传递给key()的参数是一个对象时,会触发这个已废弃(deprecated)的警告。从PHP 7.2开始,调用key()在对象上是不支持的,并且会引发此类警告。

php 复制代码
    public static function __getSlientDB()
    {

        //原方法
        //return key(self::$__config);

        //使用如下方法替代
        return current(array_keys(get_object_vars(self::$__config)));

    }

在PHP 8中,可使用get_object_vars函数来获取对象的所有属性。这个函数返回一个数组,包含对象中所有可访问的属性和它们的值。上面就可以使用此方法替换已过期的 key 方法。

三、Fatal error:

Fatal error: Uncaught TypeError: Attribute value must be of type int for selected attribute, string given 代码如下:

php 复制代码
    private static $errmode='PDO::ERRMODE_WARNING';
	
    private function initDb()
    {
        
        $this->initTime();

		$db = new PDO(self::$db_dsn, self::$db_username, self::$db_password, self::$db_dotype);

		$db->query(self::$db_querychar);

        // 此处的 PDO::ERRMODE_WARNING 原为设置的$errmode属性值,用的字符串形式
        // 修改为直接使用 PDO::ERRMODE_WARNING,也可将第一行属性去除引号即可
		$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);

        KeDebug::dblog("Link Database {$this->__dbResourceName}.", $this->calculateTime(), $this->__dbResourceName);
		
		return $db;
    
    }

PDO::ERRMODE_WARNING 原为设置的一个属性值,用的字符串形式。在原版本中都能正常,升级后的 php8中,报语法错误类型不对,因此直接使用 。

四、call_user_func_array问题

php8 call_user_func_array Uncaught Error: Unknown named parameterParse error:

原框架在调用 call_user_func_array 的时候传递的 数组参数能正常运行,但在php8.3 中,发现会报错,推测是要求函数中必须要有相关的参数定义,于是在 call_user_func_array 调用的方法上加上了与后面传递的数组参数相同名称的参数名,错误就解决了。