Предефиниране

Извикването на методи и достъпа до свойствата на даден клас могат да бъдат предефинирани посредством методите __call, __get и __set. Тези методи ще сработят когато текущият или наследеният обект не съдържа свойството или метода към който се осъществява достъп. Предефиниращите методи не трябва да бъде декларирани като статични. Всички методи, които ще се предефинират трябва да бъдат декларирани като public.

От PHP 5.1.0 е възможно предефинирането на функциите isset() и unset() посредством методите, съответно __isset и __unset. Също така, методът __isset се извиква от функция empty().

Предефиниране на свойства

void __set ( string name mixed value )

mixed __get ( string name )

bool __isset ( string name )

void __unset ( string name )

Свойствата на класовете могат да бъдат предефинирани чрез дефинирането на специални методи, с цел изпълнение на собствен код. Параметърът $name съдържа името на променливата която трябва да се установи или върне. Параметъра $value на метода __set() указва стойността с която обекта трябва да установи $name.

Пример 19-19. Пример за предефиниране с __get, __set, __isset и __unset

<?php
class Setter
{
    public $n;
    private $x = array("a" => 1, "b" => 2, "c" => 3);

    public function __get($nm)
    {
        echo "Връщане на [$nm]\n";

        if (isset($this->x[$nm])) {
            $r = $this->x[$nm];
            print "Върнато: $r\n";
            return $r;
        } else {
            echo "Нищо!\n";
        }
    }

    public function __set($nm, $val)
    {
        echo "Установяване на [$nm] в $val\n";

        if (isset($this->x[$nm])) {
            $this->x[$nm] = $val;
            echo "OK!\n";
        } else {
            echo "Не е OK!\n";
        }
    }

    public function __isset($nm)
    {
        echo "Проверка дали $nm е установена\n";

        return isset($this->x[$nm]);
    }

    public function __unset($nm)
    {
        echo "Унищожаване на $nm\n";

        unset($this->x[$nm]);
    }
}

$foo = new Setter();
$foo->n = 1;
$foo->a = 100;
$foo->a++;
$foo->z++;

var_dump(isset($foo->a)); //true
unset($foo->a);
var_dump(isset($foo->a)); //false

// не се предава на __isset() метода
// тъй като 'n' е public свойство
var_dump(isset($foo->n));

var_dump($foo);
?>

Примерът по-горе ще изведе:

Установяване на [a] в 100
OK!
Връщане на [a]
Върнато: 100
Установяване на [a] в 101
OK!
Връщане на [z]
Нищо!
Установяване на [z] в 1
Не е OK!

Проверка дали а е установена
bool(true)
Унищожаване на a
Проверка дали а е установена
bool(false)
bool(true)

object(Setter)#1 (2) {
  ["n"]=>
  int(1)
  ["x:private"]=>
  array(2) {
    ["b"]=>
    int(2)
    ["c"]=>
    int(3)
  }
}

Предефиниране на методи

mixed __call ( string name array arguments )

Вълшебният метод __call() позволява да бъде прихванато извикването на несъществуващи методи. Така, метода __call() може да се използва за реализация на потребителски-дефинирана обработка на методи, която зависи от името на конкретния извикан метод. Това е много удобно за реализация на proxy. Аргументите на фунцкята, ще бъдат предадени като масив в параметъра $arguments. Стойността, върната от метода __call() ще бъде върната към извикващия метод.

Пример 19-20. Пример за предефиниране с __call

<?php
class Caller
{
    private $x = array(1, 2, 3);

    public function __call($m, $a)
    {
        print "Извикан е метод $m:\n";
        var_dump($a);
        return $this->x;
    }
}

$foo = new Caller();
$a = $foo->test(1, "2", 3.4, true);
var_dump($a);
?>

Примерът по-горе ще изведе:

Извикан е метод test:
array(4) {
    [0]=>
    int(1)
    [1]=>
    string(1) "2"
    [2]=>
    float(3.4)
    [3]=>
    bool(true)
}
array(3) {
    [0]=>
    int(1)
    [1]=>
    int(2)
    [2]=>
    int(3)
}