Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: __call i dynamiczne metody
Forum PHP.pl > Forum > PHP > Object-oriented programming
Endzio
Witam.
Jestem w trakcie pisania klasy do wywoływania pluginów, wpadłem na ciekawy pomysł (pewnie nie tylko ja), aby odwoływać się do nich przez metody.

Dla przykładu, plugin panel_bbcode, który wyświetla ikony do wprowadzania tagów BBCode:
  1. $plug = new Plugin();
  2. echo $plug->panel_bbcode();

  1. class Plugin
  2. {
  3. function __call($plugin, $arguments)
  4. {
  5. // Tutaj powinno być include, lub file_get_contents zamiast linijki poniżej
  6. $this->{$plugin} = function ($x, $y, $z) {return 'Plugin '.$plugin.' został wywołany';};
  7.  
  8. // Tutaj powinno być definiowanie metody
  9.  
  10. return call_user_func_array(array($this, $plugin), $arguments);
  11. }
  12. }


Sposób ten (podobno) działa w PHP 5.3, ale używam wersji 5.2
Czy można takie coś zrobić w PHP 5.2?
Crozin
1) Sam pomysł nie wydaje mi się dobry... zawsze cały plugin wpakujesz do jednej metody? IMO dużo lepiej byłoby dla każdego utworzyć osobną klasę, która dziedziczyła by po jakiejś innej (abstrakcyjnej) dającej jakieś tam podstawowe narzędzia wspólne w obrębie wszystkich pluginów.
2) W PHP przed 5.3, nie zadziała Ci linijka: $this->{$plugin}..., ponieważ nie ma obsługi funkcji anonimowych. Ale mógłbyś to chyba ominąć przez create_function (nie jestem jednak pewien czy uda się utworzyć w ten sposób metodę dla obiektu - raczej nie.

W każdym bądź razie, źle kombinujesz...
Endzio
Cytat(Crozin @ 17.01.2010, 12:54:25 ) *
W każdym bądź razie, źle kombinujesz...

Lubię prostotę w kodzie.

Podoba mi się takie rozwiązanie.
W obojętnie jakim miejscu wprowadzam
  1. $plug->panel(...)
i jeśli istnieje taki plugin to "includuje" go (jeśli wcześniej metoda nie została utworzona), rejestruje metodę i wyświetla zawartość, a jeśli nie istnieje to zwraca false.

// Edytka
Po przemyśleniu doszedłem do wniosku, że masz rację, pluginy mogą być klasami, do których bym się odwoływał podobnie:
  1. $plug->panel->show();

a funkcja __call by wyglądała tak:
  1. class Plugin
  2. {
  3. function __call($plugin, $arguments)
  4. {
  5. // Tutaj include lub instrukcja warunkowa
  6. return $this->{$plugin} = new $plugin;
  7. }
  8. }



// Edytka 2
Jednak w ten sposób nie działa.
Aby zadziałało należy wpisać:
  1. $plug->panel();
  2. echo $plug->panel->show();

Przy wywołaniu $plug->panel->show() PHP nie korzysta z metody __call dry.gif
Czy istnieje możliwość pominięcia pierwszej linijki?


// Edytka 3
  1. echo $plug->panel()->show();

Zadziałało, ale w przypadku, gdy plugin nie istnieje PHP wyrzuca błąd
Cytat
Fatal error: Call to a member function show() on a non-object

Sugestie mile widziane smile.gif
bigZbig
W metodzie __call sprawdzaj najpierw czy istnieje klasa o danej nazwie, a jeśli nie istnieje przypisz do danej zmiennej obiekt klasy, która też będzie miała metodę __call z tym, że ta metoda będzie zwracała np. wyjątek albo pustego stringa - w zależności od potrzeb.

Jeśli z kolei interesuje Cie uniwersalne rozwiązanie tego typu zagadnień to proponuje zapoznać się najpierw z:
DTO – wprowadzenie i charakterystyka
a potem
DTO – zastosowanie – Konfiguracja
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.