我正在尝试使用常量作为函数参数,是否可以检查此常量的类型。
我想要的例子:
class ApiError {
const INVALID_REQUEST = 200;
}
class Response {
public function status(ApiError $status) {
//function code here
}
}
用:
$response = new Response();
$response->status(ApiError::INVALID_REQUEST);
这个应该检查给定的$status是类 ApiError 的常量。这样的事情可能吗?
正如其他人提到的,没有通用的解决方案。但是,如果您想以一种非常干净的方式做到这一点,请对您正在处理的每个"对象"(= 每个可能的状态)进行建模,例如:
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();
}
// ...
}
这给你留下了很多类,因为你封装了简单的数字,但也具有键入提示的能力。
您可以使用
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
}
要将类的所有常量列入白名单,您可以使用反射并通过ReflectionClass::getconstants()
从ApiError
中检索常量
$refl = new ReflectionClass('ApiError');
$valid_statuses = $refl->constants();
另一种方法是更改调用。如果我们想检查 const 是否存在,这一行为时已晚。 $response->status(ApiError::INVALID_REQUEST);
php 解释器还将检查 const 是否存在,并将因致命错误而死亡。这是使用 try() 无法捕获的。
所以我建议使用字符串作为参数来使用 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;
}
}
然后,使用将如下所示:
$response = new Response();
$response->status('INVALID_REQUEST');
不好的是,此解决方案没有类型提示。
我最喜欢这种方法:
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);
}
}
用法非常简单,你必须不遗余力地搞砸:
function test (NoticeType $n) {
echo ($n == NoticeType::INFO)."'n";
}
test (NoticeType::INFO());
SplEnum可以提供帮助。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;
}
输出:
6
Value not a const in enum Month