Wie finde ich verfügbare öffentliche Methoden?


9

Ich stelle fest, dass das größte Problem bei der Arbeit mit Drupal 8 darin besteht, dass ich nicht die Daten erhalten kann, die ich benötige. Drupal 8 möchte, dass ich öffentliche Methoden verwende, anstatt manuell durch ein Objekt zu bohren. Das Problem ist, ich kann keinen konsistenten Weg finden, um eine Liste der verfügbaren Methoden zu erhalten! (Sie existieren auf magische Weise und ich habe das Gefühl, ich sollte nur etwas über sie wissen.) =

Angenommen, ich habe einen Inhaltstyp mit einem Videofeld. Ich muss die unformatierte URL der Videodatei in diesem Feld abrufen.

Also würde ich mit einer Knoten-ID ($ nid) beginnen und irgendwie muss ich herausfinden, wie der Knoten geladen wird. Das ist nicht schlecht, denn es gibt viele Beispiele. Also mache ich so etwas $node = \Drupal\node\Entity\Node::load($nid);.

So weit, ist es gut. Dann muss ich den Wert meines Videofeldes (field_main_video) abrufen. Ich brauchte für immer, um das herauszufinden, weil es im Internet widersprüchliche Dokumentationen gibt. Schließlich habe ich herausgefunden, dass ich so etwas tun muss (weil es ein mehrwertiger Gegenstand ist):

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

... dann Schleife durch das Array usw. Die Verwendung von kint hat mir auch nicht geholfen, dies zu finden. Wenn ich zum Beispiel kint($node)unter Methoden nachschaue, sehe ich dort getValue () nicht als Element. Immer noch nicht schrecklich, denn es gab genug Beispiele, um es herauszufinden.

Als ich jedoch tiefer ging, wusste ich nicht (dies ist der wichtige Teil), dass ich nicht die Entitäts-ID des Videofelds abrufen, dann die Entität laden und dann das "uri" -Feld in der Entität usw. finden sollte (wie z Ich würde in D7): Es gab eine Methode, mit der ich den URI alle in derselben Codezeile erhalten kann!

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

Aber wie hätte ich wissen können, dass getFileUri () existiert? Ich bin zufällig in einem Blog-Beitrag darauf gestoßen. Dies macht es wirklich einfacher, eine URI zu erhalten als in D7 ... aber nur, wenn Sie (auf magische Weise) wissen, welche Methoden für jede 'Ebene' eines Objekts existieren.

Am Ende frage ich mit diesem Beispiel: Wie finden Sie alle öffentlichen Methoden für jede Ebene eines Objekts auf eine Weise, die leicht zu lesen und zu verstehen ist? Beachten Sie, dass es anscheinend eine drupal-zentrierte (dh Entwicklungsmodul) Methode geben sollte, um dies zu tun, anstatt api.drupal.org manuell zu durchsuchen oder etwas IDE-spezifisches zu verwenden?


1
Die offizielle Dokumentation finden Sie unter api.drupal.org. Sobald Sie die Klasse des Objekts verstanden haben, das Sie bearbeiten, erhalten Sie alle Methoden, einschließlich der geerbten.
Kiamlaluno

1
... aber anstatt alles auf api.drupal.org nachzuschlagen, gibt es doch eine Möglichkeit in php / devel, die verfügbaren Methoden auf Befehl auf den Bildschirm zu werfen?
Bobby

Antworten:


14

Inhalt Einheiten unterscheiden sich von den meisten anderen Dinge, dass sie oft nicht Methoden und geeignete Schnittstellen, zumindest nicht für konfigurierbare Felder aus .

Bei Inhaltsentitäten und Feldern sind öffentliche Methoden nicht das, was Sie tatsächlich wissen möchten, sondern das, was Sie über Felder und Eigenschaften wissen möchten. Und nur wenn Sie über eine Referenz wieder zu einer Entität gelangen, sind die Methoden von Bedeutung.

Für eine Übersicht verweise ich immer auf das großartige Entity API Cheat Sheet .

Inhaltsentitäten haben eine feste Struktur: Entität> Feld (FieldItemList)> FieldItem -> Eigenschaft. Eine Eigenschaft ist entweder skalar oder eine Referenz auf etwas anderes, z. B. eine andere Entität, ein Sprachobjekt, ein Datumsobjekt, ...

Für einige Beispiele einige nützliche Ausschnitte:

// 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();
}

Nett! Es wird ein bisschen dauern, bis es verdaut ist, aber ich neige dazu, dass dies die akzeptierte Antwort ist. Vielen Dank! Es beantwortet die Frage nicht genau, aber das liegt nur daran, dass meine Frage und mein Beispiel zwei verschiedene Dinge stellten. Vielen Dank!
Bobby

1
@Berdir, das ist eine großartige Liste von Beispielen, die wirklich den Nagel treffen. Ich war nur bei Google nach Informationen, Informationen und nichts in der Nähe. Tolle Antwort, Buchmaterial.
Marko Blazekovic

4

Ich bin mir nicht sicher, ob dies Ihre Frage vollständig beantworten wird, aber was mir sehr hilft, ist die Verwendung der Diagrammfunktion in PhpStorm.

Zum Beispiel die Hierarchie zeigen Geben Sie hier die Bildbeschreibung ein

Sie haben die Möglichkeit, auch Methodennamen anzuzeigen

Geben Sie hier die Bildbeschreibung ein

Ich hoffe das hilft dir irgendwie.


Sie können eine Klasse auch mit Befehl + Klicken und dann mit Befehl + 7 öffnen oder auf die Registerkarte Struktur klicken, um die Klassenstruktur anzuzeigen (in der sich Ihre Projektverzeichnisansicht befinden würde), um dieselben Informationen schnell zu scannen, ohne UML zu öffnen.
Kevin

Ich verwende kein phpstorm, aber dies ist gut zu wissen, um später darauf zurückgreifen zu können. Ich suche nach einer Möglichkeit, dies mit devel oder etwas Drupal-zentriertem zu tun. muss doch irgendwo etwas eingebaut sein?
Bobby

Es tut mir leid, das zu sagen, aber ich glaube wirklich nicht, dass Sie im Moment effizient an der API basteln können, ohne diese IDE zu verwenden.
Oleg Videnov

NetBeans enthält auch einige PHP-Hierarchiediagramme. Wahrscheinlich nicht so cool, aber NetBeans ist freie Software (PHP Storm ist Closed Source und meiner Meinung nach teuer) und Sie können es kostenlos herunterladen.
Sanzante

Jede IDE, die ihr Salz wert ist, kann dies tun. BTW PHPStorm ist nicht teuer, wenn Sie das nutzen, was es zu bieten hat. Sie können die kostenlose EAP-Version verwenden. Wenn Sie an einem Open Source-Projekt (Drupal-Module oder -Themen) arbeiten, erhalten Sie von JetBrains eine kostenlose Lizenz. Keine Diskussion für hier.
Kevin

4

Nun, ich habe ziemlich oft die Kombination verwendet var_dump(get_class_methods($object)), um eine Liste der verfügbaren Methoden für die gegebene Klasse zu haben.

Ich suche auch ziemlich oft nach api.drupal.orgweiteren Details.


2
Dies scheint die Antwort zu sein, die am engsten mit dem zusammenhängt, wonach ich bisher gesucht habe. Vielen Dank!
Bobby

0

Du bist schon sehr nah.

Schauen wir uns zunächst die Definition der Methode an: https://api.drupal.org/api/drupal/core%21modules%21file%21src%21Entity%21File.php/function/File%3A%3AgetFileUri/8.2.x

Von hier aus können wir die Klasse sehen, zu der dies gehört, und es gibt einen Link dazu:

Class

File
Defines the file entity class.

Durch Klicken gelangen wir zu: https://api.drupal.org/api/drupal/core%21modules%21file%21src%21Entity%21File.php/class/File/8.2.x

In Ihrer IDE können Sie auch nach der \Drupal\file\Entity\FileKlasse suchen . Eine Möglichkeit, um sicherzustellen, dass dies die richtige Klasse ist, besteht darin, sich die Anmerkung anzusehen:

@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"
  }
) 

Beachten Sie das id- es ist file. Vermutlich könnten Sie sich beim Debuggen den Inhalt von field_main_video->entityansehen und diese ID irgendwo sehen. Dann suchen Sie einfach in Ihrer IDE danach. Normalerweise weiß man jedoch genug über die Entitätstypen, die man verwendet, um den Weg zur richtigen Klasse zu erraten (wonach man überprüfen kann, ob die Annotation die richtige ID enthält).

In diesem speziellen Fall weiß ich auch, dass Filees sich wahrscheinlich um eine erweiterte Klasse handelt ContentEntityBase, da sie eher dem Datenbankinhalt (einer Inhaltsentität) als der Konfiguration (einer Konfigurationsentität) ähnelt. Wenn ich sehe, dass sich meine Annahmen bestätigen, weiß ich, dass ich die richtige Klasse gefunden habe.

Kurz gesagt: Ihre IDE, strategische debug()Aussagen und einige Vermutungen sind die besten Möglichkeiten, um Drupal 8 zu entdecken.

PS-Änderungsdatensätze können ebenfalls hilfreich sein. Sie befinden sich unter https://www.drupal.org/list-changes/drupal


Ich gehe davon aus, dass das Problem des OP umgekehrt ist: zu wissen, welche öffentlichen Methoden eine Klasse implementiert / zur Verfügung hat.
Kiamlaluno

Ja, ich muss das vielleicht noch einmal lesen, aber ich glaube nicht, dass es das ist, wonach ich suche. Ich versuche herauszufinden, wie getFileUri () überhaupt existiert!
Bobby

@Bobby Eine Datei ist ein Entitätstyp. Schauen Sie sich also nur die Quelle an , in der Sie die Methode finden, nach der Sie aufgelistet und vollständig dokumentiert sind. Ist es nur so, dass Sie nicht wussten, dass eine Datei ein Entitätstyp ist? Oder dass Sie die Konvention zum Auffinden eines Entitätstyps im Code nicht kennen? Oder etwas anderes weiter oben in der Kette? Es gibt viele Abstraktionsebenen für alles in D8, es ist die Symfony-Methode, also gibt es eine Menge "Basis" -Wissen, die Sie zuerst benötigen, bevor Sie sich mit dem Code befassen
Clive

0

Sie können die PHP-Funktion get_class_methods verwenden. Im folgenden Beispiel wird eine Datei hochgeladen:

$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);

Dadurch werden alle für die Objektdatei $ verfügbaren Methoden zu Ihrem $ Methoden-Array hinzugefügt, das Sie drucken und dann alle verfügbaren Methoden anzeigen können. Dies gilt für alle Objekte in PHP, nicht nur für Drupal.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.