Drupal-Version: 7.21
Version des Feldsammlungsmoduls: 7.x-1.0-beta5
Kurze Erklärung : Ich bin damit beschäftigt, Feldsammlungen programmgesteuert zu importieren, aber beim Löschen einiger von ihnen bleibt immer eine gefälschte Feldsammlung übrig.
Lange Erklärung : Meine Benutzer haben ein Feldsammlungsfeld in ihrem Profil. Diese Feldsammlung enthält 3 Textfelder. Ich möchte Daten aus einer benutzerdefinierten SQL-Datenbank in die Feldsammlung des Benutzers importieren. Diese Feldsammlung kann mehrere Werte haben. Wenn ich die Daten zum ersten Mal importiere, funktioniert alles einwandfrei. Ich sehe die Daten in den Feldern der Feldsammlung. Toll.
Aber hier kommt der schwierige Teil. Angenommen, ich importiere für einen bestimmten Benutzer 5 Zeilen aus der benutzerdefinierten Datenbank. Sie werden der Feldsammlung hinzugefügt, sodass diese Feldsammlung 5 Elemente enthält, die jeweils 3 Felder enthalten. Dann lösche ich einige Zeilen aus meiner benutzerdefinierten Datenbank, sodass nur noch 3 Zeilen für diesen Benutzer übrig sind. Ich führe den Import erneut aus und aktualisiere die ersten 3 Elemente der Feldsammlung, aber dann bleiben mir 2 Elemente aus dem vorherigen Import übrig. Sie sollten gelöscht werden, da ich nur 3 importierte Zeilen, aber noch 5 Feldsammlungselemente habe.
Also habe ich versucht, diese Feldsammlungselemente zu löschen, aber es sind immer noch ein oder mehrere Elemente übrig. Die Felder sind leer, wenn ich mir das Benutzerprofil ansehe, aber da ist noch etwas. Angenommen, ich füge an dieser Stelle 5 neue Zeilen für den Benutzer in meine benutzerdefinierte Datenbank ein, sodass ich insgesamt 8 Zeilen für diesen Benutzer habe. Dann führe ich den Import erneut aus. Die ersten 3 Elemente werden aktualisiert, aber wenn ich versuche, die 4. Zeile hinzuzufügen, wird immer noch eine Entitäts-ID aus dem 4. Feldsammlungselement abgerufen, versucht, sie zu aktualisieren, schlägt jedoch fehl und gibt diesen Fehler zurück:
Fatal error: Call to undefined method stdClass::save()
Ich habe versucht, die Feldsammlungselemente mit jeder der folgenden Methoden zu löschen:
// 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();
Dies ist mein vollständiger Code:
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();
}
}
}
}
Meine Frage lautet also: Wie lösche ich Feldsammlungselemente, damit sie tatsächlich verschwunden sind?
entity_delete_multiple
ist definitiv 100% der richtige Weg, dies zu tun - werfen Sie einen Blick auf diefield_collection_field_delete
Funktion, mit der Field Collection selbst Elemente bereinigt, wenn das Feld, auf das verwiesen wird, entfernt wirdentity_delete_multiple()
. Möglicherweise müssen Sie cron ein paar Mal ausführen, nachdem Sie Felder gelöscht haben (Felddaten werden nach einem Zeitplan gelöscht, um das Laden einer einzelnen Seite nicht mit all dieser Verarbeitung zu belasten)Antworten:
Ich bin auf einen ähnlichen Anwendungsfall gestoßen, bei dem ich während hook_feeds_presave () einige Daten einer Feldsammlung zuordnen wollte, da die Quellstruktur für Feeds zu komplex war. Ich habe festgestellt, dass entity_delete_multiple () die Feldsammlungselemente entfernt hat, aber als ich den Knoten bearbeitet habe, gab es dort immer noch eine Menge leerer Feldsammlungen. Das Deaktivieren und Löschen hat den Trick ausgeführt, den ich hier gefunden habe: /drupal//a/31820/2762
Wenn sich die Feedquelle geändert hat, lösche ich alle Feldsammlungselemente und erstelle sie neu. Hoffe das ist hilfreich.
quelle
node_save($node)
Ihren Knoten.node_save($node)
,DrupalEntityController
werden diesen Job machenDer beste Weg, dies jetzt zu tun, ist ein Anruf
$field_collection->delete()
und das wird alles erledigen.quelle
Die obigen Antworten sind nicht der beste Weg, da alle anderen Elemente aus der Feldsammlung verschwunden sind und der andere Weg
->delete()
einen Fehler mit dem Entitätsmodul auslöst.Der richtige Weg. Nun, was ich getan habe, war Folgendes:
In meinem Fall wollte ich das letzte Element in der Feldsammlung löschen
Schauen Sie sich diesen Code an (für Anfänger: "Denken Sie daran, dass die Entität $ bereits geladen sein muss").
das ist alles! der andere Weg ist
Der obige Weg ist gut mit der
entity_metadata_wrapper
Funktion, aber auf diese Weise gibt es einen komplexen Fehler, den ich nicht lösen kann. Sie können ihn unter https://drupal.org/node/1880312 überprüfen und nach dem Anwenden des Patches in # 9 Wenn Sie das nächste Problem erhalten, überprüfen Sie es hier https://drupal.org/node/2186689 Dieser Fehler tritt auch auf, wenn Sie die->delete()
Funktion verwenden.Hoffe es hilft jemandem.
quelle
Verwenden von vbo zum Löschen der Feldsammlungselemente. Die Feldbeziehung zur Host-Entität des Feldsammlungselements wird automatisch entfernt.
quelle
Ich hatte ein ähnliches Problem, bei dem ich Daten aus einem Feed in ein FC-Element importiere. Wenn aus dem Feed eine Aktualisierung einer Host-Entität vorgenommen wird und ich diese Änderungen importiere, wollte ich sicherstellen, dass alle vorhandenen FC-Elemente, die nicht mehr aus der Feed-Quelle vorhanden sind, entfernt wurden.
Meine Lösung:
Und das ist es. Hook_field_update (
field_collection_field_update
) von Field Collection sorgt dafür, dass alle vorhandenen FC-Elemente, auf die verwiesen wurde, tatsächlich gelöscht werden.Der einzige Nachteil dabei ist, dass die FC-Daten, wenn sie nicht geändert wurden, gelöscht und trotzdem neu erstellt werden. Aber das ist keine große Sache für mich.
quelle