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
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 polaentity_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)Odpowiedzi:
Natknąłem się na podobny przypadek użycia, w którym chciałem odwzorować niektóre dane na kolekcję pól podczas hook_feeds_presave (), ponieważ struktura źródła była zbyt złożona dla Feeds. Stwierdziłem, że podmiot_delete_multiple () usunął elementy kolekcji pól, ale kiedy edytowałem węzeł, wciąż było tam kilka pustych kolekcji pól. Rozbrojenie i usunięcie zrobiła sztuczka, którą znalazłem tutaj: https://drupal.stackexchange.com/a/31820/2762
Jeśli źródło kanałów uległo zmianie, usuwam wszystkie elementy kolekcji pól i ponownie tworzę. Mam nadzieję, że to jest pomocne.
źródło
node_save($node)
swoim węźle.node_save($node)
,DrupalEntityController
Najlepszym sposobem na zrobienie tego teraz jest połączenie telefoniczne
$field_collection->delete()
, które poradzi sobie ze wszystkim.źródło
Powyższe odpowiedzi nie są najlepszym sposobem, przy wyłączeniu wszystkie pozostałe przedmioty zniknęły z kolekcji pola, a na odwrót z
->delete()
błędem w module Entity.Właściwa droga. Cóż, zrobiłem to:
W moim przypadku chciałem usunąć ostatni element z kolekcji pól
zapoznaj się z tym kodem (dla początkujących: „pamiętaj, że musisz mieć już jednostkę $ załadowaną”)
to wszystko! na odwrót jest
Powyższy sposób jest dobry przy użyciu
entity_metadata_wrapper
funkcji, ale w ten sposób występuje złożony błąd, którego nie wiem, jak go rozwiązać, możesz go sprawdzić na https://drupal.org/node/1880312 i po zastosowaniu łatki w # 9 otrzymujesz następny problem, sprawdź go tutaj https://drupal.org/node/2186689 ten błąd występuje również, jeśli używasz->delete()
funkcji.Mam nadzieję, że to komuś pomoże.
źródło
używając vbo, aby usunąć elementy kolekcji pól. automatycznie usunie relację pola z jednostką hosta elementu zbioru pola.
źródło
Miałem podobny problem, gdy importuję dane z pliku danych do elementu FC. Gdy aktualizacja źródła jest tworzona z kanału, a ja importuję te zmiany, chciałem się upewnić, że wszelkie istniejące elementy FC, które już nie istnieją ze źródła kanału, zostały usunięte.
Moje rozwiązanie:
I to wszystko. Funkcja hook_field_update (
field_collection_field_update
) w Field Collection zajmie się faktycznym usunięciem wszelkich istniejących elementów FC, które zostały usunięte z odniesienia.Jedynym minusem jest to, że jeśli dane FC nie uległy zmianie, zostały one usunięte i utworzone ponownie. Ale to nie jest dla mnie wielka sprawa.
źródło