Wersja Drupal: 7.21
Wersja modułu kolekcji terenowej: 7.x-1.0-beta5
Krótkie wyjaśnienie : jestem zajęty próbą programowego importowania zbiorów pól, ale podczas usuwania niektórych z nich zawsze pozostaje trochę „fałszywych” zbiorów pól.
Długie wyjaśnienie : Moi użytkownicy mają w swoim profilu pole zbioru pól. Ta kolekcja pól zawiera 3 pola tekstowe. Chcę zaimportować dane z niestandardowej bazy danych SQL do kolekcji użytkownika. Ta kolekcja pól może mieć wiele wartości. Kiedy importuję dane po raz pierwszy, wszystko działa dobrze, widzę dane w polach kolekcji pól. Świetny.
Ale nadchodzi trudna część. Załóżmy, że importuję dla jednego konkretnego użytkownika 5 wierszy z niestandardowej bazy danych. Są one dodawane do kolekcji pól, więc ta kolekcja pól zawiera 5 elementów, z których każdy zawiera 3 pola. Następnie usuwam niektóre wiersze z mojej niestandardowej bazy danych, aby dla tego użytkownika pozostały tylko 3 wiersze. Ponownie uruchamiam import, aktualizując pierwsze 3 elementy kolekcji pól, ale potem pozostały mi 2 elementy z poprzedniego importu. Powinny zostać usunięte, ponieważ mam tylko 3 zaimportowane wiersze, ale nadal 5 elementów kolekcji pól.
Próbowałem więc usunąć te elementy kolekcji pól, ale zawsze pozostaje jeden lub więcej elementów. Pola są puste, gdy patrzę na profil użytkownika, ale wciąż coś tam jest. Powiedzmy, że w tym momencie dodałem 5 nowych wierszy dla użytkownika w mojej niestandardowej bazie danych, więc mam łącznie 8 wierszy dla tego użytkownika. Następnie ponownie uruchamiam import. Pierwsze 3 elementy są aktualizowane, ale kiedy próbuję dodać czwarty wiersz, nadal otrzymuje identyfikator encji z 4. elementu kolekcji pola, próbuje go zaktualizować, ale kończy się niepowodzeniem i zwraca ten błąd:
Fatal error: Call to undefined method stdClass::save()
Próbowałem usunąć elementy kolekcji pól za pomocą każdej z poniższych metod:
// 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();
To jest mój pełny kod:
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();
}
}
}
}
Więc moje pytanie brzmi: jak usunąć elementy kolekcji pola, aby faktycznie zniknęły?
entity_delete_multiple()
. Może być konieczne uruchomienie crona kilka razy po usunięciu pól (dane pól są czyszczone zgodnie z harmonogramem, aby nie obciążać ładowania jednej strony całą obróbką do wykonania)
entity_delete_multiple
jest w 100% zdecydowanie właściwym sposobem na zrobienie tego - spójrz nafield_collection_field_delete
funkcję, której używa sama Field Collection do czyszczenia przedmiotów po usunięciu odnośnego pola