Close

Not a member yet? Register now and get started.

lock and key

Sign in to your account.

Account Login

Forgot your password?

Php Magic Methods

19 мар Posted by Митко Масарлиев in Php | Comments
Php Magic Methods

Функциите __construct, __destruct, __call, __callStatic, __get, __set, __isset, __unset, __sleep, __wakeup, __toString, __invoke, __set_state и __clone са наречени магически в класовете на php. Не може да имате функция с такива имена в класовете освен ако не искате да ползвате магическата им функционалност.
Конструктори и деконструктори
__construct

PHP 5 позволява на разработчиците да декларират конструктори на класовете. Класове, които имат метод-конструктор, извикват този метод при всяко създаване на нов обект, така че той е много подходящ за извършване на инициализации, от които обектът се нуждае преди да бъде използван.

Забележка: Конструкторите на родителските класове не се извикват автоматично, ако в даден дъщерен клас е дефиниран конструктор. За да се изпълни конструкторът на родителския клас, е необходимо да се извика parent::__construct() в тялото на конструктора на дъщерния клас.

void __construct ([ mixed $args [, $... ]] )

< ?php
class Foo {
     function __construct(){
          echo "Hello World";
     }
}
$foo = new Foo();// Hello World

__destruct

В PHP 5 е въведен деструкторен метод, по подобие на другите обектно-ориентирани езици като C++. Деструкторът ще се извика в момента, в който обектът бъде унищожен.
void __destruct ( void )

< ?php
class Foo {
     function __construct(){
          echo "Hello ";
     }
     function __destruct(){
          echo "World";
     }
}
$foo = new Foo();// Hello World

Предефиниране на методи
__call ( string $name , array $arguments )
__callStatic ( string $name , array $arguments )
__call() се задейства при извикване на недостъпни методи в контекста на обект.
__callStatic() се задейства при извикване на недостъпни методи в контекста на статично извикване.

Параметърът $name указва името на метода, който се извиква. Параметърът $arguments е масив, съдържаш параметрите, които са предадени към метода $name.

< ?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’ в контекста на статично извикване

Предефиниране на свойства
void __set ( string $name , mixed $value )
mixed __get ( string $name )
bool __isset ( string $name )
void __unset ( string $name )

__set() се изпълнява при запис на данни в недостъпни членове.
__get() се използва за четене на данни от недостъпни членове.
__isset() се задейства при извикване на isset() или empty() с недостъпни членове.
__unset() се извиква когато се използва unset() с недостъпни членове.

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

Предефинирането на членове работи само в контекста на обект. Тези вълшебни методи няма да бъдат извикани в контекста на статично извикване, следователно тези методи не могат да бъдат декларирани като статични.

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

$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 on line 70 in on line 29

__sleep и __wakeup

serialize() проверява дали в класа ви има функция с вълшебното име __sleep. Ако открие такава, то тази функция се изпълнява преди всяка сериализация. Тя би могла да изчисти обекта и се очаква да върне масив с имената на всички променливи от този обект, които ще бъдат сериалзирани. Ако методът не върне нищо, тогава се сериализира стойността NULL и се генерира грешка от тип E_NOTICE.

Предназначението на __sleep е да затвори всички връзки към бази от данни, които обектът може да има, да съхрани незаписаните данни или да изпълни други подобни изчистващи задачи. Също така функцията може да се използва и в случай, че имате много големи обекти, които няма нужда да бъдат съхранени изцяло.

Обратно – unserialize() проверява за наличието на функция с вълшебното име __wakeup. Ако тя съществува, функцията може да възстанови всички ресурси, които даден обект може да има.

Употребата на __wakeup има за цел да възстанови всички връзки към бази от данни, които може да са били прекъснати по време на сериализацията и за извършване на други повторно-инициализиращи задачи.

__toString

Методът __toString позволява на даден клас да реши как ще реагира, в случай че бъде преобразуван до низ.

< ?php
// Дефиниция на клас
class TestClass
{
    public $foo;

    public function __construct($foo) {
        $this->foo = $foo;
    }

    public function __toString() {
        return $this->foo;
    }
}

$class = new TestClass('Здравей');
echo $class;
?>

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

__invoke
Методът __invoke се извиква, когато даден скрипт направи опит да извика обект, както се извиква функция.

< ?php
class CallableClass {
  function __invoke($x) {
    var_dump($x);
  }
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
?>

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

int(5)
bool(true)

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • RSS
  • Twitter
  • Yahoo! Bookmarks
  • email
  • Netvibes
  • Technorati

 


Leave a comment