Versão do Drupal: 7.21
Versão do módulo de coleta de campos: 7.x-1.0-beta5
Breve explicação : estou ocupado tentando importar coleções de campos de forma programática, mas ao excluir algumas delas sempre há alguma coleção de campos "falsas".
Explicação longa : meus usuários têm um campo de coleção de campos em seu perfil. Esta coleção de campos contém 3 campos de texto. Quero importar dados de um banco de dados sql personalizado para a coleção de campos do usuário. Essa coleção de campos pode ter vários valores. Quando importo os dados pela primeira vez, tudo funciona bem, vejo os dados nos campos da coleção de campos. Ótimo.
Mas aqui vem a parte complicada. Digamos que eu importe para um usuário específico 5 linhas do banco de dados personalizado. Eles são adicionados à coleção de campos, portanto, essa coleção de campos possui 5 itens, cada um contendo 3 campos. Em seguida, excluo algumas linhas do meu banco de dados personalizado para que eu tenha apenas 3 linhas restantes para este usuário. Eu executo a importação novamente, atualizando os 3 primeiros itens da coleção de campos, mas resta 2 itens da importação anterior. Eles devem ser excluídos porque tenho apenas 3 linhas importadas, mas ainda 5 itens de coleção de campos.
Tentei excluir esses itens da coleção de campos, mas sempre há um ou mais itens. Os campos estão vazios quando olho para o perfil do usuário, mas ainda há algo lá. Digamos que neste momento eu adiciono 5 novas linhas para o usuário no meu banco de dados personalizado, portanto, tenho 8 linhas no total para esse usuário. Então eu executo a importação novamente. Os três primeiros itens são atualizados, mas quando tento adicionar a quarta linha, ele ainda recebe um ID de entidade do 4º item da coleção de campos, tenta atualizá-lo, mas falha e retorna esse erro:
Fatal error: Call to undefined method stdClass::save()
Tentei excluir os itens da coleção de campos com cada um destes métodos abaixo:
// 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();
Este é o meu código completo:
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();
}
}
}
}
Portanto, minha pergunta é: como faço para excluir itens da coleção de campos para que eles não sejam mais usados?
entity_delete_multiple
é 100% definitivamente o caminho certo para fazê-lo - ter um olhar para afield_collection_field_delete
função, que é o que coleção de campo em si usa para limpar itens quando o campo referenciado é removidoentity_delete_multiple()
. Talvez seja necessário executar cron um par de vezes depois que você campos de exclusão (dados de campo são purgados em uma programação de modo a não sobrecarregar um único carregamento da página com tudo o que o processamento de fazer)Respostas:
Encontrei um caso de uso semelhante em que queria mapear alguns dados em uma coleção de campos durante hook_feeds_presave (), pois a estrutura de origem era muito complexa para Feeds. Descobri que entity_delete_multiple () removeu os itens da coleção de campos, mas quando editei o nó, ainda havia um monte de coleção de campos vazios lá. Desativar e excluir fez o truque, que encontrei aqui: https://drupal.stackexchange.com/a/31820/2762
Se a fonte dos feeds mudou, excluo todos os itens da coleção de campos e recrio. Espero que isso seja útil.
fonte
node_save($node)
seu nó.node_save($node)
,DrupalEntityController
vai fazer este trabalhoA melhor maneira de fazer isso agora é ligar
$field_collection->delete()
e isso vai lidar com tudo.fonte
As respostas acima não são a melhor maneira, com todos os outros itens desaparecidos da coleção de campos, e a outra maneira
->delete()
gera um erro no módulo Entidade.Maneira correta. Bem, o que eu fiz foi isso:
No meu caso, eu queria excluir o último item da coleção de campos
veja este código (para iniciantes: "lembre-se de que você deve ter a entidade $ já carregada")
Isso é tudo! o outro lado é
A maneira acima é boa usando a
entity_metadata_wrapper
função, mas dessa forma existe um bug complexo que eu não sei como resolvê-lo, você pode verificá-lo em https://drupal.org/node/1880312 e depois aplicar o patch no # 9 Para obter a próxima edição, verifique aqui https://drupal.org/node/2186689 esse bug também ocorre se você usar a->delete()
função.Espero que ajude alguém.
fonte
usando o vbo para excluir os itens da coleção de campos. ele removerá automaticamente a relação de campo com a entidade host do item de coleção de campos.
fonte
Eu tive um problema semelhante, onde estou importando dados de um feed para um item do FC. Quando uma atualização para uma entidade host é feita a partir do feed, e eu estou importando essas alterações, eu queria garantir que todos os itens FC existentes que não existem mais da fonte do feed fossem removidos.
Minha solução:
E é isso. Hook_field_update (
field_collection_field_update
) da Field Collection se encarregará de realmente excluir quaisquer itens de FC existentes que tenham sido referenciados.A única desvantagem disso é que, se não houver alterações nos dados do FC, eles serão excluídos e recriados de qualquer maneira. Mas isso não é grande coisa para mim.
fonte