2012-06-17 2 views
6

Я пытаюсь использовать константу как параметр функции, можно ли проверить тип этой константы.PHP: константа как переменная в функции

Пример того, что я хочу:

class ApiError { 
    const INVALID_REQUEST = 200; 
} 

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

ПРИМЕНЕНИЕ:

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

Это Шоуда проверить, что данный статус $ постоянен класса ApiError. Что-то вроде этого возможно?

+0

статус (ApiError $ статус) ожидает экземпляр класса ApiError не постоянное значение –

+0

я знаю, поэтому я спрашиваю: «Как сделать it " – m4recek

ответ

5

Вы можете использовать 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 
} 

белый список всех констант класса, вы могли бы использовать отражение и извлекать константы из ApiErrorvia ReflectionClass::getconstants()

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

Как уже упоминалось другие, не существует универсального решения. Но если вы хотите сделать это в очень чистом виде, модель каждый «объект», что вы имеете дело с (= всеми возможными состояниями), например:

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(); 
    } 
    // ... 
} 

Это оставляет вас с большим количеством классов , потому что вы инкапсулируете простые числа, но также и с возможностью типа-намека.

+2

Я ненавижу предложение in_array(), потому что это ориентированное на массив программирование в отличие от объектно-ориентированного. –

0

Мне нравится этот подход лучше всего:

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()); 
1

Другой подход был бы измените вызов. Если мы хотим проверить, существует ли константа, эта строка будет слишком поздней. $response->status(ApiError::INVALID_REQUEST);

PHP-интерпретатор также проверяет существование константы и будет умирать с Fatal Error. Это не уловимо, используя try().

Так что я бы предложил использовать строку в качестве параметра, чтобы проверить наличие с помощью определенных() и константы()

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'); 

Плохая вещь в том, что нет никаких намеков типа для этого решения.

+0

IMO это лучший ответ, если вам нужно сохранить константы. –

0

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 
Смежные вопросы