Jak udokumentować metody magic (_call i _callStatic) dla IDE

81

Po wielu szczęśliwych latach kodowania w notatniku ++ i wysublimowanym, doradzono mi, abym spróbował PHP IDE. Wypróbowuję phpStorm i wydaje mi się to fajne. Uzupełnianie kodu i dokumentacja to świetna funkcja, ale nie działa, gdy używane są magiczne metody. Czy jest jakaś praca, aby phpStorm zrozumiał, co się dzieje w magicznych metodach?

Nasza sytuacja wygląda mniej więcej tak:

abstract class a {
    public static function __callStatic($method,$args)
    {
        if(strpos($method,"get_by_") === 0)
        {
            //do stuff
        } elseif(strpos($method,"get_first_by_") === 0) {
            //do stuff
        } elseif($method == "get_all") {
            //do stuff
        }
    }
}

class b extends a {
    // some more stuff
}

b::get_by_user_id(27);
b::get_first_by_id(156);
b::get_all();

Magiczna metoda callStatic pozwala nam pobrać kolekcję obiektów za pomocą 1 lub więcej argumentów, które składają się na wywołanie funkcji.

Widzę, że w takich przypadkach istnieje instrukcja @method, ale phpStorm przechwytuje tylko pierwsze z tych instrukcji. Ponadto mogę ustawić zwracany typ tylko na mieszany, ponieważ wolałbym móc ustawić go jako dowolną klasę, do której została wywołana (b w moim przykładzie).

Wszelkie pomysły lub sugestie będą bardzo wdzięczne, dzięki.

Rob Forrest
źródło
1
DLACZEGO KTOŚ POMYŚLAŁ, ŻE PODEJŚCIE _callTO DOBRY POMYSŁ? !!
Brian Gordon,
Muszę powiedzieć, że dał +1 komentarzowi Briana na wypadek, gdyby jakakolwiek rozsądna osoba znalazła to pytanie. Magiczne metody są dla wszystkich intencji i celów: nieudokumentowane (spróbuj udokumentować (n) [parametr | warunek wstępny | warunek końcowy | wyjątek] do metody magicznej), nie są przyjazne dla IDE (spróbuj krok po kroku debugować magiczną metodę), odporne na refaktoryzację (proszę, nawet nie rozważaj próby refaktoryzacji magicznej metody w stałym oprogramowaniu) i LAZY (ok, ta ostatnia może być interpretowana jako opinia).
Luke A. Leber
17
-1 do opinii w komentarzu @ LukeA.Leber, ponieważ świadczy o braku wizji. Podczas gdy metody magiczne nie są sposobem na napisanie mniejszej ilości kodu (jeśli używasz ich do lenistwa), metody magiczne umożliwiają tworzenie architektur, które w innym przypadku nie byłyby możliwe lub które byłyby tak skandalicznie złożone, że nie warto by ich pisać. I są całkowicie przyjazne dla IDE podczas używania PHPDoc. Zauważ, że przez większość czasu nie potrzebujesz magicznych metod, ale kiedy ich potrzebujesz, nie ma ich zastępstwa (w PHP). Kiedy są używane w bardzo uporządkowany sposób, użycie ich jest kompletnym, prawidłowym rozwiązaniem.
MikeSchinkel
5
Nie myśl, że nadpisywanie __callto zły pomysł. Chodzi o wdrożenie. Implementacja pokazana w powyższym pytaniu zdecydowanie nie byłaby najlepszym sposobem, ale w przypadku łańcuchowych interfejsów API zapewnia dużą elastyczność.
Steve Bauman

Odpowiedzi:

144

Użyj komentarza PHPDoc na poziomie klasy - w szczególności tagu @method - działa dobrze w PhpStorm:

/**
 * @method static someClass get_by_user_id(int $id) Bla-bla
 * @method static someClass get_first_by_id(int $id) 
 */
abstract class a {
...

W powyższym:

  • @method - tag PHPDoc
  • static - mówi, że jest to metoda statyczna
  • someClasslub $this- typ zwrotu
  • get_by_user_id - nazwa metody
  • (int $id) - podpis metody: ([[type] [parameter]<, ...>])
  • Bla-bla - opcjonalny opis

Więcej o @method:

PS Chociaż @method staticdziała dobrze w PhpStorm (mówi IDE, że metoda jest statyczna), może nie być (jeszcze?) Obsługiwane przez rzeczywiste narzędzie phpDocumentor (przepraszam, nie używałem go przez jakiś czas).


Alternatywnie : (oczywiście w PhpStorm) Settings | Inspections | PHP | Undefined | Undefined method --> Downgrade severity if __magic methods are present in class- w żaden sposób nie pomoże to w uzupełnianiu kodu dla takich metod, ale nie będzie oznaczać tych magicznych metod jako błędów "niezdefiniowanej metody".


bilet phpDocumentor dotyczący używania RegEx / częściowych nazw dla @property/ @methodtagów (jak może to być przydatne dla dokumentacji i jak niewielką pomoc może wnieść do rzeczywistego IDE podczas zajmowania się uzupełnianiem kodu):

LazyOne
źródło
2
Dzięki, wygląda to na rozsądną sugestię i na pewno działa w phpStorm, ale jestem trochę niechętny zapisywaniu potencjalnie setek wierszy @method na początku każdej klasy. Widzisz, że metoda get_by_ * może być poprzedzona dowolnym parametrem obiektu, aby uzyskać obiekty tego typu za pomocą określonego parametru. Nawet wykluczając możliwość get_by_ _and_ skończyłbym z około 1500 @methodsw 140 różnych klasach. Czy nie ma bardziej ogólnego sposobu dostarczania dokumentacji?
Rob Forrest
Nie. Wszystkie magiczne metody muszą być specjalnie zadeklarowane (to jest główny punkt dokumentowania w ten sposób) - PHPDoc nie rozumie częściowych nazw (np get_by_*(int $id).). Dla IDE (kontrola kodu, a nie zakończenie!) Masz rozwiązanie alt (wyłącz ostrzeżenia). Dla phpDocumentor (lub narzędzia alternatywnego) - nie jest mi znane rozwiązanie (może jest, ale ja o tym nie wiem). Masz link do github - załóż nowe zgłoszenie i poproś o dodanie takich „nazw częściowych” pasujących funkcjonalności - zobacz co powiedzą (najprawdopodobniej zostanie odrzucone). Jeśli zostanie zaimplementowany, IDE może go mieć również później.
LazyOne
github.com/phpDocumentor/phpDocumentor2/issues - ale przed wysłaniem swojego sprawdź, czy podobny bilet nie istnieje.
LazyOne
Dzięki za to wszystko. Obecnie istnieje otwarty bilet w związku z tym, ale wydaje się, że wszystko ucichło. Umieściłem tam komentarz i zobaczymy, co z tego wyniknie.
Rob Forrest
2
Dla porównania, bilet phpDocumentor (aby inni użytkownicy wiedzieli, o jakim bilecie mówisz; dodali go również do samej odpowiedzi): github.com/phpDocumentor/phpDocumentor2/issues/689
LazyOne
4

Nieco związane z oryginalnym pytaniem:

Możesz również zdefiniować to w pliku meta phpstorm. Oto przykład metody fabrycznej (wersja 2016.3):

// Define in .phpstorm.meta.php
namespace PHPSTORM_META {
    $STATIC_METHOD_TYPES = [
        \Factory::create('') => [],
    ];
}

// Then use in code
$factory = new \Factory();
$user = $factory->create(\User::class);
// Here you get autocomplete.
$user->subscribe();

W ten sposób nie musisz blokować wszystkich możliwości, gdy dzieje się magia.

Poproś o dokumenty, aby uzyskać szczegółowe informacje.

Yauheni Prakopchyk
źródło
To nie działa z __call. To także nie jest udokumentowane i nieprawidłowe PHP. PHPStorm zapewnia wsparcie tylko tam, gdzie masz statycznie zdefiniowane metody, które zwracają mieszankę typów w zależności od danych wejściowych.
jgmjgm