php - PHP 7 中静默 "Declaration ... should be compatible"警告

标签 php php-7 php-7.2 php-7.1 php-7.0

升级到 PHP 7 后,日志几乎因此类错误而堵塞:

PHP 警告:Example::do($a, $b, $c) 的声明应与 Example.php 第 22548 行的 ParentOfExample::do($c = null) 兼容

如何在 PHP 7 中消除这些且仅消除这些错误?

  • 在 PHP 7 之前,它们是 E_STRICT 类型的警告 which could be easily dealt with 。现在它们只是普通的旧警告。由于我确实想了解其他警告,因此我不能完全关闭所有警告。

  • 我没有能力重写这些遗留 API,更不用说所有使用它们的软件了。你猜怎么着,没有人会为此付出代价。我也不是一开始就开发它们的,所以我不是应该受到指责的人。 (单元测试?十年前还不流行。)

  • 我想避免any trickeryfunc_get_args 以及尽可能类似的内容。

  • 并不是真的,我想降级到 PHP 5。

  • 我仍然想了解其他错误和警告。

有没有一种干净又好的方法来实现这一点?

最佳答案

1。解决方法

由于并不总是能够纠正您没有编写的所有代码,尤其是遗留代码......

if (PHP_MAJOR_VERSION >= 7) {
    set_error_handler(function ($errno, $errstr) {
       return strpos($errstr, 'Declaration of') === 0;
    }, E_WARNING);
}

对于以 Declaration of 开头的警告,此错误处理程序返回 true,这基本上告诉 PHP 警告已得到处理。这就是 PHP 不会在其他地方报告此警告的原因。

另外,此代码只能在 PHP 7 或更高版本中运行。

<小时/>

如果您希望这种情况仅在特定代码库中发生,那么您可以检查有错误的文件是否属于该代码库或感兴趣的库:

if (PHP_MAJOR_VERSION >= 7) {
    set_error_handler(function ($errno, $errstr, $file) {
        return strpos($file, 'path/to/legacy/library') !== false &&
            strpos($errstr, 'Declaration of') === 0;
    }, E_WARNING);
}
<小时/>

2。正确的解决方案

至于实际修复别人的遗留代码,在很多情况下,这可以在简单和易于管理之间完成。在下面的示例中,B 类是 A 的子类。请注意,您不一定会按照这些示例删除任何 LSP 违规。

  1. 有些情况非常简单。如果子类中缺少默认参数,只需添加它并继续。例如。在这种情况下:

    Declaration of B::foo() should be compatible with A::foo($bar = null)
    

    你会这样做:

    - public function foo()
    + public function foo($bar = null)
    
  2. 如果您在子类中添加了其他约束,请在函数体内移动时将它们从定义中删除。

    Declaration of B::add(Baz $baz) should be compatible with A::add($n)
    

    您可能需要根据严重性使用断言或引发异常。

    - public function add(Baz $baz)
    + public function add($baz)
      {
    +     assert($baz instanceof Baz);
    

    如果您发现约束纯粹用于文档目的,请将它们移到它们所属的位置。

    - protected function setValue(Baz $baz)
    + /**
    +  * @param Baz $baz
    +  */
    + protected function setValue($baz)
      {
    +     /** @var $baz Baz */
    
  3. 如果子类的参数比父类(super class)少,并且可以在父类(super class)中将它们设置为可选,则只需在子类中添加占位符即可。给定错误字符串:

    Declaration of B::foo($param = '') should be compatible with A::foo($x = 40, $y = '')
    

    你会这样做:

    - public function foo($param = '')
    + public function foo($param = '', $_ = null)
    
  4. 如果您发现子类中需要某些参数,请将问题交给您处理。

    - protected function foo($bar)
    + protected function foo($bar = null)
      {
    +     if (empty($bar['key'])) {
    +         throw new Exception("Invalid argument");
    +     }
    
  5. 有时,更改父类(super class)方法以完全排除可选参数可能会更容易,从而回到 func_get_args 魔法。不要忘记记录缺少的参数。

      /**
    +  * @param callable $bar
       */
    - public function getFoo($bar = false)
    + public function getFoo()
      {
    +     if (func_num_args() && $bar = func_get_arg(0)) {
    +         // go on with $bar
    

    当然,如果您必须删除多个参数,这可能会变得非常乏味。

  6. 如果你严重违反替代原则,事情就会变得更加有趣。如果您没有输入参数,那么这很容易。只需将所有额外参数设置为可选,然后检查它们是否存在。给出的错误:

    Declaration of B::save($key, $value) should be compatible with A::save($foo = NULL)
    

    你会这样做:

    - public function save($key, $value)
    + public function save($key = null, $value = null)
      {
    +     if (func_num_args() < 2) {
    +         throw new Exception("Required argument missing");
    +     }
    

    请注意,我们无法在此处使用 func_get_args(),因为它不考虑默认(未传递)参数。我们只剩下 func_num_args()

  7. 如果您有一整套具有不同接口(interface)的类层次结构,那么进一步使其分化可能会更容易。重命名每个类中定义冲突的函数。然后在这些类的单个中间父级中添加代理函数:

    function save($arg = null) // conforms to the parent
    {
        $args = func_get_args();
        return $this->saveExtra(...$args); // diverged interface
    }
    

    这样,LSP 仍然会被违反,尽管没有警告,但您可以保留子类中的所有类型检查。

关于php - PHP 7 中静默 "Declaration ... should be compatible"警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36079651/

相关文章:

Docker、Alpine、IonCube、PHP7 FPM

wordpress - 无法从 Google App Engine PHP 7.2 环境建立外部 HTTP 连接

ubuntu - 如何在 xampp Ubuntu 18.04 中安装/启用 GD?

php - 将 jQuery/AJAX 脚本附加到使用 window.setInterval(, 1000*60) 方法添加的元素

php - 在使用 CodeIgniter 的表单验证类之前处理输入

php - 如何准备查询以从另一个表检查然后从另一个表获取

php - MYSQL查询单字段两次调用

php - 将所有 mysql_* 函数切换为 mysqli_* 函数会导致警告错误

php - Linux - PHP 7.0 和 MSSQL (Microsoft SQL)

php - E : Unable to locate package php7. 2-bcmath