【私人系列】日常PHP遇到的各种稀奇古怪的问题

在类的__destruct(){}中无法调用指定文件获取其内容

环境:

php8、iis7、http、某框架

过程:

  1. 某个控制器的 __destruct(){} 中调用A对象,该对象的执行需要先获得BC两个配置文件;
  2. BC两个配置文件的路径都采用了相对路径,其中B文件在入口文件所在目录之外,C文件在入口文件所在目录之内;
  3. 代码顺序是先读取B文件再读取C文件,系统提示无法读取C文件
  4. 这个调用方式写在该控制器其它方法中都能成功,唯独在 __destruct(){} 中出错。

可能性:

  1. __destruct()方法在对象销毁时自动调用,此时文件包含路径可能已经变化,无法找到文件。
  2. __destruct()方法执行时,脚本可能已经完成,资源被释放,文件句柄关闭,导致无法读取文件。
  3. __destruct()方法内部不能进行I/O操作,包括文件包含,会自动执行abort()终止脚本。

根据后来找到的解决方案第一条,我认为第一种可能性为最大。

解决:

  1. BASE_DIR 修改B文件为绝对路径后正常;
  2. 在读取文件之前使用 file_exists确定文件是否存在,规避该问题,后续还要不判断类是否存在,否则还是会报错;
  3. 不在 __destruct(){} 中执行该操作,规避该问题;
  4. 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 转换成整型数据时会丢失精度。

解决:

  1. 打开 …\xxx.php 文件。
  2. 找到第66行,检查类型转换的代码:
    很有可能是这样的:
$int_value = (int) 16.8; 

或者

$int_value = intval(16.8);
  1. 修改代码改用 round() 函数显式四舍五入:
$int_value = round(16.8); 
// 现在 $int_value 是 17,没有丢失精度
  1. 或者直接使用float值:
$float_value = 16.8;
// 不需要转换为整数
  1. 如果需要确切的整数值,可以指定 round() 函数的精度:
$int_value = round(16.8, 0);
// 现在 $int_value 是 17
  1. 保存文件,重新运行 PHP 代码测试。
  2. 如果提示信息还存在,请仔细检查代码,看看是否有其他隐式类型转换。
    修改后的代码可以正常运行,且不会再出现该提示信息。
    原因是显示使用 round() 函数进行四舍五入,避免了将浮点值隐式转换为整数时可能导致的精度损失问题。

案例:

原代码:

mt_rand(self::$fontSize*1.2, self::$fontSize*1.6)

分析:

mt_rand()函数返回的是一个整数,而 self::$fontSize 应该是一个整数像素值,那么 self::$fontSize*1.2self::$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)
)

通过显式四舍五入或者强制类型转换,可以避免浮点数向整数的隐式转换,从而避免精度损失。

在这里插入图片描述

阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有 28 28 个按键,分别印有 26 26 个小写英文字母和 B、P 两个字母。经阿狸研究发现,这个打字机是这样工作的: 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。 按一下印有 B 的按键,打字机凹槽中最后一个字母会消失。 按一下印有 P 的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。 例如,阿狸输入 aPaPBbP,纸上被打印的字符如下: a aa ab 我们把纸上打印出来的字符串从 1 1 开始顺序编号,一直到 � n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数 ( � , � ) (x,y)(其中 1 ≤ � , � ≤ � 1≤x,y≤n),打字机会显示第 � x 个打印的字符串在第 � y 个打印的字符串中出现了多少次。 阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么? 输入格式 输入的第一行包含一个字符串,按阿狸的输入顺序给出所有阿狸输入的字符。 第二行包含一个整数 � m,表示询问个数。 接下来 � m 行描述所有由小键盘输入的询问。其中第 � i 行包含两个整数 � , � x,y,表示第 � i 个询问为 ( � , � ) (x,y)。 输出格式 输出 � m 行,其中第 � i 行包含一个整数,表示第 � i 个询问的答案
06-09
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值