Jak zaimplementować proste sprawdzanie typów w PHP5?
Teoretycznie proste sprawdzanie typów w funkcjach, przy liÅ›cie argumentów, już jest - ale nie dotyczy to typów wbudowanych a obiektów. Czasem jednak jest potrzebny sposób na automatyczne sprawdzenie rodzaju zamiennej - i to postaram siÄ™ niżej omówić.
Nie da siÄ™ kontroli typów zrobić jak w C++, gdzie jest ona bardziej Å›cisÅ‚a, ale myÅ›lÄ™ że w wielu wypadkach starczy. Jest to o tyle wygodne, że Å‚atwiej nieco bÄ™dzie wykrywać nieÅ›cisÅ‚oÅ›ci (zresztÄ…, po to jest sprawdzanie typów).
Przykład kodu:
class Test
{
protected $properties = array(
'var1' => array('tralala', 'string'),
'var2' => array(3, 'integer'),
'var3' => array(array('tralala', 'bulcykcyk), 'array')
);
public function __set($key, $value)
{
if (!array_key_exists($key, $this->properties)) {
throw new Exception(sprintf('"%s" property doesn't exists.', $key));
}
if (gettype($value) != $this->properties[$key][1]) {
throw new Exception(sprintf('"%s" property must be an "%s" type, is "%s".',
$key,
$this->properties[$key][1],
gettype($value)
));
}
$this->properties[$key][0] = $value;
}
}
Najtrudniejszym elementem jest tutaj każdorazowe ustawianie właściwej konstrukcji zmiennej $properties, ponieważ ta tablica ma konkretny format:
$properties = array(
'nazwa_zmiennej' => array('wartość', 'typ')
)
Jako "wartość" wstawiamy tam wartość wÅ‚aÅ›ciwoÅ›ci (obojÄ™tnie, czy obiekt, int, string, tablicÄ™ czy coÅ› innego), a jako "typ" - wartość zwracana przez funkcjÄ™ getttype() wywoÅ‚anÄ… na przechowywanym obiekcie. Dla napisów bÄ™dzie to wartość "string", dla liczb caÅ‚kowitych: "integer", a dla obiektów: "object".
Ta kontrola typów jest o tyle uproszczona, że nie sprawdza, czy przechowywany obiekt jest instancjÄ… danej klasy (tej która ma być przechowywana), oraz czy tablica przechowuje żądany typ obiektów. O ile pierwsze czasem warto, i Å‚atwo zrobić za pomocÄ… is_a() czy też get_class(), o tyle drugie może być trudniejsze i wymagać funkcji dodatkowych (jeÅ›li sprawdzanie ma być niezależne od iloÅ›ci zagłębieÅ„ tablicy).
Przykład użycia:
$a = new Test;
try {
$a->var1 = 'asd'; //ok
$a->var2 = 1; //ok
$a->var3 = array(1, 2, 3); //ok
//$a->var1 = 1; //exception!
//$a->var2 = 'a'; //exception!
//$a->var3 = 1; //exception!
} catch (Exception $e) {
echo $e->getMessage();
}
W moim wypadku najlepszym rozwiązaniem było utworzenie klasy "Test" jako abstrakcyjnej ("abstract") i tworzenie kolejnych klas jako dziedziczących z niej. Każde z dzieci musi oczywiście mieć swoją wersję tablicy "$properties".