Drupalバージョン:7.21
フィールドコレクションモジュールバージョン:7.x-1.0-beta5
簡単な説明:フィールドコレクションをプログラムでインポートするのに忙しいのですが、それらの一部を削除すると、常にいくつかの「偽の」フィールドコレクションが残っています。
長い説明:ユーザーのプロファイルにフィールドコレクションフィールドがあります。このフィールドコレクションには、3つのテキストフィールドが含まれています。カスタムSQLデータベースからユーザーのフィールドコレクションにデータをインポートしたい。このフィールドコレクションは複数の値を持つことができます。初めてデータをインポートすると、すべてが正常に機能し、フィールドコレクションのフィールドにデータが表示されます。すごい。
しかし、ここでトリッキーな部分があります。たとえば、特定のユーザーに対して、カスタムデータベースから5行をインポートするとします。それらはフィールドコレクションに追加されるため、このフィールドコレクションにはそれぞれ3つのフィールドを含む5つのアイテムがあります。次に、カスタムデータベースからいくつかの行を削除して、このユーザーの残りの行が3行だけになるようにします。インポートを再度実行して、フィールドコレクションの最初の3つのアイテムを更新しますが、前回のインポートの2つのアイテムが残ります。インポートされた行は3つだけですが、フィールドコレクションアイテムが5つあるため、削除する必要があります。
そのため、これらのフィールドコレクションアイテムを削除しようとしましたが、常に1つ以上のアイテムが残っています。ユーザープロファイルを見るとフィールドは空ですが、まだ何かがあります。この時点で、カスタムデータベースにユーザーの新しい行を5つ追加したとしましょう。このユーザーの行は合計で8行になります。次に、インポートを再度実行します。最初の3つのアイテムが更新されますが、4番目の行を追加しようとすると、4番目のフィールドコレクションアイテムからエンティティIDが取得され、更新が試行されますが失敗し、次のエラーが返されます。
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()
ます。フィールドを削除した後、数回cronを実行する必要がある場合があります(フィールドデータは、単一のページのロードで実行するすべての処理に負担をかけないように、スケジュールに基づいてパージされます)
entity_delete_multiple
100%間違いなく正しい方法です。field_collection_field_delete
参照されたフィールドが削除されたときにフィールドコレクション自体がアイテムをクリーンアップするために使用する関数を確認してください