Version Drupal: 7.21
Version du module de collecte sur le terrain: 7.x-1.0-beta5
Brève explication : Je suis en train d'essayer d'importer des collections de champs par programme, mais lors de la suppression de certaines d'entre elles, il reste toujours une collection de champs «fausse».
Explication longue : Mes utilisateurs ont un champ de collecte de champs sur leur profil. Cette collection de champs contient 3 champs de texte. Je souhaite importer des données d'une base de données SQL personnalisée dans la collection de champs de l'utilisateur. Cette collection de champs peut avoir plusieurs valeurs. Lorsque j'importe les données pour la première fois, tout fonctionne correctement, je vois les données dans les champs de la collection de champs. Génial.
Mais voici la partie délicate. Supposons que j'importe pour un utilisateur spécifique 5 lignes de la base de données personnalisée. Ils sont ajoutés à la collection de champs, donc cette collection de champs contient 5 éléments contenant chacun 3 champs. Ensuite, je supprime certaines lignes de ma base de données personnalisée afin qu'il ne me reste que 3 lignes pour cet utilisateur. J'exécute à nouveau l'importation, en mettant à jour les 3 premiers éléments de la collection de champs, mais je me retrouve avec 2 éléments de l'importation précédente. Ils doivent être supprimés car je n'ai que 3 lignes importées mais toujours 5 éléments de collection de champs.
J'ai donc essayé de supprimer ces éléments de collection de champs, mais il reste toujours un ou plusieurs éléments. Les champs sont vides quand je regarde le profil utilisateur mais il y a encore quelque chose. Disons qu'à ce stade, j'ajoute 5 nouvelles lignes pour l'utilisateur dans ma base de données personnalisée, donc j'ai 8 lignes au total pour cet utilisateur. Ensuite, je lance à nouveau l'importation. Les 3 premiers éléments sont mis à jour, mais lorsque j'essaie d'ajouter la 4e ligne, il obtient toujours un identifiant d'entité du 4e élément de collection de champs, essaie de le mettre à jour mais échoue et renvoie cette erreur:
Fatal error: Call to undefined method stdClass::save()
J'ai essayé de supprimer les éléments de collection de champs avec chacune de ces méthodes ci-dessous:
// 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();
Voici mon code complet:
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();
}
}
}
}
Ma question est donc la suivante: comment supprimer des éléments de collection de champs pour qu'ils soient réellement partis?
entity_delete_multiple
est 100% certainement la bonne façon de le faire - jetez un œil à lafield_collection_field_delete
fonction, qui est ce que Field Collection utilise lui-même pour nettoyer les éléments lorsque le champ référencé est suppriméentity_delete_multiple()
. Vous devrez peut-être exécuter cron plusieurs fois après avoir supprimé des champs (les données de champ sont purgées selon un calendrier afin de ne pas surcharger un seul chargement de page avec tout ce traitement à faire)Réponses:
J'ai rencontré un cas d'utilisation similaire où je voulais mapper certaines données dans une collection de champs pendant hook_feeds_presave () car la structure source était trop complexe pour Feeds. J'ai trouvé que entity_delete_multiple () supprimait les éléments de la collection de champs, mais lorsque j'ai modifié le nœud, il y avait encore un tas de collections de champs vides. La suppression et la suppression ont fait l'affaire, que j'ai trouvée ici: https://drupal.stackexchange.com/a/31820/2762
Si la source du flux a changé, je supprime tous les éléments de la collection de champs et recrée. J'espère que cela vous sera utile.
la source
node_save($node)
votre nœud.node_save($node)
,DrupalEntityController
fera ce travailLa meilleure façon de le faire maintenant est d'appeler
$field_collection->delete()
et de tout gérer.la source
Les réponses ci-dessus ne sont pas la meilleure façon, avec unset tous les autres éléments ont disparu de la collection de champs, et dans l'autre sens avec
->delete()
jette un bug avec le module Entity.Bonne façon. Eh bien, ce que j'ai fait, c'est ceci:
Dans mon cas, je voulais supprimer le dernier élément de la collection de champs
jetez un oeil à ce code, (pour les débutants: "rappelez-vous que vous devez avoir l'entité $ déjà chargée")
c'est tout! l'autre voie est
La façon ci-dessus est bonne en utilisant la
entity_metadata_wrapper
fonction mais avec cette façon il y a un bug complexe que je ne sais pas comment le résoudre, vous pouvez le vérifier sur https://drupal.org/node/1880312 et après avoir appliqué le patch dans # 9 vous obtenez le prochain problème, vérifiez-le ici https://drupal.org/node/2186689 ce bug est également si vous utilisez la->delete()
fonction.J'espère que cela aide quelqu'un.
la source
en utilisant vbo pour supprimer les éléments de la collection de champs. il supprimera automatiquement la relation de champ avec l'entité hôte d'élément de collection de champs.
la source
J'ai eu un problème similaire, où j'importe des données d'un flux dans un élément FC. Lorsqu'une mise à jour d'une entité hôte est effectuée à partir du flux et que j'importe ces modifications, je voulais m'assurer que tous les éléments FC existants qui n'existent plus dans la source du flux ont été supprimés.
Ma solution:
Et c'est tout. Le hook_field_update (
field_collection_field_update
) de Field Collection se chargera de supprimer réellement tous les éléments FC existants qui ont été dé-référencés.Le seul inconvénient est que s'il n'y a pas eu de changement dans les données FC, elles sont supprimées et recréées de toute façon. Mais ce n'est pas un gros problème pour moi.
la source