PHP中是否可能弃用方法参数?

6

Lets say I have a method:

public function createFoo(Foo $foo, $isPremiumFoo=false);

事后看来,让 $isPremiumFoo 标志参数挂在方法末尾有点儿傻。因此我们把它放到了 Foo 中,现在我想从方法签名中删除它。但我不想一下子全部删除,因为这是一个公共方法,已经被外部使用。我想使用 @deprecate 警告用户停止使用它,然后最终将其移除。由于 PHP 中不能重载方法,那么怎样才能只弃用该方法的参数而不是整个方法呢?

如果您能够修改createFoo的内容,只需在其前面添加func_num_args检查即可(我假设您正在谈论弃用createFoo($foo, true)createFoo($foo, false)调用;否则,仅检查$isPremiumFoo === false将是微不足道的)。 - raina77ow
对不起,我的意思是如何将方法参数标记为@deprecated而不将整个方法标记为过时。 - Josh Johnson
@JoshJohnson 只需从签名中删除它。如果有人提供了2个参数,请记住它。如果只有一个 - 使用Foo属性的那个。 - Royal Bg
4个回答

9
如果您使用的是 PhpStorm 2020.3 或更新版本,则可以使用 #[Deprecated] 属性。它在 PHP 版本 < 8 中被解析为注释,在 >=8 版本中被解析为属性。

Usage of deprecated parameter attribute


7
您可以像这样做:
class Foo {

}
class Bar {
    public function createFoo(Foo $foo, $isPremiumFoo=false) {
        if (count(func_get_args()) > 1) {
            $warn = "isPremiumFoo is deprecated and will be removed 
                     in a future release"; 
            trigger_error($warn, E_USER_NOTICE);    
        }
        // continue with the implementation
    }
}

$foo = new Foo();
$bar = new Bar();

$bar->createFoo($foo);         // wont trigger the notice
$bar->createFoo($foo, true);   // will trigger the notice
$bar->createFoo($foo, false);  // will trigger the notice

谢谢!我接受这个答案是因为它完成了工作并且至少在运行时发出警告(额外的好处是日志聚合器可以报告使用情况),但我仍然在寻找一种方法,让常见的编辑器(PHPStorm、Vi等)在用户输入时像处理@deprecated方法一样提醒用户。 - Josh Johnson
2
任何想使用这种方法的人请注意,E_USER_DEPRECATED是在PHP 5.3中添加的,更适合此目的。 - h00ligan

2

我也做过同样的事情。我们团队采用的方法是更新文档块。

然后在IDE中,当有人弹出时,他们可以清楚地看到它已经被弃用并且我们不再使用它。随着时间的推移,我们最终将其完全删除。

例如:

/**
 * Create Foo
 *    
 * @param Foo Description
 * @param bool Deprecated, use Foo->setIsPremium(true|false)
 *
 * @return Bar
 */
public function createFoo(Foo $foo, $isPremiumFoo=false);

对于新用户来说,是的。但是现有用户可能甚至没有意识到这种变化。难道不应该像PHP弃用一样吗?你的网站使用mysql_*函数。你升级到PHP 5.5,所有日志都会被弃用方法的通知填满。 - Royal Bg
完全有可能。我们所处的情况可能会更加独特,因为我们正在处理大部分新员工和快速变化的代码库。感谢您的评论,我可能会考虑在不久的将来加入这些警告。 - caseyw

0
<?php
class Foo
{
    private $isPremium = false;

    public function setPremium($premium)
    {
        $this->isPremium = $premium;
    }

    public function isPremium() 
    {
        return $this->isPremium;
    }
}

function createFoo(Foo $foo)
{
    if (func_num_args() > 1) {
        $isPremium = func_get_args()[1];
        $foo->setPremium($isPremium);
    }

    return $foo;
}

$foo = new Foo();
var_dump(createFoo($foo)); // false (because default value is false in the class)
$foo->setPremium(true);
var_dump(createFoo($foo)); // true (the new way - you can manipulate it as an object property.)
var_dump(createFoo($foo, false)); // false (even thought you have manipulated it, it's backwards compatibility for users who are using the second param)
var_dump(createFoo($foo, true)); // true (again backward compatibility)

解释在代码注释中。基本上,没有任何东西阻止您使用比函数接收的更多参数调用函数。因此,您可以安全地从签名中删除它,并在函数体中进行检查。

使用这种逻辑,如果提供了第二个参数,您可以向用户显示某种警告。使用新API的新用户可能甚至不知道曾经存在第二个参数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接