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


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

Ницца! Это займет немного, чтобы переварить, но я склоняюсь к тому, чтобы быть принятым ответом. Спасибо! Это не совсем отвечает на вопрос, но это только потому, что мой вопрос и мой пример как бы задали две разные вещи. Спасибо!
— Бобби

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


Я считаю, что проблема ОП в обратном: знать, какие публичные методы реализует / имеет класс.
— 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.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.