【问题标题】:PHP: Class constants in type declarations of input paramatersPHP:输入参数的类型声明中的类常量
【发布时间】:2021-03-21 19:30:44
【问题描述】:

对于自定义记录器,我想强制调用者传递Psr\Log\LogLevel 中定义的有效类常量。

这个类的定义如下:

namespace Psr\Log;
/**
 * Describes log levels.
 */
class LogLevel
{
    const EMERGENCY = 'emergency';
    const ALERT     = 'alert';
    const CRITICAL  = 'critical';
    const ERROR     = 'error';
    const WARNING   = 'warning';
    const NOTICE    = 'notice';
    const INFO      = 'info';
    const DEBUG     = 'debug';
}

记录器的功能(错误)如下所示:

public static function log($log, LogLevel $logLevel = null): void {
   // .....
}

这不起作用,因为 LogLevel::DEBUG 例如是一个字符串而不是类的实例。有没有办法在 PHP 类型声明中强制使用类常量?因为如果我定义string 那么你显然可以传递任何字符串,但我只想允许声明的常量。

【问题讨论】:

  • 尝试使用 LogLevel::$logLevel
  • @Nullable 我应该如何声明没有语法错误?
  • 我认为这是不可能的;你应该用定义的 LogLevel 实例化一个 LogLevel,或者在你的 log 方法中有一个 check 方法。
  • 我同意@Bobot
  • @Blackbam 这在 PHP 文档中没有描述

标签: php parameters typing class-constants


【解决方案1】:

PHP 没有常量限制,只有类型。

但是你可以做一个这样的解决方法:

class LogLevel
{
    protected string $logName;

    private function __construct(string $logName)
    {
        $this->logName = $logName;
    }
    public function getName(): string
    {
        return $this->logName;
    }

    public static function emergency(): self
    {
        return new self('emergency');
    }

    public static function alert(): self
    {
        return new self('alert');
    }

    public static function critical(): self
    {
        return new self('critical');
    }
    // create the other constants here
}

现在你的静态函数可以工作了

public static function log($log, LogLevel $logLevel = null): void {
   // .....
}

$logLevel 将收到LogLevel::emergency()LogLevel::critical() 等,您只需调用$logLevel->getName() 即可获得关卡名称

【讨论】:

    【解决方案2】:

    如果你有 Phpstorm,你可以使用新的 #[ExpectedValues] 属性功能:https://blog.jetbrains.com/phpstorm/2020/10/phpstorm-2020-3-eap-4/#expectedvalues_examples

    【讨论】:

    • 令人兴奋的功能感谢分享!请注意:这不会在运行时应用,这只是 PHPStorm 功能。
    • 这不会验证调用者是否传递了正确的值,这些只是建议哪些常量可用?
    • 是的,您应该将其视为Static Analysis Tool。但是如果你想在运行时检查它,你应该自己做
    【解决方案3】:

    没有简单的方法,但您可以检查插入的字符串是否与某些值匹配

    function checkLog(string $logLevel){
      $acceptableValues = array("emergency", "error", "debug");
      if(!in_array($logLevel, $acceptableValues) die();
    }
    
    

    用你的类的常量替换数组中的字符串。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-16
      • 2016-07-21
      • 1970-01-01
      • 2021-11-25
      • 2010-09-28
      • 2015-09-12
      相关资源
      最近更新 更多