在类的__destruct(){}中无法调用指定文件获取其内容
环境:
php8、iis7、http、某框架
过程:
- 某个控制器的
__destruct(){}
中调用A对象,该对象的执行需要先获得B和C两个配置文件; - B和C两个配置文件的路径都采用了相对路径,其中B文件在入口文件所在目录之外,C文件在入口文件所在目录之内;
- 代码顺序是先读取B文件再读取C文件,系统提示无法读取C文件;
- 这个调用方式写在该控制器其它方法中都能成功,唯独在
__destruct(){}
中出错。
可能性:
- __destruct()方法在对象销毁时自动调用,此时文件包含路径可能已经变化,无法找到文件。
- __destruct()方法执行时,脚本可能已经完成,资源被释放,文件句柄关闭,导致无法读取文件。
- __destruct()方法内部不能进行I/O操作,包括文件包含,会自动执行abort()终止脚本。
根据后来找到的解决方案第一条,我认为第一种可能性为最大。
解决:
- 用
BASE_DIR
修改B文件为绝对路径后正常; - 在读取文件之前使用
file_exists
确定文件是否存在,规避该问题,后续还要不判断类是否存在,否则还是会报错; - 不在
__destruct(){}
中执行该操作,规避该问题; - 用
try {}catch(Error $e){}
来解决该问题。
php后一个页面死活获取不到前一个页面的session,非常不稳定
环境:
php8、iis6、http
过程:
1、生成一个token,存储在服务器session中,提交token给前端页面;
2、前端提交表单时同时提交该token,结果服务器中的session为空;
可能性:
研究一天,时好时坏,在不同浏览器中可能好可能坏,正当崩溃之时,似乎一切都好了但很快又挂了。。。
php中设置session过期时间的方法详解
解决办法就是手动给一个session的过期时间,要实现则只能与cookie配合完成。一般情况下上这样就解决问题了。但,凡事有个但。。。
前端页面cookie中存储该session的id,但提交给后端时,该id对应session消失或出错;
后又推测是当时在进行安全演防,session一超过数量就被清理,于是cookie对应的session就不见了,当然,这个推测是极其不靠谱的,妥妥的失败。。。
将php升级到最新版本,依旧不对。。。蓸
解决:
最后,tmd,是框架核心引擎的最高安全模式(有三个模式)中这句话出错了
session_set_cookie_params(0,NULL,NULL,TRUE);
改成这样就没问题了。具体参数参考官方:session_set_cookie_params
session_set_cookie_params(0,NULL,NULL,NULL,TRUE);
参考:
php 中session_set_cookie_params 和 setcookie 函数的区别与用法
php文件无法上传,session无法获取或生成
环境:
php8、iis6
解决:
因某些原因session存储目录或文件上传的缓存目录中缓存文件数超过2的16次方-1,即25535,清空即可。
一般是写一个批处理文件,用系统自带的时间计划,定时清理。
内容如下:
echo 正在清理文件,请稍等......
del /f /s /q D:\temp\phpSession\*
del /f /s /q D:\temp\phpUpload\*
精度丢失(float to int loses precision)
错误:
错误提示:PHP Deprecated: Implicit conversion from float 16.8 to int loses precision in ...\xxx.php on line 66
提示的意思是:在...\xxx.php 第66行存在一个隐式类型转换:从浮点数 16.8 转换成整型数据时会丢失精度。
解决:
- 打开 …\xxx.php 文件。
- 找到第66行,检查类型转换的代码:
很有可能是这样的:
$int_value = (int) 16.8;
或者
$int_value = intval(16.8);
- 修改代码改用 round() 函数显式四舍五入:
$int_value = round(16.8);
// 现在 $int_value 是 17,没有丢失精度
- 或者直接使用float值:
$float_value = 16.8;
// 不需要转换为整数
- 如果需要确切的整数值,可以指定 round() 函数的精度:
$int_value = round(16.8, 0);
// 现在 $int_value 是 17
- 保存文件,重新运行 PHP 代码测试。
- 如果提示信息还存在,请仔细检查代码,看看是否有其他隐式类型转换。
修改后的代码可以正常运行,且不会再出现该提示信息。
原因是显示使用 round() 函数进行四舍五入,避免了将浮点值隐式转换为整数时可能导致的精度损失问题。
案例:
原代码:
mt_rand(self::$fontSize*1.2, self::$fontSize*1.6)
分析:
mt_rand()
函数返回的是一个整数,而 self::$fontSize
应该是一个整数像素值,那么 self::$fontSize*1.2
和 self::$fontSize*1.6
计算出来的值就是浮点数了。
由于 mt_rand()
期望接收整数参数,所以这里做了浮点数向整数的隐式转换,但由于浮点数的数值可能非整除,这个隐式转换很可能会导致精度损失。所以 PHP 给出了这个提示,告诉你:Implicit conversion from float 16.8 to int loses precision
,即从浮点数 16.8 转换到整数会丢失精度。
为了解决这个问题,可以对 mt_rand()
的参数做显式四舍五入,避免精度损失:
mt_rand(
round(self::$fontSize*1.2),
round(self::$fontSize*1.6)
)
或者直接使用整型值参数:
mt_rand(
intval(self::$fontSize*1.2),
intval(self::$fontSize*1.6)
)
通过显式四舍五入或者强制类型转换,可以避免浮点数向整数的隐式转换,从而避免精度损失。