Как мне найти доступные публичные методы?

9

Я обнаружил, что самая большая проблема в работе с Drupal 8 - я не могу получить нужные мне данные. Drupal 8 хочет, чтобы я использовал публичные методы, а не сверлял вручную объект. Проблема в том, что я не могу найти последовательный способ получения списка доступных методов! (они волшебным образом существуют, и я чувствую, что должен знать о них).

Для этого примера, скажем, у меня есть тип контента с полем видео. Мне нужно получить необработанный URL-адрес видеофайла в этом поле.

Поэтому я бы начал с идентификатора узла ($ nid), и каким-то образом я должен выяснить, как загрузить узел. Это не так уж плохо, потому что есть много примеров. Так что я делаю что-то вроде $node = \Drupal\node\Entity\Node::load($nid);.

Все идет нормально. Затем мне нужно получить значение моего видео поля (field_main_video). Я НАВСЕГДА понял, потому что в сети есть противоречивая документация. Наконец, я понял, что мне нужно сделать что-то вроде этого (потому что это многозначный элемент):

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

... затем цикл по массиву и т. д. Использование kint также не помогло мне найти это. Потому что, например, если я kint($node)и смотрю под методами, я не вижу getValue () как элемент там. Все еще не ужасно, потому что было достаточно примеров, чтобы понять это.

Однако когда я углубляюсь, то, чего я не знал (это важная часть), было то, что вместо того, чтобы получать идентификатор сущности поля видео, затем загружать сущность, затем находить поле «uri» в сущности и т. Д. (Например, Я бы в D7): был метод, который позволяет мне получить URI все в той же строке кода!

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

Но как я мог знать, что этот getFileUri () существует? Я случайно наткнулся на это в сообщении в блоге. Это действительно делает получение URI легче, чем в D7 ... но только если вы знаете (волшебным образом), какие методы существуют для каждого «уровня» объекта.

В конце этого примера я спрашиваю: как найти все общедоступные методы для каждого уровня объекта так, чтобы их было легко читать и понимать? Заметьте, что, похоже, должен быть друпалцентричный (т.е. модуль devel) способ сделать это, а не искать вручную api.drupal.org или использовать что-то специфичное для IDE?

Бобби
источник
1
Официальная документация находится на api.drupal.org. Как только вы понимаете класс объекта, с которым вы работаете, вы получаете все методы, включая унаследованные.
kiamlaluno
1
... но вместо того, чтобы искать все на api.drupal.org, наверняка в php / devel есть способ вывести доступные методы на экран по команде?
Бобби

Ответы:

14

Контентные сущности отличаются от большинства других тем, что они часто не имеют методов и надлежащих интерфейсов, по крайней мере, для настраиваемых полей.

В случае сущностей и полей контента публичные методы - это не совсем то, что вы на самом деле хотите знать, а то, что вы хотите знать о полях и свойствах. И только когда вы снова обращаетесь к сущности через ссылку, методы имеют значение.

Для обзора, я всегда обращаюсь к великому Шпаргалке Entity API .

Объекты содержимого имеют фиксированную структуру: Entity> Field (FieldItemList)> FieldItem -> Property. Свойство является либо скалярным, либо ссылкой на что-то другое, например, на другую сущность, объект языка, объект даты, ...

Для нескольких указанных примеров, несколько полезных фрагментов:

// 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
источник
Ницца! Это займет немного, чтобы переварить, но я склоняюсь к тому, чтобы быть принятым ответом. Спасибо! Это не совсем отвечает на вопрос, но это только потому, что мой вопрос и мой пример как бы задали две разные вещи. Спасибо!
Бобби
1
@Berdir, это потрясающий список примеров, которые действительно бьют по гвоздю. Я был просто Google для некоторой информации, любой информации и ничего даже близко к этому. Отличный ответ, книжный материал.
Марко
4

Не уверен, что это полностью ответит на ваш вопрос, но мне очень помогает использование диаграмм в PhpStorm.

Например, показывая иерархию введите описание изображения здесь

У вас есть варианты, чтобы показать также имена методов

введите описание изображения здесь

Я надеюсь, что это поможет вам.

Олег Виденов
источник
Вы также можете открыть класс командой + клик, затем команда + 7 или щелкнуть вкладку Структура, чтобы увидеть структуру класса (где будет вид вашего каталога проекта), чтобы быстро просмотреть ту же информацию, не открывая UML.
Кевин
Я не использую phpstorm, но это полезно знать для дальнейшего использования. Я ищу способ сделать это, используя devel или что-то друпоцентрическое. наверняка что-то должно быть встроено где-то?
Бобби
Мне жаль это говорить, но я действительно не думаю, что в данный момент вы можете эффективно работать с API, не используя эту IDE.
Олег Виденов
NetBeans также включает в себя некоторые диаграммы иерархии PHP. Возможно, это не так круто, но NetBeans - это бесплатное программное обеспечение (PHP Storm с закрытым исходным кодом и имхо дорого), и вы можете скачать его бесплатно.
sanzante
Это может сделать любой IDE, достойный их соли. Кстати, PHPStorm не дорогой, если вы используете то, что он может предложить. Вы можете использовать бесплатную версию EAP, и если вы работаете над проектом с открытым исходным кодом (модули или темы Drupal), JetBrains предоставит вам бесплатную лицензию. Не обсуждение здесь, хотя.
Кевин
4

Ну, я часто использовал комбинацию, var_dump(get_class_methods($object))чтобы получить список доступных методов для данного класса.

Я также часто заглядываю в api.drupal.orgподробности.

Айван
источник
2
Это похоже на ответ, наиболее тесно связанный с тем, что я искал до сих пор. Спасибо!
Бобби
0

Ты уже очень близко.

Во-первых, давайте посмотрим на определение метода: https://api.drupal.org/api/drupal/core%21modules%21file%21src%21Entity%21File.php/function/File%3A%3AgetFileUri/8.2.x

Отсюда мы можем увидеть класс, частью которого он является, и на него есть ссылка:

Class

File
Defines the file entity class.

Нажатие приводит нас к: https://api.drupal.org/api/drupal/core%21modules%21file%21src%21Entity%21File.php/class/File/8.2.x

В вашей IDE вы также можете искать \Drupal\file\Entity\Fileкласс. Один из способов убедиться, что это правильный класс, - взглянуть на аннотацию:

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

Обратите внимание id- это так file. Предположительно, при отладке вы можете посмотреть содержимое field_main_video->entityи где-нибудь увидеть этот идентификатор. Тогда вы просто ищете его в вашей IDE. Обычно, однако, достаточно известно о типах сущностей, которые он использует, чтобы угадать свой путь к нужному классу (после чего можно проверить, что аннотация содержит правильный идентификатор).

В этом конкретном случае я также знаю, что Fileэто, вероятно, класс, который расширяется ContentEntityBase, поскольку он больше похож на контент базы данных (сущность контента), чем на конфигурацию (сущность конфигурации). Поэтому, когда я вижу, что мои предположения подтверждаются, это помогает мне узнать, что я нашел правильный класс.

Итак, вкратце: ваша IDE, стратегические debug()заявления и некоторые догадки - лучшие способы открыть Drupal 8.

PS Изменение записей также может быть полезным. Они находятся по адресу https://www.drupal.org/list-changes/drupal

wizonesolutions
источник
Я считаю, что проблема ОП в обратном: знать, какие публичные методы реализует / имеет класс.
kiamlaluno
Да, возможно, мне придется прочитать это снова, но я не думаю, что это то, что я ищу. Я пытаюсь понять, как getFileUri () вообще существует!
Бобби
@Bobby Файл - это тип сущности, поэтому вы просто смотрите на его источник , где вы найдете метод, который вы после перечислили и полностью документировали. Это просто, что вы не знали, что файл является типом сущности? Или что вы не знаете соглашения для определения типа объекта в коде? Или что-то еще дальше по цепочке? В D8 есть много уровней абстракции для всего, это путь symfony, поэтому вам нужно сначала получить много «базовых» знаний, прежде чем углубляться в код
Clive
0

Вы можете использовать функцию PHP get_class_methods. В приведенном ниже примере пользователи загружают файл:

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

Это добавит все методы, доступные для объекта $ file, в ваш массив $ Methods, который вы можете распечатать, а затем увидеть все доступные методы. Это действительно для любых объектов в PHP, не только для Drupal.

Кристиан Кордейро
источник