Estou estudando o uso das classes Entity Metadata Wrapper (definidas pelo módulo de entidade no Drupal 7) para acessar valores de campo, pois essa parece ser uma maneira limpa de fazer isso.
No entanto, existem algumas coisas que tornam isso um pouco estranho. Suponha que eu tenho um wrapper para um tipo de conteúdo que define um campo nomeado field_something
como tal:
$wrapper = entity_metadata_wrapper('node', node_load($nid));
$value = $wrapper->field_something->value();
O primeiro problema que tenho é que não tenho como saber de antemão se o que recebo é um valor real (uma string, uma entidade etc.), outro invólucro da estrutura de metadados (quando os campos têm vários valores) ou uma matriz (quando campos possuem várias propriedades).
Eu encontrei uma maneira de responder a essas perguntas usando o info()
método:
$info = $wrapper->field_something->info();
$is_multi_value = (strpos($info['type'], 'list<') === 0);
$has_multiple_properties = isset($info['property info']]);
No entanto, isso não é prático. Sempre que eu quiser usar um campo sem saber sua definição antes, devo levar em consideração vários casos. Isso torna meu código bastante pesado.
Para lidar com isso, escrevi um código que:
- Garante que sempre recebemos uma matriz de retorno, mesmo que seja um campo de valor único;
- Quando houver várias propriedades, retorne o valor da primeira coluna.
O ponto 1. aqui sempre funcionará, a menos que o chamador deseje saber se esse foi um campo de valor único ou não. O ponto 2 funciona em alguns casos, não em todos, mas é conveniente quando aplicável.
Aqui está o código:
function entity_metadata_simple_values($field) {
$fields = array();
$values = array();
$info = $field->info();
if (strpos($info['type'], 'list<') === 0) {
foreach ($field->getIterator() as $field_iteration) {
$fields[] = $field_iteration;
}
} else {
$fields[] = $field;
}
foreach ($fields as $final_field) {
$ff_info = $final_field->info();
if (isset($ff_info['property info'])) {
$column = reset(array_keys($ff_info['property info']));
$values[] = $final_field->{$column}->value();
} else {
$values[] = $final_field->value();
}
}
return $values;
}
Portanto, minha pergunta é: existem maneiras melhores / mais simples de resolver esse problema de obter valores do wrapper de metadados quando o tipo de campo não é conhecido?
Portanto, como ninguém encontrou outra solução, responderei minha própria pergunta:
Não há uma maneira mais simples de acessar valores de tipos de campos desconhecidos ao usar wrappers de metadados da entidade.
Existem métodos alternativos ao que eu descrevi inicialmente (por exemplo, os apontados por @thepearson). Em particular, este método é útil:
Ele retornará o tipo listado se o seu tipo for uma lista (por exemplo, 'integer' se o seu tipo for 'list <integer>') ou false se o seu tipo não for uma lista. Internamente, ele faz strops como o código que eu publiquei inicialmente, mas acho que é mais uma prova de futuro.
A conclusão é que:
Os wrappers de metadados da entidade funcionam bem se você não tem idéia dos seus tipos de campo e deseja abordar cuidadosamente cada caso possível;
Os wrappers de metadados da entidade funcionam bem se você sabe exatamente quais são os seus campos e deseja usá-los;
Se você tiver apenas algumas idéias de como são os seus tipos de campo (por exemplo, todo o texto, mas você não sabe se eles estão formatados ou não, e não sabe se são únicos ou com vários valores), os wrappers de metadados da entidade não forneça atalhos e você precisa escrever o seu próprio, como fiz na pergunta inicial.
fonte
Para a verificação de campo único / múltiplo, achei útil testar o tipo de objeto do invólucro, que será
EntityListWrapper
para um campo de valores múltiplos eEntityValueWrapper
para um campo de valor único:fonte
if($wrapper->field_name instanceof EntityListWrapper) {...}