2012-06-17 10 views
6

Sto cercando di utilizzare costante come parametro di funzione, è possibile controllare il tipo di questa costante.PHP: costante come variabile nella funzione

Esempio di ciò che voglio:

class ApiError { 
    const INVALID_REQUEST = 200; 
} 

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

USO:

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

questo Shoud verificare che, dato lo stato $ è costante della classe ApiError. È possibile qualcosa del genere?

+0

stato (ApiError $ stato) si aspetta che un'istanza della classe ApiError non il valore costante –

+0

Lo so, è per questo che sto chiedendo "Come fare " – m4recek

risposta

5

È possibile utilizzare in_array() da confrontare con i valori whitelist, che è una strategia consigliata ogni volta che è necessario per convalidare l'input ad una specifica valore impostato:

// 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 
} 

di whitelist tutte le costanti di una classe, è possibile utilizzare la riflessione e recuperare le costanti da ApiErrorvia ReflectionClass::getconstants()

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

Mentre gli altri menzionati, non esiste una soluzione generica. Ma se si desidera farlo in un modo molto pulito, modello di ogni "oggetto" che hai a che fare con (= ogni stato possibile), ad esempio:

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

Questo ti lascia con un sacco di classi , perché incapsuli numeri semplici, ma anche con la possibilità di digitare suggerimenti.

+2

Detesto la proposta in_array() perché è una programmazione orientata all'array piuttosto che orientata agli oggetti. –

0

Mi piace questo approccio migliore:

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

utilizzo è molto straight-forward e si dovrebbe andare dal tuo modo di rovinare:

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

test (NoticeType::INFO()); 
1

Un altro approccio sarebbe quello di cambia la chiamata. Se vogliamo verificare se const è esistente, questa linea sarebbe troppo tardi. $response->status(ApiError::INVALID_REQUEST);

L'interprete di php controllerà anche il const per l'esistenza e morirà con un errore irreversibile. Questo non è catchable usando try().

Quindi, vorrei suggerire di usare stringa come un parametro per verificare l'esistenza utilizzando definito() e costante()

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; 
    } 
} 

L'uso sarebbe quindi simile a questa:

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

La cosa brutta è che non ci sono suggerimenti di tipo per questa soluzione.

+0

IMO questa è la migliore risposta se è necessario mantenere costanti. –

0

SplEnum potrebbe aiutare. Esempio da documenti 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; 
} 

uscita:

6 
Value not a const in enum Month 
Problemi correlati