Предефинирането в PHP осигурява средства за динамично "създаване" на членове и методи. Динамичните елементи се обработват посредством вълшебни методи, които могат да бъдат добавени към даден клас, с цел извършване на различни операции.
Предефиниращите методи се извикват при осъществяване на достъп до членове и методи, които не са декларирани или не са видими в текущата област на действие. По-нататък в раздела ще се използват термините "недостъпни членове" и "недостъпни методи" за указване на това съчетание от декларация и видимост.
Всички предефиниращи методи трябва да се декларират като public.
Забележка: Параметрите на тези вълшебни методи не могат да бъдат предавани по референция.
Забележка: Интерпретирането на "предефинирането" в PHP е различно от това на повечето обектно-ориентирани езици. Предефинирането обикновено предоставя възможността да съществуват множество методи с едно и също име, но с различен брой и тип на параметрите
Версия | Описание |
---|---|
5.1.0 | Добавени са __isset() и __unset(). |
5.3.0 | Добавен е __callStatic(). Добавено е предупреждение за прилагане на public видимост и нестатично деклариране. |
__set() се изпълнява при запис на данни в недостъпни членове.
__get() се използва за четене на данни от недостъпни членове.
__isset() се задейства при извикване на isset() или empty() с недостъпни членове.
__unset() се извиква когато се използва unset() с недостъпни членове.
Параметърът $name указва името на члена, с който се работи. Параметърът $value на метода __set() указва стойността в която трябва да се установи члена $name.
Предефинирането на членове работи само в контекста на обект. Тези вълшебни методи няма да бъдат извикани в контекста на статично извикване, следователно тези методи не могат да бъдат декларирани като статични.
Example #1 Пример за предефиниране с __get, __set, __isset и __unset
<?php
class MemberTest {
/** Място за предефинирани данни. */
private $data = array();
/** Предефиниране не се извършва при декларирани членове. */
public $declared = 1;
/** Предефинирането задейства само при осъществяване на достъп извън тялото на класа. */
private $hidden = 2;
public function __set($name, $value) {
echo "Установяне на '$name' в '$value'\n";
$this->data[$name] = $value;
}
public function __get($name) {
echo "Връщане на стойността на '$name'\n";
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
$trace = debug_backtrace();
trigger_error(
'Недефинирано свойство посредством __get(): ' . $name .
' в ' . $trace[0]['file'] .
' на ред ' . $trace[0]['line'],
E_USER_NOTICE);
return null;
}
/** От PHP 5.1.0 */
public function __isset($name) {
echo "Установен ли е '$name'?\n";
return isset($this->data[$name]);
}
/** От PHP 5.1.0 */
public function __unset($name) {
echo "Унищожаване на '$name'\n";
unset($this->data[$name]);
}
/** Това не е вълшебен метод, просто е тук за пример. */
public function getHidden() {
return $this->hidden;
}
}
echo "<pre>\n";
$obj = new MemberTest;
$obj->a = 1;
echo $obj->a . "\n\n";
var_dump(isset($obj->a));
unset($obj->a);
var_dump(isset($obj->a));
echo "\n";
echo $obj->declared . "\n\n";
echo "Нека да експериментираме с private свойство именувано 'hidden':\n";
echo "Private свойствата са видими в тялото на класа, така че, не се използва __get()...\n";
echo $obj->getHidden() . "\n";
echo "Private свойствата не са видими извън тялото на класа, така че, се използва __get()...\n";
echo $obj->hidden . "\n";
?>
Примерът по-горе ще изведе:
Установяване на 'a' в '1' Вземане на стойността на 'a' 1 Установен ли е 'a'? bool(true) Унищожаване на 'a' Установен ли е 'a'? bool(false) 1 Нека да експериментираме с private свойство именувано 'hidden' Private свойствата са видими в тялото на класа, така че, не се използва __get()... 2 Private свойствата не са видими извън тялото на класа, така че, се използва __get()... Връщане на стойността на 'hidden' Notice: Undefined property via __get(): hidden in <file> on line 70 in <file> on line 29
__call() се задейства при извикване на недостъпни методи в контекста на обект.
__callStatic() се задейства при извикване на недостъпни методи в контекста на статично извикване.
Параметърът $name указва името на метода, който се извиква. Параметърът $arguments е масив, съдържаш параметрите, които са предадени към метода $name.
Example #2 Предефиниране на методи с __call и __callStatic
<?php
class MethodTest {
public function __call($name, $arguments) {
// Забележка: стойността на $name е чувствителна към регистъра.
echo "Извикване на метод на обект '$name' "
. implode(', ', $arguments). "\n";
}
/** От PHP 5.3.0 */
public static function __callStatic($name, $arguments) {
// Забележка: стойността на $name е чувствителна към регистъра.
echo "Извикване на статичен метод '$name' "
. implode(', ', $arguments). "\n";
}
}
$obj = new MethodTest;
$obj->runTest('в контекста на обект');
MethodTest::runTest('в контекста на статично извикване'); // От PHP 5.3.0
?>
Примерът по-горе ще изведе:
Извикване на метод на обект'runTest' в контекста на обект Извикване на статичен метод 'runTest' в контекста на статично извикване