【问题标题】:Intermittent PHP Abstract Class Error间歇性 PHP 抽象类错误
【发布时间】:2018-04-14 21:54:24
【问题描述】:

我已经为此奋斗了一段时间,但无法弄清楚,也许其他人有或者也许这里有 Slim、PHP、Apache 等更深层次的问题。在工作了几个小时后,我的 Slim 安装将开始在所有路线上提供这个:

致命错误:Slim\Collection 类包含 1 个抽象方法,因此必须声明为抽象方法或实现 F:\Projects\example\server\vendor\slim\slim\Slim\Collection 中的剩余方法 (IteratorAggregate::getIterator) .php 在第 21 行

如果我重新启动 Apache,这个问题就会消失。 (反正几个小时。)

我发现两年前有人遇到过类似的问题,而帮助他们的人根本没有真正帮助他们:https://community.apachefriends.org/viewtopic.php?p=250966&sid=96ef58aaeb7fe142a7dcdfd506a8683f

我已尝试彻底清除并安装我的作曲家供应商目录。这不能解决问题。我可以清楚地看到getIterator在错误消息中的文件中按预期实现了。

PHP 版本 7.0.12、Windows 7、x86 PHP 构建

几个小时后又发生了,出现了不同但相似的错误消息:

致命错误:Pimple\Container 类包含 1 个抽象方法,因此必须声明为抽象方法或实现 F:\Projects\example\server\vendor\pimple\pimple\src\Pimple 中的剩余方法 (ArrayAccess::sqlserver) \Container.php 第 34 行

这个问题有一个类似的问题,并通过重新启动 PHP 来“解决”它,但这显然不是一个实际的解决方案,而且我没有启用 opcache: PHP 7, Symfony 3: Fatal error 1 abstract method and must therefore be declared abstract or implement the remaining methods

有什么猜测吗?请记住:此消息位于我未编写的文件中,并在 Apache 重新启动时消失。 PHP 7 是否有一些缓存会导致这种情况?

编辑 3/10/17:

是的,我已经用 Slim 开了一张票。我还在一个非超薄文件(Pimple)中看到它,所以我认为这不是一个超薄问题。 https://github.com/slimphp/Slim/issues/2160

正如我所说,我的 opcache 已关闭。我已经在 php.ini 文件和查看 phpinfo() 中确认了这一点。

【问题讨论】:

  • 我已经尝试更新到 PHP 7.1,但仍然每天一次,强制重启 apache。
  • 这与我的问题类似:phabricator.wikimedia.org/T152502
  • 我没有使用 slim 的经验,所以这是问题文件吗? github.com/slimphp/Slim-Http/blob/master/src/Collection.php 如果没有,那你能发布代码吗?您是否尝试过联系框架的维护者?
  • 你能用小提琴重新创建场景吗?令我惊讶的是,apache 重新启动解决了这个问题,因为您提到 Opcache 无论如何都被禁用了。如果从 cli 构造类 100% 的时间有效并且缓存被禁用。然后,您需要查看代码。此外,您是否 100% 确定您没有另一个名为“Container”的类位于不同的命名空间中,并且它不会在某些条件下尝试实例化错误的类?
  • 这不是我可以放入 jsfiddle 或类似的东西。问题在于现有的标准库,并且代码很好。 (正如重新启动修复问题所证明的那样。)令人发指的是,问题已经消失了,但我不知道为什么或是否会再次出现。很沮丧。如果您在这里希望得到解决方案,请发表评论以保持此线程活跃。

标签: php apache slim


【解决方案1】:

我想你遇到了this opcache bug。这不是完全相同的情况,但可能相关。

调用 opcache_reset() 函数后,我们遇到了一些奇怪的错误。 它在服务器上随机发生(400 台服务器中的 10 台生产)

一些字母 a 被其他字母替换,Class 似乎已经被声明了.. 等等

opcache_reset() 后触发的错误示例:

  • PHP 致命错误:XXX 类包含 1 个抽象方法,因此必须声明为抽象方法或实现其余方法 (YYY::funczzz) 在第 20 行的 /dir/dir/x.php 中

门票已关闭,因为开发人员没有足够的信息来重现它。如果你能想出最小的可重现案例,我推荐reporting it。创建一个非常小的 Slim 应用程序,然后使用 JMeter 或其他工具发出许多请求。发布您的发现。

同时,唯一的解决方法可能是在 php.ini 中关闭 opcache:

opcache.enable=0

当然,这会严重影响性能。在它修复之前,您必须在性能或定期重启 Apache 之间做出选择。

如果关闭缓存不起作用,那么我能想到的唯一原因是操作码编译器的间歇性问题。缓存与否,编译后的版本必须有错误。如果这是原因,那么与 PHP 开发人员开一个可重现的票证或自己调试 PHP 源代码将是唯一的出路。

【讨论】:

  • 是的,我也这么认为。所以我禁用了它,并在我的问题中提到了这一点。禁用后很长时间仍然发生。
  • 添加到我的答案中。也许,虽然不太可能,这是编译器的问题。
  • @WillShaver 只是想知道您是否找到了解决问题的方法,因为目前我也遇到了同样的情况
  • @martink 对不起,我从来没有这样做过。我尝试了很多东西,但由于它只在我的开发盒上而不是生产中,我只是偶尔重新启动了 apache 服务器。
【解决方案2】:

我在使用 CodeIgniter 和 PHP 7.1.x 时遇到了同样的问题。

我升级到PHP 7.2,问题不再出现。

【讨论】:

    【解决方案3】:

    如果您在 Windows 上开发,我建议您不要使用 XAMPP 或 WAMPP,并在 VM 上尝试使用 Linux 的真正开发服务器。

    尝试安装 Vagrant 和 Virtualbox,然后前往 puphpet.com,它可以为您生成虚拟机配置。解压下载,cd 到文件夹,输入 vagrant up。然后只需将您的主机指向虚拟机。我敢打赌,一旦你有了一个真正的开发环境,这个错误就会消失。您的另一个选择是 Docker,但它有一些学习曲线。

    问题不在于您的代码(或您的供应商代码),而在于您的平台。

    【讨论】:

    【解决方案4】:

    我遇到了这种确切的行为,它不是完全是 opcache 错误,即使它由 opcache 引起的。

    问题是我们有几个具有相同基名的类,例如

    Request\GenericProtocol\Dispatcher     abstract
    Request\Protocol1\Dispatcher
    Request\Protocol2\Dispatcher
    

    现在默认情况下,我们的安装 opcache 使用“优化”仅使用基本名称作为缓存键。结果,每当一个脚本碰巧在一个干净的缓存上实例化一个 Protocol2 Dispatcher 时,它就巧妙地破坏了对 Protocol1 的所有后续调用。由于使用模式,这伪装成任何其他类型的错误。

    最后我们只是激活了相应的选项:

    opcache.use_cwd 布尔值

    如果启用,OPcache 会将当前工作目录附加到脚本键,从而消除具有相同基本名称的文件之间可能发生的冲突。禁用此指令会提高性能,但可能会破坏现有应用程序

    中断条件是这样的:你至少有两个类具有相同的基本名称

    我们的下一次迭代确实计划重命名很多类

     Request\Protocol1\Dispatcher   ==> Request\Protocol1\Protocol1Dispatcher
    

    能够重新禁用 use_cwd 并压缩百分之几的性能(PTB 和 PHB 认为这是值得的),但我知道这可能不适用于所有框架。

    【讨论】:

      猜你喜欢
      • 2012-02-06
      • 2016-05-20
      • 1970-01-01
      • 2023-03-07
      • 2016-04-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多