Comment trouver les méthodes publiques disponibles?

9

Je trouve que le plus gros problème avec Drupal 8 est que je ne peux pas obtenir les données dont j'ai besoin. Drupal 8 veut que j'utilise des méthodes publiques plutôt que d'explorer manuellement un objet. Le problème est que je n'arrive pas à trouver un moyen cohérent d'obtenir une liste des méthodes disponibles! (ils existent comme par magie, et j'ai l'impression que je suis juste censé les connaître). =

Pour cet exemple, disons que j'ai un type de contenu avec un champ vidéo. J'ai besoin d'obtenir l'URL brute du fichier vidéo dans ce champ.

Je commencerais donc par un identifiant de nœud ($ nid), et je dois en quelque sorte trouver comment charger le nœud. Ce n'est pas trop mal car il y a beaucoup d'exemples. Donc je fais quelque chose comme $node = \Drupal\node\Entity\Node::load($nid);.

Jusqu'ici tout va bien. Ensuite, j'ai besoin d'obtenir la valeur de mon champ vidéo (field_main_video). Cela m'a pris POUR TOUJOURS à comprendre parce qu'il y a une documentation conflictuelle autour du net. Enfin, j'ai compris que je devrais faire quelque chose comme ça (car c'est un élément à plusieurs valeurs):

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

... puis boucle à travers le tableau, etc. L'utilisation de kint ne m'a pas non plus aidé à trouver cela. Parce que, par exemple, si je kint($node)regarde sous les méthodes, je ne vois pas getValue () comme un élément là-bas. Toujours pas terrible, car il y avait suffisamment d'exemples pour le comprendre.

En approfondissant, cependant, ce que je ne savais pas (c'est la partie importante), c'est que plutôt que d'obtenir l'ID d'entité du champ vidéo, puis de charger l'entité, puis de trouver le champ "uri" dans l'entité, etc. (comme Je le ferais en D7): Il y avait une méthode qui me permet d'obtenir l'URI tout dans cette même ligne de code!

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

Mais comment aurais-je pu savoir que cette getFileUri () existait? Il m'est arrivé de tomber dessus dans un article de blog. Cela rend vraiment l'obtention d'un URI plus facile qu'en D7 ... mais seulement si vous savez (comme par magie) quelles méthodes existent pour chaque «niveau» d'un objet.

En fin de compte, avec cet exemple, je demande: Comment trouvez-vous toutes les méthodes publiques pour chaque niveau d'un objet d'une manière facile à lire et à comprendre? Notez qu'il semble qu'il devrait y avoir une méthode centrée sur Drupal (c'est-à-dire un module de développement) plutôt que de rechercher manuellement api.drupal.org ou d'utiliser quelque chose d'IDE spécifique?

Policier
la source
1
La documentation officielle se trouve sur api.drupal.org. Une fois que vous comprenez la classe de l'objet que vous manipulez, vous obtenez toutes les méthodes, y compris celles héritées.
kiamlaluno
1
... mais plutôt que de tout chercher sur api.drupal.org, il y a sûrement un moyen dans php / devel de vider les méthodes disponibles sur l'écran sur commande?
Bobby

Réponses:

14

Les entités de contenu sont différentes de la plupart des autres choses en ce qu'elles n'ont souvent pas de méthodes et d'interfaces appropriées, du moins pas pour les champs configurables.

Dans le cas d'entités de contenu et de champs, les méthodes publiques ne sont pas vraiment ce que vous voulez réellement savoir, ce que vous voulez, c'est connaître les champs et les propriétés. Et ce n'est que lorsque vous accédez à nouveau à une entité via une référence que les méthodes sont importantes.

Pour un aperçu, je me réfère toujours à la grande feuille de triche de l'API d'entité .

Les entités de contenu ont une structure fixe, Entité> Champ (FieldItemList)> FieldItem -> Propriété. Une propriété est soit scalaire, soit une référence à autre chose, par exemple une autre entité, un objet langage, un objet date, ...

Pour quelques exemples spécifiés, quelques extraits utiles:

// 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
la source
Agréable! Cela va prendre un peu de temps à digérer, mais je penche pour que ce soit la réponse acceptée. Merci! Cela ne répond pas exactement à la question mais c'est seulement parce que ma question et mon exemple demandaient en quelque sorte 2 choses différentes. Je vous remercie!
Bobby
1
@Berdir, voici une liste d'exemples impressionnants, vraiment percutants. J'étais juste google pour quelques informations, toutes les informations et rien même proche de cela. Grande réponse, matériel de livre.
Marko Blazekovic
4

Je ne sais pas si cela répondra complètement à votre question, mais ce qui m'aide beaucoup, c'est d'utiliser la fonction de diagrammes dans PhpStorm.

Par exemple, montrant la hiérarchie entrez la description de l'image ici

Vous avez des options pour afficher également les noms des méthodes

entrez la description de l'image ici

J'espère que cela vous aide en quelque sorte.

Oleg Videnov
la source
Vous pouvez également ouvrir une classe avec commande + clic, puis commande + 7 ou cliquez sur l'onglet Structure pour voir la structure de la classe (où serait la vue du répertoire de votre projet) pour analyser rapidement les mêmes informations sans ouvrir UML.
Kevin
Je n'utilise pas phpstorm, mais c'est bon à savoir pour référence future. Je cherche un moyen de le faire en utilisant devel ou quelque chose de centré sur drupal. sûrement quelque chose doit être construit quelque part?
Bobby
Je suis désolé de le dire, mais je ne pense vraiment pas qu'en ce moment vous puissiez bricoler efficacement l'API sans utiliser cet IDE.
Oleg Videnov
NetBeans inclut également certains diagrammes de hiérarchie PHP. Probablement pas si cool, mais NetBeans est un logiciel libre (PHP Storm est une source fermée et à mon humble avis) et vous pouvez le télécharger gratuitement.
sanzante
Tout IDE digne de ce nom peut le faire. BTW PHPStorm n'est pas cher si vous utilisez ce qu'il a à offrir. Vous pouvez utiliser la version gratuite d'EAP, et si vous travaillez sur un projet open source (modules ou thèmes Drupal), JetBrains vous DONNERA une licence gratuite. Pas une discussion ici cependant.
Kevin
4

Eh bien, je me suis retrouvé à utiliser assez souvent la combinaison de var_dump(get_class_methods($object))pour avoir une liste des méthodes disponibles pour la classe donnée.

Je cherche aussi assez souvent api.drupal.orgpour plus de détails.

yvan
la source
2
Cela semble être la réponse la plus proche de ce que je cherchais jusqu'à présent. Merci!
Bobby
0

Tu es déjà très proche.

Tout d'abord, regardons la définition de la méthode: https://api.drupal.org/api/drupal/core%21modules%21file%21src%21Entity%21File.php/function/File%3A%3AgetFileUri/8.2.x

De là, nous pouvons voir la classe dont il fait partie, et il y a un lien vers celle-ci:

Class

File
Defines the file entity class.

Cliquer dessus nous amène à: https://api.drupal.org/api/drupal/core%21modules%21file%21src%21Entity%21File.php/class/File/8.2.x

Dans votre IDE, vous pouvez également rechercher la \Drupal\file\Entity\Fileclasse. Une façon d'être sûr que c'est la bonne classe est de regarder l'annotation:

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

Remarquez le id- c'est file. Vraisemblablement, si vous déboguez, vous pourriez regarder le contenu de field_main_video->entityet vous verriez cet ID quelque part. Il vous suffit ensuite de le rechercher dans votre IDE. Habituellement, cependant, on en sait assez sur les types d'entités que l'on utilise pour deviner son chemin vers la bonne classe (après quoi on pourrait vérifier que l'annotation contient l'ID correct).

Dans ce cas particulier, je sais également que Filec'est probablement une classe qui s'étend ContentEntityBase, car elle ressemble plus au contenu de la base de données (une entité de contenu) qu'à la configuration (une entité de configuration). Donc, quand je vois mes hypothèses se confirmer, cela m'aide à savoir que j'ai trouvé la bonne classe.

Donc, en bref: votre IDE, vos debug()déclarations stratégiques et certaines hypothèses sont les meilleurs moyens de découvrir Drupal 8.

Les enregistrements PS Change peuvent également être utiles. Ils sont sur https://www.drupal.org/list-changes/drupal

wizonesolutions
la source
Je suppose que le problème de l'OP est l'inverse: savoir quelles méthodes publiques une classe implémente / dispose.
kiamlaluno
Oui, je devrai peut-être relire ceci, mais je ne pense pas que ce soit ce que je recherche. J'essaie de comprendre comment getFileUri () existe même en premier lieu!
Bobby
@Bobby Un fichier est un type d'entité, il vous suffit donc de regarder sa source , où vous trouverez la méthode que vous recherchez et entièrement documentée. Est-ce juste que vous ne saviez pas qu'un fichier est un type d'entité? Ou que vous ne connaissez pas la convention pour localiser un type d'entité dans le code? Ou quelque chose d'autre plus haut dans la chaîne? Il existe de nombreuses couches d'abstraction pour tout dans D8, c'est la manière symfony, donc il y a beaucoup de connaissances "de base" dont vous avez besoin avant de plonger dans le code
Clive
0

Vous pouvez utiliser la fonction PHP get_class_methods. L'exemple ci-dessous utilise un téléchargement de fichier:

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

Cela ajoutera toutes les méthodes disponibles au fichier $ objet dans votre tableau $ methods, que vous pourrez imprimer et voir toutes les méthodes disponibles. Ceci est valable pour tous les objets en PHP, pas seulement Drupal.

Cristian Cordeiro
la source