Acceso a valores de tipos de campo desconocidos cuando se usa entity_metadata_wrapper

12

He estado buscando usar las clases Entity Metadata Wrapper (definidas por el módulo de entidad en Drupal 7) para acceder a los valores de campo, ya que parece ser una forma limpia de hacerlo.

Sin embargo, hay un par de cosas que hacen que esto sea un poco incómodo. Supongamos que tengo un contenedor para un tipo de contenido que define un campo denominado field_somethingcomo tal:

$wrapper = entity_metadata_wrapper('node', node_load($nid));
$value = $wrapper->field_something->value();

El primer problema que tengo es que no tengo forma de saber de antemano si lo que obtengo es un valor real (una cadena, una entidad, etc.), otro contenedor de estructura de metadatos (cuando los campos tienen múltiples valores) o una matriz (cuando los campos tienen múltiples propiedades).

He encontrado una manera de responder esas preguntas usando el info()método:

$info = $wrapper->field_something->info();
$is_multi_value = (strpos($info['type'], 'list<') === 0);
$has_multiple_properties = isset($info['property info']]);

Sin embargo, eso no es práctico. Siempre que quiera usar un campo sin saber de antemano su definición, debo tener en cuenta varios casos. Esto hace que mi código sea bastante pesado.

Para lidiar con esto, he escrito un código que:

  1. Asegura que siempre nos devuelva una matriz, incluso si es un campo de valor único;
  2. Cuando hay varias propiedades, devuelve el valor de la primera columna.

El punto 1. aquí siempre funcionará, a menos que la persona que llama quiera saber si este era un campo de valor único o no. El punto 2 funciona en algunos casos, no en todos, pero es conveniente cuando corresponde.

Aquí está el 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;
}

Entonces mi pregunta es: ¿hay formas más simples / mejores de abordar este problema de obtener valores del envoltorio de metadatos cuando no se conoce el tipo de campo?

Alice Heaton
fuente

Respuestas:

4

Aquí hay algunas sugerencias para hacer este proceso un poco más fácil.

$wrapper->field_something->type();

devolverá el tipo del campo, es decir node, taxonomy_term, integer, textetc. A continuación, podría manejar el valor devuelto por $wrapper->field_something->value()correctamente.

también

$wrapper->field_something->raw()

devolverá el valor bruto del campo. Que será un arrayen el caso de campos de valores múltiples de solo el valor. Por ejemplo, un entity_referenceserá el nid(o ID de entidad) de la entidad referenciada, o un arrayID de entidad referenciada.

thepearson
fuente
¡Vaya, entré en eso demasiado rápido! Quería agregar: $ wrapper-> field_something-> type () devuelve la misma información que el elemento 'type' de la matriz devuelta por $ wrapper-> field_something-> info (). De manera crucial, aún devuelve una cadena "list <type>" para tipos de valores múltiples, por lo que todavía necesito un strpos (o equivalente) para resolver que tiene varios valores (si quiero resolverlo antes de buscarlo).
Alice Heaton
En cuanto al segundo punto: de hecho, puedo determinar si es de valor múltiple probando el retorno de -> raw () o de -> value (), sin embargo, prefiero saber antes de obtener el valor, como si fuera de valor múltiple. Quiero ejecutarlo a través de un bucle foreach con -> getIterator () en lugar de ir manualmente a través de la matriz, lo que requiere que vuelva a crear un contenedor para cada elemento.
Alice Heaton
3

Entonces, como nadie ha encontrado otra solución, responderé mi propia pregunta:

No hay una forma más sencilla de acceder a valores de tipos de campo desconocidos cuando se utilizan contenedores de metadatos de entidad.

Existen métodos alternativos al que describí inicialmente (por ejemplo, los señalados por @thepearson). En particular, este método es útil:

 entity_property_list_extract_type($type)

Devolverá el tipo listado si su tipo es una lista (por ejemplo, 'entero' si su tipo es 'lista <integer>'), o falso si su tipo no es una lista. Internamente hace un strpos al igual que el código que publiqué inicialmente, pero supongo que es más una prueba futura.

La conclusión es que:

  • Los envoltorios de metadatos de entidad funcionan bien si no tiene idea de sus tipos de campo y desea abordar cuidadosamente cada caso posible;

  • Los envoltorios de metadatos de entidad funcionan bien si sabe exactamente qué tipos son sus campos y desea utilizarlos;

  • Si solo tiene algunas ideas de cómo son sus tipos de campo (por ejemplo, todo el texto, pero no sabe si están formateados o no, y no sabe si son de valor único o múltiple), entonces los contenedores de metadatos de Entity no proporcione ningún atajo y necesita escribir el suyo como lo hice en la pregunta inicial.

Alice Heaton
fuente
1

Para la verificación de campo único / múltiple, he encontrado útil probar el tipo de objeto contenedor, que será EntityListWrapperpara un campo de valores múltiples y EntityValueWrapperpara un campo de valor único:

<?php
...
$wrapper = entity_metadata_wrapper('user', $account);
// Get address, or first address if a multi-value field instance.
if (get_class($wrapper->field_address) == 'EntityListWrapper') {
  $value = $wrapper->field_address[0]->value();
}
else {
  $value = $wrapper->field_address->value();
}
Fonante
fuente
O inclusoif($wrapper->field_name instanceof EntityListWrapper) {...}
rudolfbyker