简体   繁体   English

PHP:函数中的常量变量

[英]PHP: constant as variable in function

I'm trying to use constant as a function paramter, is it possible to check type of this constant. 我试图使用常量作为函数参数,是否可以检查此常量的类型。

Example of what I want: 我想要的例子:

class ApiError {
  const INVALID_REQUEST = 200;
}

class Response {
  public function status(ApiError $status) {
    //function code here
  }
}

USE: 使用:

$response = new Response();
$response->status(ApiError::INVALID_REQUEST);

This shoud check that given $status is constant of class ApiError. 这个给定$ status的shoud检查是ApiError类的常量。 Is something like this possible? 这样的事情可能吗?

As the others mentioned, there is no generic solution. 正如其他人提到的那样,没有通用的解决方案。 But if you'd like to do it in a very clean way, model every "object" that you're dealing with (= every possible status), eg: 但是如果你想以一种非常干净的方式做到这一点,那就建模你正在处理的每个“对象”(=每个可能的状态),例如:

interface ApiError {   // make it an abstract class if you need to add logic
    public function getCode();
}

class InvalidRequestApiError implements ApiError {
    public function getCode() {
        return 200;
    }
}

// Usage:
$response = new Response();
$response->status( new InvalidRequestApiError() );

class Response {
    public function status(ApiError $status) {
        echo "API status: " . $status->getCode();
    }
    // ...
}

This leaves you with a lot of classes, because you encapsulate simple numbers, but also with the ability to type-hint. 这会留下很多类,因为您封装了简单的数字,但也具有类型提示功能。

You can use in_array() to test against whitelisted values, which is a recommended strategy whenever you need to validate input to a specific value set: 您可以使用in_array()来测试列入白名单的值,这是您需要验证特定值集的输入时的推荐策略:

// Test if it is in an array of valid status constants...
$valid_statuses = array(
   ApiError::INVALID_REQUEST, 
   ApiError::INVALID_SOMETHINGELSE, 
   ApiError::STATUS_OK
);
if (in_array($status, $valid_statuses)) {
   // it's an acceptable value
}

To whitelist all constants of a class, you could use reflection and retrieve the constants from ApiError via ReflectionClass::getconstants() 要将类的所有常量列入白名单,可以使用反射并通过ReflectionClass::getconstants()ApiError检索常量

$refl = new ReflectionClass('ApiError');
$valid_statuses = $refl->constants();

An other approach would be to change the call. 另一种方法是改变呼叫。 If we want to check if the const is existing, this line would be too late. 如果我们想检查const是否存在,那么这条线就太晚了。 $response->status(ApiError::INVALID_REQUEST);

The php interpreter will also check the const for existence and will die with a Fatal Error. php解释器还将检查const是否存在并将死于致命错误。 That is not catchable using try(). 这不是使用try()捕获的。

So I would suggest to use string as a parameter to check the existence using defined() and constant() 所以我建议使用string作为参数来检查使用defined()constant()的存在性

class ApiError {
  const INVALID_REQUEST = 200;
}

class Response {
  public function status($status) {
    if (!defined('ApiError::'.$status)) {
      return false; // Or throw Exception / other error handling
    }

    $errorCode = constant('ApiError::'.$status);

    //function code here
    return true;
  }
}

The use would then look like this: 然后使用看起来像这样:

$response = new Response();
$response->status('INVALID_REQUEST');

Bad thing is that there is no type hints for this solution. 不好的是,这个解决方案没有类型提示。

I like this approach best: 我最喜欢这种方法:

class NoticeType {
    const INFO = 'neutral';
    const WARN = 'alert';
    const FAIL = 'critical';
    const PASS = 'success';
    const LITE = 'brand';

    private $_type;

    function __construct($NOTICE_constant)
    {
        if (!preg_match('/neutral|alert|critical|success|brand/', $NOTICE_constant))
            throw new \Exception('Invalid parameter for '.__CLASS__.' constructor');
        $this->_type = $NOTICE_constant;
    }
    function getType() {
        return $this->_type;
    }
    function __toString() {
        return $this->_type;
    }
    static function INFO () {
        return new NoticeType(self::INFO);
    }
    static function WARN () {
        return new NoticeType(self::WARN);
    }
    static function FAIL () {
        return new NoticeType(self::FAIL);
    }
    static function PASS () {
        return new NoticeType(self::PASS);
    }
    static function LITE () {
        return new NoticeType(self::LITE);
    }
}

Usage is very straight-forward and you would have to go out of your way to mess up: 使用非常简单,你不得不自己搞砸了:

function test (NoticeType $n) {
    echo ($n == NoticeType::INFO)."\n";
}

test (NoticeType::INFO());

SplEnum could help. SplEnum可以提供帮助。 Example from PHP docs: PHP文档示例:

class Month extends SplEnum {
    const __default = self::January;

    const January = 1;
    const February = 2;
    const March = 3;
    const April = 4;
    const May = 5;
    const June = 6;
    const July = 7;
    const August = 8;
    const September = 9;
    const October = 10;
    const November = 11;
    const December = 12;
}

echo new Month(Month::June) . PHP_EOL;

try {
    new Month(13);
} catch (UnexpectedValueException $uve) {
    echo $uve->getMessage() . PHP_EOL;
}

Output: 输出:

6
Value not a const in enum Month 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM