Reputation: 434
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. Is something like this possible?
Upvotes: 8
Views: 6672
Reputation: 3529
SplEnum could help. Example from PHP docs:
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
Upvotes: 0
Reputation: 81
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.
$response->status(ApiError::INVALID_REQUEST);
The php interpreter will also check the const for existence and will die with a Fatal Error. That is not catchable using try().
So I would suggest to use string as a parameter to check the existence using defined() and 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.
Upvotes: 2
Reputation: 8733
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());
Upvotes: 1
Reputation: 26730
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), e.g.:
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.
Upvotes: 11
Reputation: 270599
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:
// 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()
$refl = new ReflectionClass('ApiError');
$valid_statuses = $refl->constants();
Upvotes: 5