Versión de Drupal: 7.21
Versión del módulo de colección de campo: 7.x-1.0-beta5
Breve explicación : estoy ocupado tratando de importar colecciones de campos mediante programación, pero al eliminar algunas de ellas siempre queda alguna colección de campo 'falsa'.
Explicación larga : Mis usuarios tienen un campo de colección de campos en su perfil. Esta colección de campos contiene 3 campos de texto. Quiero importar datos de una base de datos SQL personalizada a la colección de campo del usuario. Esta colección de campos puede tener múltiples valores. Cuando importo los datos por primera vez, todo funciona bien, veo los datos en los campos de la colección de campos. Excelente.
Pero aquí viene la parte difícil. Digamos que importo para un usuario específico 5 filas de la base de datos personalizada. Se agregan a la colección de campos, por lo que esta colección de campos tiene 5 elementos, cada uno con 3 campos. Luego elimino algunas filas de mi base de datos personalizada para que solo me queden 3 filas para este usuario. Ejecuto la importación nuevamente, actualizando los primeros 3 elementos de la colección de campos, pero luego me quedan 2 elementos de la importación anterior. Deben eliminarse porque solo tengo 3 filas importadas pero todavía 5 elementos de colección de campo.
Así que intenté eliminar estos elementos de la colección de campo, pero siempre quedan uno o más elementos. Los campos están vacíos cuando miro el perfil del usuario, pero todavía hay algo allí. Digamos que en este punto agrego 5 filas nuevas para el usuario en mi base de datos personalizada, por lo que tengo 8 filas en total para este usuario. Luego ejecuto la importación nuevamente. Los primeros 3 elementos se actualizan, pero luego, cuando intento agregar la cuarta fila, aún obtiene una identificación de entidad del cuarto elemento de la colección de campos, intenta actualizarlo pero falla y devuelve este error:
Fatal error: Call to undefined method stdClass::save()
Intenté eliminar los elementos de la colección de campos con cada uno de estos métodos a continuación:
// Method 1
entity_delete_multiple('field_collection_item', array($fc_id));
// Method 2
$field_collection_item = field_collection_item_load($fc_id);
$field_collection_item->delete();
// Method 3
$field_collection_item = field_collection_item_load($fc_id);
$field_collection_item->deleteRevision();
Este es mi código completo:
function import_user_field_collection(&$user, $old_user_id) {
// I do a query to get the rows I want to import for this specific user.
db_set_active('custom_sql_database');
$result = db_query("SELECT * FROM {users} WHERE user_id = :user_id", array(':user_id' => $old_user_id));
db_set_active('default');
$i = 0; // Keep count of how many rows I imported.
foreach($result as $row) {
// Check if the field collection item already exists.
if(!empty($user->field_profile_diploma_opleiding[LANGUAGE_NONE][$i]['value'])) {
// If it does exists, update this particular field collection item.
$fc_id = $user->field_profile_diploma_opleiding[LANGUAGE_NONE][$i]['value'];
$field_collection_item = entity_load('field_collection_item', array($fc_id));
// These 3 text fields are children of the field collection field.
$field_collection_item[$fc_id]->field_profile_diploma_instituut[LANGUAGE_NONE][0]['value'] = $row->instituut;
$field_collection_item[$fc_id]->field_profile_diploma_vakgebied[LANGUAGE_NONE][0]['value'] = $row->vakgebied;
$field_collection_item[$fc_id]->field_profile_diploma_jaar[LANGUAGE_NONE][0]['value'] = $row->jaar_diploma;
$field_collection_item[$fc_id]->save(TRUE);
} else {
// If the field collection item doesn't exist I want to create a new field collection item.
$field_collection_item = entity_create('field_collection_item', array('field_name' => 'field_profile_diploma_opleiding'));
$field_collection_item->setHostEntity('user', $user);
$field_collection_item->field_profile_diploma_instituut[LANGUAGE_NONE][0]['value'] = $row->instituut;
$field_collection_item->field_profile_diploma_vakgebied[LANGUAGE_NONE][0]['value'] = $row->vakgebied;
$field_collection_item->field_profile_diploma_jaar[LANGUAGE_NONE][0]['value'] = $row->jaar_diploma;
$field_collection_item->save(TRUE);
}
$i++;
}
$fc_fields = field_get_items('user', $user, 'field_profile_diploma_opleiding');
// Check if there are more field collection items than imported rows
if(count($fc_fields) > $i) {
for($i; $i <= count($fc_fields); $i++) {
// Run through each field collection item that's left from the previous import and delete it.
if(!empty($user->field_profile_diploma_opleiding[LANGUAGE_NONE][$i]['value'])) {
// Method 1
$fc_id = $user->field_profile_diploma_opleiding[LANGUAGE_NONE][$i]['value'];
entity_delete_multiple('field_collection_item', array($fc_id));
// Method 2
//$field_collection_item = field_collection_item_load($fc_id);
//$field_collection_item->delete();
// Method 3
//$field_collection_item = field_collection_item_load($fc_id);
//$field_collection_item->deleteRevision();
}
}
}
}
Entonces mi pregunta es: ¿cómo elimino los elementos de la colección de campo para que realmente se hayan ido?
entity_delete_multiple
es 100% definitivamente la forma correcta de hacerlo: eche un vistazo a lafield_collection_field_delete
función, que es lo que Field Collection usa para limpiar los elementos cuando se elimina el campo de referenciaentity_delete_multiple()
. Es posible que deba ejecutar cron un par de veces después de eliminar campos (los datos de campo se depuran en un horario para no cargar una sola carga de página con todo ese procesamiento que hacer)Respuestas:
Me encontré con un caso de uso similar en el que quería asignar algunos datos a una colección de campos durante hook_feeds_presave () ya que la estructura de origen era demasiado compleja para los feeds. Descubrí que entity_delete_multiple () eliminó los elementos de la colección de campos, pero cuando edité el nodo, todavía había un montón de colección de campos vacía allí. Desarmar y eliminar hizo el truco, que encontré aquí: https://drupal.stackexchange.com/a/31820/2762
Si la fuente de los feeds ha cambiado, elimino todos los elementos de la colección de campos y vuelvo a crearlos. Espero que esto sea útil.
fuente
node_save($node)
tu nodo.node_save($node)
,DrupalEntityController
va a hacer este trabajoLa mejor manera de hacer esto ahora es llamar
$field_collection->delete()
y eso se encargará de todo.fuente
Las respuestas anteriores no son la mejor manera, ya que todos los demás elementos desaparecieron de la colección de campo y, por otro lado,
->delete()
arroja un error con el módulo Entidad.Forma correcta. Bueno, lo que hice fue esto:
En mi caso, quería eliminar el último elemento de la colección de campo.
eche un vistazo a este código (para principiantes: "recuerde que debe tener la entidad $ cargada")
¡eso es todo! la otra forma es
La forma anterior es buena usando la
entity_metadata_wrapper
función, pero de esa manera hay un error complejo que no sé cómo resolverlo, puede verificarlo en https://drupal.org/node/1880312 y luego aplicar el parche en el # 9 obtienes el siguiente problema, compruébalo aquí https://drupal.org/node/2186689 este error también es si usas la->delete()
función.Espero que ayude a alguien.
fuente
usando vbo para eliminar los elementos de la colección de campos. eliminará automáticamente la relación de campo con la entidad anfitriona del elemento de colección de campos.
fuente
Tuve un problema similar, donde estoy importando datos de un feed a un elemento FC. Cuando se realiza una actualización a una entidad de host desde el feed, y estoy importando esos cambios, quería asegurarme de que se eliminaran todos los elementos FC existentes que ya no existen desde el origen del feed.
Mi solución:
Y eso es. Hook_field_update (
field_collection_field_update
) de Field Collection se encargará de eliminar realmente cualquier elemento FC existente que haya sido desreferenciado .El único inconveniente de esto es que si no hubo cambios en los datos de FC, se eliminan y se vuelven a crear de todos modos. Pero eso no es gran cosa para mí.
fuente