PHPDevs

Projekt obiektowy z Composerem i Twigiem? Czytaj!

Programowanie obiektowe > Lekcja 5

Metody magiczne

Przed nami kolejne dość ciekawe zagadnienie, co prawda z magią ma niewiele wspólnego. Są to w zasadzie normalne metody, ale nazywane magicznymi, ponieważ wywoływane są automatycznie w momencie wykonania danych akcji. Mamy w PHP kilka takich metod i zaraz sobie je omówimy. Występują tylko w kontekście klas, a ich nazwy zaczynają się od __.

__construct i __destruct

Najczęściej używana i spotykana to __construct - konstruktor. Metoda ta wywoływana jest w momencie utworzenia obiektu. Możemy też przekazywać przy jej pomocy dowolną liczbę argumentów. Do czego się przydaje w praktyce? Na przykład do przesłania jakichś wartości do nowo tworzonego obiektu.

Ciekawostka

Konstruktor używany jest przy wzorcu projektowym Dependency Injection (DI, wstrzykiwanie zależności). Jest to bardzo popularne podejście, które polega na wstrzykiwaniu obiektów do klasy, zamiast za każdym razem tworzeniu nowych gdzieś wewnątrz danej klasy. Umożliwia to lepszą kontrolę tego, gdzie dana instancja jest używana, pozwala operować na danym jednym obiekcie czy też będzie pomocne przy tworzeniu testów. Więcej o wzorcach jak i samym wstrzykiwaniu opowiem gdzieś dalej.

Destruktor działa odwrotnie, czyli wykonuje się gdy obiekt jest niszczony. Samemu przeważnie się tego nie robi (chociaż teoretycznie można), więc z chwilą zakończenia wykonywania kodu wszystko jest niszczone.

<?php

class Person
{
    private $name;
    private $city;

    public function __construct(string $name, string $city)
    {
        $this->name = $name;
        $this->city = $city;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function getCity(): string
    {
        return $this->city;
    }

    public function __destruct()
    {
        echo 'Person removed!';
    }
}

$person = new Person('Jan Kowalski', 'Warszawa');
echo 'Name: ' . $person->getName() . ', city: ' . $person->getCity(); // result: Name: Jan Kowalski, city: Warszawa

unset($person); // remove object, result: Person removed!

Uwaga

Dawniej konstruktor definiowany był poprzez utworzenie metody o nazwie identycznej jak nazwa klasy. Jest to zasada bodajże z czasów php 4. Obecnie, od php >=7, taki zapis nie jest już wspierany. Gdybyś jednak kiedyś musiał pracować przy bardzo starym kodzie, to warto o tym wiedzieć.

__get i __set

Metody te wykonują się, gdy odwołujemy się do nieistniejącej właściwości obiektu. __get przy próbie odczytania wartości (przyjmuje jeden argument, którym jest nazwa tejże właściwości), a __set w momencie zmiany nieistniejącej właściwości (przyjmuje dwa argumenty - nazwę i wartość).

<?php
class Person
{
    public function __get($name)
    {
        return false;
    }

    public function __set($name, $value)
    {
        $this->$name = $value;
    }
}

$person = new Person();
$person->city = 'Poznań';
echo 'Name: ' . $person->name . ', city: ' . $person->city; // result: Name: , city: Poznań

Dzięki tym metodom możemy na przykład dynamicznie tworzyć nowe właściwości dla naszego obiektu (patrz przykład powyżej). Brzmi jak fajne ułatwienie, ale w praktyce nie do końca tak jest. Przez takie automatyczne tworzenie właściwości możemy utracić kontrolę nad tym co właściwie będzie działo się z obiektem, bo każdy może do niego dopisać co tylko chce. Z tego też powodu należy tych metod używać z rozwagą. Powiedziałbym nawet, że powinny być używane tylko tam gdzie to naprawdę konieczne, a i są teorie, że w ogóle nie powinny być używane. Wiedzieć, że istnieją z pewnością warto.

__call i __callStatic

Powyżej było coś do nieistniejących właściwości, to może i coś do metod by się przydało? Oto jest. __call uruchamia się w momencie odwołania do nieistniejącej metody. Dostajemy do dyspozycji dwa argumenty: pierwszy z jej nazwą, drugi z tablicą zawierającą przesłane do wywoływanej metody argumenty.

__callStatic działa identycznie, z tym że obsługuje nieistniejące metody statyczne.

W przypadku tych magicznych metod również należy mieć na uwadze słowa, które padły kilka linii wyżej: automatyczne wywoływanie pewnych akcji, gdy metoda nie istnieje, może być przydatne, ale rodzi też niebezpieczeństwo przypadkowego wykonania pewnych rzeczy w niezamierzonym miejscu.

<?php
class Person
{
    public function __call($name, $argunents)
    {
        return 'Method: ' . $name;
    }

    public static function __callStatic($name, $argunents)
    {
        return 'Static method: ' . $name;
    }
}

$person = new Person();
echo $person->getName(); // result: Method: getMethod
echo $person::getName(); // result: Static method: getMethod

__toString

Tej metody możemy użyć, aby w momencie próby wyświetlania całego obiektu został zwrócony jakiś string. Standardowo oczywiście taka próba zakończyła by się błędem, a dzięki __toString możemy tego w razie potrzeby dokonać.

<?php
class Person
{
    public function __toString()
    {
        return 'person';
    }
}

echo new Person(); // result: person

Ważna uwaga

Metody magiczne muszą być publiczne (modyfikator public). W innym przypadku kod po prostu nie zadziała i dostaniemy odpowiedni błąd.

Oprócz wymienionych powyżej istnieją jeszcze następujące magiczne metody:

Nie będę na razie więcej wyjaśniał. Poznałeś podstawowe metody magiczne, w razie czego więcej w manualu. No i pamiętaj o ich rozważnym używaniu ;) Z doświadczenia mogę powiedzieć tyle, że najbardziej powszechny i regularnie używany jest konstruktor, o pozostałych myślałbym bardziej okazyjnie i gdy są naprawdę potrzebne.

Poprzednia lekcja Następna lekcja

Udostępnij

  • Facebook
  • Twitter

Komentarze