Версия Drupal: 7.21
Версия модуля сбора данных: 7.x-1.0-beta5
Краткое объяснение : Я занят попытками импортировать коллекции полей программно, но при удалении некоторых из них всегда остается какая-то «поддельная» коллекция полей.
Подробное объяснение : у моих пользователей есть поле для сбора полей в их профиле. Эта коллекция полей содержит 3 текстовых поля. Я хочу импортировать данные из пользовательской базы данных SQL в поле коллекции пользователя. Эта коллекция полей может иметь несколько значений. Когда я импортирую данные в первый раз, все работает нормально, я вижу данные в полях коллекции полей. Отлично.
Но здесь начинается сложная часть. Допустим, я импортирую для одного конкретного пользователя 5 строк из пользовательской базы данных. Они добавляются в коллекцию полей, поэтому эта коллекция полей содержит 5 элементов, каждый из которых содержит 3 поля. Затем я удаляю несколько строк из своей пользовательской базы данных, чтобы у меня осталось только 3 строки для этого пользователя. Я снова запускаю импорт, обновляя первые 3 элемента коллекции полей, но затем у меня остаются 2 элемента из предыдущего импорта. Их следует удалить, потому что у меня есть только 3 импортированные строки, но все еще 5 элементов коллекции полей.
Поэтому я попытался удалить эти элементы коллекции полей, но всегда остается один или несколько элементов. Когда я смотрю на профиль пользователя, поля пусты, но что-то там еще есть. Допустим, в этот момент я добавил 5 новых строк для пользователя в своей пользовательской базе данных, поэтому у меня есть 8 строк для этого пользователя. Затем я снова запускаю импорт. Первые 3 элемента обновляются, но затем, когда я пытаюсь добавить 4-ую строку, он все еще получает идентификатор объекта из 4-го элемента коллекции полей, пытается обновить его, но не удается и возвращает эту ошибку:
Fatal error: Call to undefined method stdClass::save()
Я попытался удалить элементы коллекции полей с помощью каждого из следующих методов:
// 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();
Это мой полный код:
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();
}
}
}
}
Итак, мой вопрос: как удалить элементы коллекции полей, чтобы они на самом деле исчезли?
entity_delete_multiple
на 100% определенно правильный способ сделать это - взгляните наfield_collection_field_delete
функцию, которая сама Field Collection использует для очистки элементов при удалении указанного поляentity_delete_multiple()
. Вам может потребоваться запустить cron пару раз после удаления полей (данные полей очищаются по расписанию, чтобы не загружать загрузку одной страницы всей этой обработкой)Ответы:
Я столкнулся с похожим случаем использования, когда я хотел отобразить некоторые данные в коллекцию полей во время hook_feeds_presave (), так как структура источника была слишком сложной для Feeds. Я обнаружил, что entity_delete_multiple () удалил элементы коллекции полей, но когда я отредактировал узел, там все еще была куча пустых коллекций полей. Удаление и удаление сделали свое дело, которое я нашел здесь: https://drupal.stackexchange.com/a/31820/2762
Если источник каналов изменился, я удаляю все элементы коллекции полей и воссоздаю. Надеюсь, это полезно.
источник
node_save($node)
свой узел.node_save($node)
,DrupalEntityController
будем делать эту работуЛучший способ сделать это сейчас - это позвонить,
$field_collection->delete()
и это все обработает.источник
Приведенные выше ответы не являются лучшим способом, при этом все остальные элементы, исчезнувшие из коллекции полей, были сброшены, а другой способ - с
->delete()
ошибкой в модуле Entity.Правильный путь. Хорошо, что я сделал, было это:
В моем случае я хотел удалить последний элемент в коллекции полей
взгляните на этот код (для начинающих: «помните, что у вас уже должна быть загружена $ entity»)
это все! другой способ
Описанный выше способ хорош при использовании
entity_metadata_wrapper
функции, но в этом случае есть сложная ошибка, которую я не знаю, как ее решить, вы можете проверить ее на https://drupal.org/node/1880312 и после применения патча в # 9 Вы получите следующую проблему, проверьте ее здесь https://drupal.org/node/2186689 Эта ошибка также, если вы используете->delete()
функцию.Надеюсь, это кому-нибудь поможет.
источник
использование vbo для удаления элементов коллекции полей. он автоматически удалит отношение поля с сущностью узла элемента коллекции полей.
источник
У меня была похожая проблема, когда я импортирую данные из канала в элемент FC. Когда из канала выполняется обновление сущности хоста, и я импортирую эти изменения, я хотел убедиться, что все существующие элементы FC, которых больше не существует из источника канала, были удалены.
Мое решение:
И это все. Метод hook_field_update (
field_collection_field_update
) Field Collection позаботится о фактическом удалении любых существующих элементов FC, на которые была дана обратная ссылка.Единственным недостатком является то, что если в данных FC не было никаких изменений, они все равно удаляются и воссоздаются. Но это не имеет большого значения для меня.
источник