Как мне найти доступные общедоступные методы?
Я нахожу, что самая большая проблема в работе с 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($node)
и посмотрю в разделе методы, я не увижу там GetValue() в качестве элемента. Все еще не страшно, потому что вокруг было достаточно примеров, чтобы понять это.
Однако по мере того, как я углубляюсь, я не знал (это важная часть), что вместо того, чтобы получать идентификатор сущности поля видео, затем загружать сущность, затем находить поле "uri" в сущности и т.Д (как я сделал бы в D7): Был метод, который позволяет мне получить URI в одной и той же строке кода!
$url = \Drupal\node\Entity\Node::load($nid)->field_main_video->entity->getFileUri();
Но как я мог знать, что этот getFileUri() существует? Я случайно наткнулся на это в своем блоге. Это действительно облегчает получение URI, чем в D7... но только если вы знаете (волшебным образом), какие методы существуют для каждого "уровня" объекта.
В конце концов, в этом примере я спрашиваю: Как вы находите все общедоступные методы для каждого уровня возражать так, чтобы было легко читать и понимать? Обратите внимание, что, похоже, должен быть ориентированный на drupal (т.Е. модуль разработки) способ сделать это, а не искать вручную api.drupal.org или использовать что-то специфичное для IDE?
5 answers
Сущности контента отличаются от большинства других вещей тем, что они часто не имеют методы и надлежащие интерфейсы, по крайней мере, не для настраиваемых полей.
В случае сущностей и полей содержимого общедоступные методы - это не то, что вы на самом деле хотите знать, а то, что вы хотите знать о полях и свойствах. И только когда вы снова попадаете в сущность через ссылку, тогда методы имеют значение.
Для общего обзора я всегда ссылаюсь на великую сущность Шпаргалка по API.
Сущности содержимого имеют фиксированную структуру, Сущность > Поле (список полей) > Элемент поля -> Свойство. Свойство является либо скалярным, либо ссылкой на что-то другое, например, на другую сущность, объект языка, объект даты,...
Для нескольких определенных примеров, некоторые полезные фрагменты:
// 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();
}
Ну, я обнаружил, что довольно часто использую комбинацию var_dump(get_class_methods($object))
, чтобы иметь список доступных методов для данного класса.
Я также довольно часто заглядываю в api.drupal.org
для получения более подробной информации.
Вы уже очень близки.
Во-первых, давайте рассмотрим определение метода: 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
и где-нибудь увидеть этот идентификатор. Затем вы просто ищете его в своей среде разработки. Обычно, однако, человек знает достаточно о типы сущностей, которые используются для определения пути к нужному классу (после чего можно проверить, что аннотация содержит правильный идентификатор).
В данном конкретном случае я также знаю, что File
является , вероятно, классом, который расширяет ContentEntityBase
, поскольку он больше похож на содержимое базы данных (сущность содержимого), чем на конфигурацию (сущность конфигурации). Поэтому, когда я вижу, что мои предположения подтверждаются, это помогает мне понять, что я нашел правильный класс.
Итак, короче говоря: ваша IDE, стратегическая debug()
утверждения и некоторые догадки - лучшие способы открыть для себя Drupal 8.
P.S. Записи изменений также могут быть полезны. Они находятся в https://www.drupal.org/list-changes/drupal
Вы можете использовать функцию 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);
Это добавит все методы, доступные для файла object$, в ваш массив $methods, который вы можете распечатать, а затем просмотреть все доступные методы. Это справедливо для любых объектов в PHP, а не только для Drupal.