Heim > Fragen und Antworten > Hauptteil
In PHP 8.1 veraltet null
作为参数传递给许多核心函数。我的主要问题是 htmlspecialchars(php)
和 trim(php)
等函数,其中 null
nicht mehr stillschweigend in einen leeren String konvertiert.
Um dieses Problem zu lösen, ohne viel Code zu verwenden, habe ich versucht, die ursprünglich integrierten Funktionen umzubenennen und sie durch Wrapper zu ersetzen, die die Eingabe von null
in einen (leeren) String konvertieren.
Das Hauptproblem bei diesem Ansatz besteht darin, dass die Funktion rename_function(PECL apd)
nicht mehr funktioniert, sie wurde zuletzt im Jahr 2004 1 aktualisiert.
Ich muss die integrierten Funktionen neu schreiben, um zu vermeiden, dass bei jedem Aufruf der Funktion eine Nullprüfung geschrieben wird, wodurch mein gesamter Code doppelt so groß wird.
Die einzige andere Lösung, die mir einfällt, besteht darin, einfach meine benutzerdefinierte Funktion zu verwenden, aber dafür muss ich immer noch den gesamten Code und die Bibliotheken von Drittanbietern durchgehen, die ich habe.
In PHP 8.1 wird null nicht mehr stillschweigend in eine leere Zeichenfolge umgewandelt, wenn es an eine integrierte Funktion übergeben wird.
P粉8113290342024-01-11 15:36:30
我想(作为补充,现有的答案得到了我的支持)就如何看待和解决此类“问题”描绘了一幅不同的图画。它并没有减少所概述的方法的正确性或错误性,而只是一种希望互惠互利的附加观点。每个项目都是不同的。
给定前提:
那么这对我来说(首先)看起来是一个报告问题。通过不报告 E_DEPRECATED
。
这样做的好处是(不仅是您的代码),现在知道您的代码带有弃用通知。报告确实有效。
另一方面,压制弃用通知可能会让它们消失。如果您丢失了代码库带有弃用通知的信息,从技术上讲,从信息丢失中恢复可能仍然很容易(再次报告弃用通知),但是如果更改的时间延长了,现在可能会出现压倒性的噪音 (E_TOO_MUCH_NOISE)。
那么代码不沉默实际上是一件坏事吗?或者说可以转化为利益吗?我宁愿选择后者。不管怎样,我们已经在处理这些信息了。
因此,在这种情况中,我的想法是一般不抑制弃用通知,而是“静默”函数调用。这很容易,但无论从好的方面还是从坏的方面来说,这都是愚蠢的:
trim($mixed); #1 -> @trim($mixed); #2
这当然是一个可以使用标准文本工具应用于代码库的操作。它还会向您显示过去已经使用过 @
抑制运算符的位置:
@trim($mixed); #3 -> @@trim($mixed); #4
如果您是一名 PHP 开发人员,在编辑器中查看此类代码(对于情况#2-#4),他们会立即向您尖叫,并且对于所有四种情况至少都会引起您的注意($mixed
)。
感谢您没有保持沉默,我们让这些地方尖叫,只是不是在运行时1。
与第一种通过不报告 E_DEPRECATED
来保持沉默的方法不同,这种方法很容易丢失信息,而信息是通过使用所有 @
符号来保存的。
它对解决噪音问题有帮助吗?如果我们停止在这里工作,那就完全不行了。现在我们会在代码上涂上@
-符号,决定不采取进一步的操作,这样我们就可以使用第一个解决方案(不报告弃用消息)来完成它,而无需触及代码。 p>
那么它的好处是什么?好吧,尽管代码现在静默运行,PHP 仍然提供诊断消息。也就是说,现在可以将 PHP 错误处理程序注册为侦听器(在执行代码时)。
仅在代码级别,很容易检查这些位置,因为 @
符号(通常)也很容易在代码中发现。
第二部分很很重要,因为尽管多个地方可能会受到弃用的影响,但一定不能有一个解决方案来解决所有问题(我更喜欢远离“一刀切” '解决方案'”(如果可能的话),但特别是在问题上下文中 PHP 8.1 发生了变化,我可以想象根据使用地点会有不同的需求。
例如,在模板代码(输出)中,具体类型不是一个问题,因此转换为字符串很可能是首选解决方案:
@trim($mixed); -> trim((string)$mixed) @@trim($mixed); -> @trim((string)$mixed)
模板(输出)保持稳定。
但对于实际的输入处理,弃用通知可能会发现值得修复的实际潜在缺陷,例如缺少默认值(使事情变得过于复杂)、值的处理不明确(空与空、字符串、布尔与数字)与 PHP 中的数组与对象)或一般的 $mixed
混淆。
这样的 trim($mixed)
可能是一个被遗忘多年的安全防护,从未进行过升级(有更好的安全防护可用)。对于这样的代码,我很确定我已经想要并要求 $mixed
实际上是 $string
before 我使用 trim ()
。原因很简单,至少直接想到两件事:
trim()
- 它可以被删除(我最喜欢的修复之一:删除代码!) - 或 -李>
使用 $mixed 进行修补是完全有效的? ''
如果原始使用是字符串或null
仅。
@trim($mixed); -> trim($mixed ?? '') @@trim($mixed); -> @trim($mixed ?? '')
但除此之外,例如像 42 这样的数字,将抛出 TypeError
,而不是弃用消息。这可以区分正在运行的代码和未运行的代码。
因此,这里还有更多需要维护的地方,例如检查位置,如果可能的话进一步聚类,然后应用更多专用修复程序。它可能会揭示缺失的测试或断言,需要一些时间来稳定整个应用程序流程等。
在这种情况下,要完成代码的迁移,进行集群,处理空合并运算符,并为真正的修复做适当的文书工作。一旦完成了使用空合并运算符的非明显错误抑制并删除了 @
抑制运算符,如果修复计划未捕获这些信息,您可能会丢失这些信息。
当我在这些地方看起来受过更多教育时,当我发现自己挠头或揉眼睛时,我并不感到惊讶。然后我提醒自己,这些错误不是因为 PHP 8.1 版本造成的,版本更改只是让它们(再次)出现,有时我什至会通过维护 PHP 版本来获得完整的错误集群作为副渔获物。
备忘单
(string)$mixed
- 之前的行为$mixed ?? ''
- 仅在 null
上抑制 TypeError
错误@
- 完全错误抑制。您应该在适用的地方记录您的代码库。@@
- 如果出现这种情况,这可能是一个值得研究的有趣地方。空($mixed)? '' : xxx($mixed)
- 把垃圾带出去,典型的空瘫/混合混乱,寻找集群,有机会大大简化代码库。迁移到标量类型(PHP 7),从最内向外引入严格的类型处理,在适用的情况下使用 PHP“经典”和“严格”类型处理。 PHP 7.0 断言和 PHP 8.1 弃用消息可以很好地支持这里。错误处理程序
错误处理没有什么魔力,它是 PHP.net 上记录的标准(与 Example #1),它作为错误事件的观察者,可以区分受抑制的错误和非受抑制的错误通过 error_reporting(php)
/ error_reporting(php-ini)
至少达到通常需要的级别,如果需要进行区分(在生产环境中,E_DEPRECATED
通常不是报告的一部分)。此示例性处理程序会抛出所有报告的错误,对于弃用事件以及 E_ALL
也会抛出此类错误,因此需要 @
抑制运算符不抛出:
set_error_handler(static function ($type, $message, $file, $line) use (&$deprecations) {
if (!(error_reporting() & $type)) {
// This error code is not included in error_reporting, so let it fall
// through to the standard PHP error handler
// capture E_DEPRECATED
if ($type === E_DEPRECATED) {
$deprecations[] =
['deprecations' => count($deprecations ?: [])]
+ get_defined_vars();
}
return false;
}
// throwing error handler, stand-in for own error reporter
// which may also be `return false;`
throw new ErrorException($message, $type, error_reporting(), $file, $line);
});
类似的错误处理程序可以在 3v4l.org 上的扩展示例中找到,包括要报告的已弃用代码上。
E_USER_DEPRECATED
从技术上讲,错误抑制运算符可以与 E_USER_DEPRECATED
结合使用,与上面 E_DEPRECATED
概述的相同。
但是,对它的控制较少并且它可能已被项目依赖项中已有的第三方代码使用。类似下面的代码并不罕见:
@trigger_error('this. a message.', E_USER_DEPRECATED);
它的作用完全相同:发出弃用事件,但将它们从 PHP 报告中排除。订阅这些内容可能会让您陷入噪音之中。使用 E_DEPRECATED
,您总是可以直接从 PHP 获得“好的、原创的”。
@
错误抑制运算符的方法并对其进行评论时,IMSoP 立即举起红/黑旗(正确!),很容易将婴儿与洗澡水一起倒掉@
抑制运算符。在我的回答中,它的目的只是抑制弃用通知但是使用的结果是它抑制所有诊断消息和错误,在某些 PHP 版本中甚至是致命的消息和错误,因此 PHP 退出 255,无需任何进一步的诊断 - 不仅要小心,还要处理。这个运营商很强大。跟踪它在代码库中的使用情况并不断检查它是否符合您的基线/期望。对于合法情况,请考虑使用消音器。为了移植/维护代码,首先使用它来标记。完成批量编辑后,再次将其删除。P粉5920854232024-01-11 00:24:47
首先,要记住两件事:
htmlspecialchars($something)
可以替换为 htmlspecialchars($something ?? '')
接下来,一些选项:
?? ''
或修复一个逻辑错误,无论如何你都不希望出现 null。nullable_htmlspecialchars
等自定义函数,并在代码中直接查找和替换。nullableoverride\htmlspecialchars
;然后在添加 use function nullableoverride\htmlspecialchars;
的任何文件中,将使用该函数而不是内置函数。不过,这必须添加到每个文件中,因此您可能需要一个工具来自动添加它。?? ''
到适当的函数调用,因此您不必手动编辑它们。不幸的是,似乎还没有这方面的内置规则,因此您必须学会编写自己的规则。?? ''
到简单的情况。