Como encontro métodos públicos disponíveis?

9

Estou descobrindo que o maior problema ao trabalhar com o Drupal 8 é que não consigo obter os dados necessários. O Drupal 8 quer que eu use métodos públicos em vez de detalhar manualmente um objeto. O problema é que não consigo descobrir uma maneira consistente de obter uma lista dos métodos disponíveis! (eles existem magicamente, e eu sinto que devo saber sobre eles). =

Neste exemplo, digamos que eu tenha um tipo de conteúdo com um campo de vídeo. Preciso obter o URL bruto do arquivo de vídeo nesse campo.

Então, eu começaria com uma identificação de nó ($ nid) e, de alguma forma, tenho que descobrir como carregar o nó. Isso não é tão ruim, porque há muitos exemplos. Então eu faço algo parecido $node = \Drupal\node\Entity\Node::load($nid);.

Por enquanto, tudo bem. Preciso obter o valor do meu campo de vídeo (field_main_video). Isso sempre me levou a descobrir, porque há documentação conflitante em torno da rede. Finalmente, descobri que teria que fazer algo assim (porque é um item de vários valores):

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

... então percorrer o array etc. Usar o kint também não me ajudou a encontrar isso. Porque, por exemplo, se eu kint($node)olhar em métodos, não vejo getValue () como um item lá. Ainda não é terrível, porque havia exemplos suficientes para descobrir isso.

À medida que vou mais fundo, porém, o que eu não sabia (essa é a parte importante) era que, em vez de obter o ID da entidade do campo de vídeo, carregar a entidade e encontrar o campo "uri" na entidade, etc. (como Gostaria em D7): Havia um método que me permite obter o URI nessa mesma linha de código!

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

Mas como eu poderia saber que esse getFileUri () existia? Por acaso tropeçou em um post do blog. Isso realmente facilita a obtenção de um URI do que no D7 ... mas apenas se você souber (magicamente) quais métodos existem para cada 'nível' de um objeto.

No final, com este exemplo, pergunto: Como você encontra todos os métodos públicos para cada nível de um objeto de uma maneira fácil de ler e entender? Observe que parece que deve haver uma maneira centrada em drupal (isto é, módulo devel) de fazê-lo, em vez de pesquisar manualmente api.drupal.org ou usar algo específico do IDE?

Bobby
fonte
1
A documentação oficial está em api.drupal.org. Depois de entender a classe do objeto que você está manipulando, você obtém todos os métodos, incluindo os herdados.
Kiamlaluno
1
... mas ao invés de procurar tudo no api.drupal.org, certamente existe uma maneira no php / devel de despejar os métodos disponíveis na tela sob comando?
Bobby

Respostas:

14

As entidades de conteúdo são diferentes da maioria das outras coisas, pois geralmente não possuem métodos e interfaces adequadas, pelo menos não para campos configuráveis.

No caso de entidades e campos de conteúdo, métodos públicos não são realmente o que você realmente deseja saber, o que você deseja é saber sobre campos e propriedades. E somente quando você chega a uma entidade novamente através de uma referência, os métodos são importantes.

Para uma visão geral, sempre me refiro à excelente Folha de Dicas da API de Entidades .

As entidades de conteúdo têm uma estrutura fixa, Entidade> Campo (FieldItemList)> FieldItem -> Propriedade. Uma propriedade é escalar ou uma referência a outra coisa, por exemplo, outra entidade, um objeto de linguagem, um objeto de data, ...

Para alguns exemplos especificados, alguns trechos úteis:

// 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
fonte
Agradável! Isso vai demorar um pouco para digerir, mas estou inclinado a ser a resposta aceita. Obrigado! Ele não responde exatamente à pergunta, mas é apenas porque minha pergunta e meu exemplo estavam pedindo duas coisas diferentes. Obrigado!
Bobby
1
@ Berdir, esta é uma lista impressionante de exemplos, acertando as unhas. Eu era apenas google para algumas informações, qualquer informação e nada nem perto disso. Ótima resposta, material do livro.
Marko Blazekovic 11/11/19
4

Não tenho certeza se isso responderá completamente à sua pergunta, mas o que me ajuda muito é usar o recurso de diagramas no PhpStorm.

Por exemplo, mostrando a hierarquia insira a descrição da imagem aqui

Você tem opções para mostrar também nomes de métodos

insira a descrição da imagem aqui

Espero que isso ajude você de certa forma.

Oleg Videnov
fonte
Você também pode abrir uma classe com o comando + clique, depois o comando + 7 ou clique na guia Estrutura para ver a estrutura da classe (onde seria a exibição do diretório do projeto) para verificar rapidamente as mesmas informações sem abrir a UML.
Kevin
Eu não uso o phpstorm, mas é bom saber para referência futura. Estou procurando uma maneira de fazer isso usando o devel ou algo centrado no drupal. certamente algo deve ser construído em algum lugar?
Bobby
Lamento dizer isso, mas realmente não acho que, neste momento, você possa mexer com a API de forma eficiente sem usar esse IDE.
Oleg Videnov
O NetBeans também inclui alguns diagramas de hierarquia PHP. Provavelmente não é tão legal, mas o NetBeans é um software livre (o PHP Storm é de código fechado e o IMHO caro) e você pode baixá-lo gratuitamente.
sanzante
Qualquer IDE que se preze pode fazer isso. O PHPStorm não é caro se você utilizar o que ele tem a oferecer. Você pode usar a versão gratuita do EAP e, se trabalhar em um projeto de código aberto (módulos ou temas do Drupal), o JetBrains concederá uma licença gratuita. Não é uma discussão por aqui embora.
22417 Kevin
4

Bem, eu me vi usando muitas vezes a combinação de var_dump(get_class_methods($object))ter uma lista de métodos disponíveis para a classe em questão.

Também procuro com frequência para api.drupal.orgobter mais detalhes.

yvan
fonte
2
Essa parece ser a resposta mais intimamente relacionada ao que eu estava procurando até agora. Obrigado!
Bobby
0

Você já está muito perto.

Primeiro, vejamos a definição do método: https://api.drupal.org/api/drupal/core%21modules%21file%21src%21Entity%21File.php/function/File%3A%3AgetFileUri/8.2.x

A partir daqui, podemos ver a classe da qual faz parte e há um link para ela:

Class

File
Defines the file entity class.

Clicar nesse link nos leva a: https://api.drupal.org/api/drupal/core%21modules%21file%21src%21Entity%21File.php/class/File/8.2.x

No seu IDE, você também pode procurar a \Drupal\file\Entity\Fileclasse. Uma maneira de garantir que essa é a classe correta é observar a anotação:

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

Observe o id- é file. Presumivelmente, se estiver depurando, você pode ver o conteúdo field_main_video->entitye ver esse ID em algum lugar. Depois, basta procurá-lo no seu IDE. Normalmente, porém, se sabe o suficiente sobre os tipos de entidade que você está usando para adivinhar o caminho para a classe correta (após o qual se pode verificar se a anotação contém o ID correto).

Nesse caso em particular, também sei que provavelmenteFile é uma classe que se estende , pois é mais parecida com o conteúdo do banco de dados (uma entidade de conteúdo) do que com a configuração (uma entidade de configuração). Então, quando vejo minhas suposições confirmadas, isso me ajuda a saber que encontrei a classe certa.ContentEntityBase

Então, resumindo: seu IDE, debug()declarações estratégicas e algumas suposições são as melhores maneiras de descobrir o Drupal 8.

Os registros PS Change também podem ser úteis. Eles estão em https://www.drupal.org/list-changes/drupal

wizonesolutions
fonte
Entendo que o problema do OP é o inverso: saber quais métodos públicos uma classe implementa / tem disponível.
Kiamlaluno
Sim, talvez eu precise ler isso de novo, mas acho que não é o que estou procurando. Eu estou tentando descobrir como getFileUri () existe mesmo em primeiro lugar!
21417 Bobby
@Bobby Um arquivo é um tipo de entidade; portanto, basta olhar para a fonte , onde você encontrará o método que está listado e totalmente documentado. Só que você não sabia que um arquivo é um tipo de entidade? Ou que você não conhece a convenção para localizar um tipo de entidade no código? Ou algo mais adiante na cadeia? Há muitas camadas de abstração para tudo na D8, é o caminho symfony, por isso há uma grande quantidade de conhecimentos "base" Você precisa primeiro Antes de entrar no código
Clive
0

Você pode usar a função get_class_methods do PHP. O exemplo abaixo utiliza um upload de arquivo:

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

Isso adicionará todos os métodos disponíveis ao arquivo $ do objeto na sua matriz $ methods, que você pode imprimir e ver todos os métodos disponíveis. Isso é válido para qualquer objeto no PHP, não apenas para o Drupal.

Cristian Cordeiro
fonte