Jak znaleźć dostępne metody publiczne?

9

Uważam, że największym problemem w pracy z Drupalem 8 jest to, że nie mogę uzyskać potrzebnych danych. Drupal 8 chce, żebym używał publicznych metod zamiast ręcznego drążenia obiektu. Problem polega na tym, że nie mogę znaleźć spójnego sposobu na uzyskanie listy dostępnych metod! (istnieją magicznie i wydaje mi się, że powinienem o nich wiedzieć)

W tym przykładzie załóżmy, że mam typ zawartości z polem wideo. Muszę uzyskać nieprzetworzony adres URL pliku wideo w tym polu.

Zacznę więc od identyfikatora węzła ($ nid) i jakoś muszę wymyślić, jak załadować węzeł. Nie jest tak źle, ponieważ jest wiele przykładów. Więc robię coś takiego $node = \Drupal\node\Entity\Node::load($nid);.

Na razie w porządku. Następnie muszę uzyskać wartość mojego pola wideo (field_main_video). Zajęło mi to ZAWSZE rozszyfrowanie, ponieważ wokół sieci istnieje sprzeczna dokumentacja. W końcu pomyślałem, że muszę zrobić coś takiego (ponieważ jest to element wielowartościowy):

$video = \Drupal\node\Entity\Node::load($nid)->field_main_video->getValue();

... a potem zapętlić tablicę itp. Użycie kinta również mi nie pomogło. Ponieważ na przykład, jeśli szukam kint($node)metod, nie widzę w tym getValue () elementu. Nadal nie jest straszny, ponieważ było wystarczająco dużo przykładów, aby to rozgryźć.

Kiedy jednak wchodziłem głębiej, nie wiedziałem (to jest ważna część), że zamiast uzyskać identyfikator encji pola wideo, a następnie załadować encję, a następnie znaleźć pole „uri” w encji itp. (Np. Chciałbym w D7): Była metoda, która pozwala mi uzyskać URI wszystko w tym samym wierszu kodu!

$url = \Drupal\node\Entity\Node::load($nid)->field_main_video->entity->getFileUri();

Ale skąd mogłem wiedzieć, że istnieje metoda getFileUri ()? Zdarzyło mi się natknąć na to w poście na blogu. To naprawdę sprawia, że ​​uzyskanie URI jest łatwiejsze niż w D7 ... ale tylko wtedy, gdy wiesz (magicznie), jakie metody istnieją dla każdego 'poziomu' obiektu.

Na koniec w tym przykładzie pytam: Jak znaleźć wszystkie publiczne metody dla każdego poziomu obiektu w sposób łatwy do odczytania i zrozumienia? Zauważ, że wydaje się, że powinien istnieć sposób na drupal-centryczny (tj. Moduł programistyczny), zamiast ręcznego przeszukiwania api.drupal.org lub używania czegoś specyficznego dla IDE?

Konstabl
źródło
1
Oficjalna dokumentacja znajduje się na api.drupal.org. Po zrozumieniu klasy obiektu, którym się posługujesz, otrzymujesz wszystkie metody, w tym odziedziczone.
kiamlaluno
1
... ale zamiast sprawdzać wszystko na api.drupal.org, na pewno istnieje sposób w php / devel na zrzucenie dostępnych metod na ekran na polecenie?
Bobby

Odpowiedzi:

14

Podmioty treści różnią się od większości innych tym, że często nie mają metod i odpowiednich interfejsów, przynajmniej nie dla pól konfigurowalnych.

W przypadku encji treści i pól metody publiczne nie są tak naprawdę tym, co naprawdę chcesz wiedzieć, a tym, czego chcesz, to wiedzieć o polach i właściwościach. I tylko wtedy, gdy ponownie dojdziesz do bytu poprzez referencję, metody mają znaczenie.

Dla ogólnego przeglądu zawsze odwołuję się do wspaniałego ściągu interfejsu API Entity API .

Elementy treści mają stałą strukturę, Entity> Field (FieldItemList)> FieldItem -> Właściwość. Właściwość jest skalarna lub odnosi się do czegoś innego, np. Innej encji, obiektu językowego, obiektu daty ...

W kilku określonych przykładach kilka użytecznych fragmentów:

// List of fields that an entity has, the field definitions also have a lot of information like the type.
array_keys($entity->getFieldDefinitions())

// Use get() instead of the magic __get() on the entity level then you at least get some type hints.
$entity->get('field_name').

// Get the list of properties a certain field has, use array_keys() again for just the names, but the definitions also have the type and if it's computed or not.
$entity->getFieldDefinition('field_name')->getFieldStorageDefinition()->getPropertyDefinitions()

// Most field types have value property, but e.g. entity references have target_id and the computed entity. as you found. File and Image fields have additional properties like title/alt/description.
$entity->get('field_name')->value
$entity->get('field_name')->target_id
$entity->get('field_name')->entity

// Note that get('value') is not the same as ->value on the field item level, get() returns a typed data object, get('value')->getValue() is the same as ->value.

// When not specified, the delta 0 is assumed (all fields are a list internally, even something like the node id), you can use array access or the delta to access another delta, make sure it exists.
$entity->get('field_name')[1]->value
$entity->get('field_name')->get(1)->value

// When you have an entity reference, you can get the entity type and class like this:
$entity->get('field_name')->entity->getEntityTypeId()
$entity->get('field_name')->entity->getEntityType()->getClass()
// or 
get_class($entity->get('field_name')->entity)

// From there you can look up the interface and type hint against that, to a) make sure you have a valid, loadable reference and get type hints in an IDE:
$file = $entity->get('field_name')->entity;
if ($file instanceof \Drupal\file\FileInterface) {
  $file->getFileUri();
}
Berdir
źródło
Miły! Zajmie to trochę czasu, ale pochylam się nad tym, aby być zaakceptowaną odpowiedzią. Dzięki! To nie odpowiada dokładnie na pytanie, ale to tylko dlatego, że moje pytanie i mój przykład zadawały 2 różne rzeczy. Dziękuję Ci!
Bobby,
1
@Berdir, to niesamowita lista przykładów, naprawdę trafiających w gwoździe. Po prostu szukałem w Google niektórych informacji, jakichkolwiek informacji i nic nawet blisko tego. Świetna odpowiedź, materiał książkowy.
Marko Blazekovic
4

Nie jestem pewien, czy to całkowicie odpowie na twoje pytanie, ale bardzo pomaga mi korzystanie z funkcji diagramów w PhpStorm.

Na przykład pokazując hierarchię wprowadź opis zdjęcia tutaj

Masz opcje, aby wyświetlić także nazwy metod

wprowadź opis zdjęcia tutaj

Mam nadzieję, że ci to pomoże.

Oleg Videnov
źródło
Możesz także otworzyć klasę za pomocą polecenia + kliknięcia, a następnie polecenia + 7 lub kliknij kartę Struktura, aby zobaczyć strukturę klas (gdzie byłby widok katalogu projektu), aby szybko zeskanować te same informacje bez otwierania UML.
Kevin
Nie używam phpstorma, ale warto o tym wiedzieć w przyszłości. Szukam sposobu na zrobienie tego za pomocą devel lub czegoś drupal-centric. na pewno coś musi być gdzieś wbudowane?
Bobby
Przykro mi to mówić, ale tak naprawdę nie sądzę, aby w tym momencie można było majstrować przy interfejsie API bez użycia tego IDE.
Oleg Videnov
NetBeans zawiera również niektóre diagramy hierarchii PHP. Prawdopodobnie nie tak fajnie, ale NetBeans jest wolnym oprogramowaniem (PHP Storm jest zamkniętym źródłem, a IMHO drogie) i można go pobrać za darmo.
sanzante
Może to zrobić każde IDE warte swojej soli. BTW PHPStorm nie jest drogi, jeśli wykorzystasz to, co ma do zaoferowania. Możesz skorzystać z darmowej wersji EAP, a jeśli pracujesz nad projektem open source (moduły lub motywy Drupal), JetBrains da Tobie bezpłatną licencję. Ale tutaj nie ma dyskusji.
Kevin
4

Cóż, dość często używałem kombinacji, var_dump(get_class_methods($object))aby mieć listę dostępnych metod dla danej klasy.

Często szukam też api.drupal.orgdalszych szczegółów.

Yvan
źródło
2
To wydaje się być odpowiedzią najbardziej zbliżoną do tego, czego do tej pory szukałem. Dzięki!
Bobby
0

Jesteś już bardzo blisko.

Najpierw spójrzmy na definicję metody: https://api.drupal.org/api/drupal/core%21modules%21file%21src%21Entity%21File.php/function/File%3A%3AgetFileUri/8.2.x

Stąd możemy zobaczyć klasę, której jest częścią, i jest do niej link:

Class

File
Defines the file entity class.

Kliknięcie powoduje przejście do: https://api.drupal.org/api/drupal/core%21modules%21file%21src%21Entity%21File.php/class/File/8.2.x

W swoim IDE możesz także wyszukać \Drupal\file\Entity\Fileklasę. Jednym ze sposobów, aby upewnić się, że jest to poprawna klasa, jest spojrzenie na adnotację:

@ContentEntityType(
  id = "file",
  label = @Translation("File"),
  handlers = {
    "storage" = "Drupal\file\FileStorage",
    "storage_schema" = "Drupal\file\FileStorageSchema",
    "access" = "Drupal\file\FileAccessControlHandler",
    "views_data" = "Drupal\file\FileViewsData",
  },
  base_table = "file_managed",
  entity_keys = {
    "id" = "fid",
    "label" = "filename",
    "langcode" = "langcode",
    "uuid" = "uuid"
  }
) 

Zauważ id- jest file. Przypuszczalnie, jeśli debugujesz, możesz spojrzeć na zawartość field_main_video->entityi zobaczysz gdzieś ten identyfikator. Następnie po prostu wyszukaj go w swoim IDE. Zazwyczaj jednak wie się wystarczająco dużo o typach jednostek, których się używa, aby odgadnąć drogę do właściwej klasy (po czym można sprawdzić, czy adnotacja zawiera poprawny identyfikator).

W tym konkretnym przypadku wiem też, że prawdopodobnieFile jest to klasa, która się rozszerza , ponieważ bardziej przypomina ona zawartość bazy danych (encja treści) niż konfigurację (encja konfiguracji). Więc kiedy widzę, że moje założenia się potwierdzają, to pomaga mi wiedzieć, że znalazłem właściwą klasę.ContentEntityBase

Krótko mówiąc: twoje IDE, strategiczne debug()deklaracje i pewne domysły to najlepsze sposoby na odkrycie Drupala 8.

Pomocne mogą być również rekordy PS Change. Są na https://www.drupal.org/list-changes/drupal

wizonesolutions
źródło
Uważam, że problem PO jest odwrotny: wiedza o metodach publicznych, które klasa implementuje / udostępnia.
kiamlaluno
Tak, może będę musiał przeczytać to jeszcze raz, ale nie sądzę, że tego właśnie szukam. Próbuję dowiedzieć się, jak w ogóle istnieje metoda getFileUri ()!
Bobby
@Bobby Plik jest typem encji, więc po prostu spójrz na jego źródło , gdzie znajdziesz metodę, której szukasz, w pełni udokumentowaną. Czy po prostu nie wiedziałeś, że plik jest typem jednostki? A może nie znasz konwencji lokalizacji typu jednostki w kodzie? A może coś jeszcze w łańcuchu? W D8 jest wiele warstw abstrakcji dla wszystkiego, jest to sposób na symfony, więc jest dużo podstawowej wiedzy, której potrzebujesz, zanim zagłębisz się w kod
Clive
0

Możesz użyć funkcji get_class_methods w PHP. Poniższy przykład przedstawia przesyłanie plików:

$image = $form_state->getValue('image_field_name_from_form');
$file = File::load( $image[0] );
$file->setPermanent();
$file->save();

$methods = [];
foreach (get_class_methods($file) as $method) {
        $methods[] = $method;
}
print_r($methods);

Spowoduje to dodanie wszystkich metod dostępnych do pliku obiektowego $ do tablicy $ metod, którą można wydrukować, a następnie zobaczyć wszystkie dostępne metody. Dotyczy to dowolnych obiektów w PHP, nie tylko Drupala.

Cristian Cordeiro
źródło