As importações em massa em PHP geralmente começam com um CSV enviado por um cliente, uma exportação de um fornecedor ou uma extração de um sistema legado. O risco surge quando elas são tratadas como uma simples leitura de arquivo seguida de inserções no banco de dados. Uma linha pode ter formato válido e, ainda assim, criar uma duplicata, descumprir uma regra de negócio, sobrescrever informações vigentes ou disparar um efeito externo duas vezes.
Uma importação deve ser projetada como um processo operacional com um ciclo definido: recebimento, análise, validação, pré-visualização, confirmação, execução, revisão e recuperação. Essa abordagem permite que o produto entenda o que será incorporado, que as operações intervenham diante de exceções e que a tecnologia limite o impacto de dados defeituosos.
Tratar a importação como um processo de negócio

O arquivo não é a fonte da verdade por si só: é uma solicitação para modificar o estado da aplicação. Por isso, convém criar uma entidade de importação com um identificador próprio, usuário ou sistema que a iniciou, data de recebimento, tipo de dados, versão do contrato, arquivo ou referência segura a ele, estado global e resumo dos resultados.
Os estados globais devem expressar uma situação operacional, não apenas um booleano. Por exemplo: recebido, analisado, aguardando confirmação, em processamento, concluído, concluído com ocorrências, interrompido ou cancelado. Uma importação com 9.800 linhas aceitas e 200 rejeitadas não é necessariamente um fracasso; pode ser uma execução concluída com ocorrências se as linhas rejeitadas estiverem isoladas e explicadas.
Também é necessário decidir quais consequências pertencem à carga. Criar um pedido, atualizar um catálogo ou cadastrar contatos pode exigir cálculos, auditoria ou notificações. Separar a persistência principal dos efeitos colaterais reduz o risco de que uma nova tentativa envie mensagens repetidas ou execute integrações de forma não controlada.
Definir um contrato de entrada antes de aceitar arquivos
O contrato de importação especifica o que se espera receber e como será interpretado. Deve incluir formato permitido, codificação, separador, cabeçalhos, tipos de dados, campos obrigatórios, formato de datas, regras de normalização, limites de tamanho e número máximo de linhas. Se forem aceitas planilhas, também é necessário definir a planilha relevante e como serão tratadas células vazias, fórmulas e valores convertidos automaticamente.
Os campos que conectam a origem ao destino merecem atenção especial. Um identificador externo estável, como o código do cliente no sistema de origem, é preferível ao uso do número da linha ou de um nome como referência. Deve ficar claro se esse identificador cria um registro, atualiza um existente ou se ambas as operações são permitidas.
Separar camadas de validação
A validação estrutural responde a perguntas mecânicas: o arquivo pode ser lido?, as colunas obrigatórias existem?, a data tem um formato aceito?, o valor é numérico?, a linha respeita o limite de comprimento? Essa camada deve detectar antecipadamente problemas que impedem a interpretação dos dados.
A validação de domínio aplica regras de negócio: um status pode não ser permitido, uma data de desligamento não pode preceder a data de admissão, uma porcentagem deve permanecer dentro de sua faixa ou uma combinação de campos pode ser incompatível. Por fim, as verificações contra os dados existentes validam referências, permissões, unicidade e transições permitidas. Por exemplo, que um código de fornecedor exista, que o usuário possa operar sobre aquela organização ou que um registro não esteja bloqueado.
Essa separação melhora as mensagens e o diagnóstico. Não é o mesmo informar uma coluna ausente, uma referência inexistente ou uma alteração não autorizada. Além disso, as regras de domínio devem ser reutilizadas pela aplicação e pelo importador para evitar que a carga se torne um atalho que contorne os controles normais.
Pré-visualizar alterações e confirmar uma intenção explícita
A pré-visualização não deve prometer uma execução exata se os dados puderem mudar entre a análise e a confirmação, mas deve oferecer uma estimativa verificável. Exiba o total de linhas lidas, linhas válidas, linhas com avisos, linhas rejeitadas, inclusões previstas, atualizações previstas e registros que não sofrerão alterações.
Os avisos servem para casos que exigem atenção, mas não invalidam automaticamente uma linha: por exemplo, um telefone normalizado, uma descrição truncada segundo uma regra conhecida ou um campo opcional vazio. Os avisos não devem ocultar rejeições. Cada resultado precisa de um código estável, uma mensagem compreensível e, quando for seguro, o valor recebido e o valor normalizado.
A confirmação deve estar associada a uma versão específica da análise. Se o usuário substituir o arquivo, corrigir linhas em uma interface ou alterar parâmetros relevantes, o sistema deverá invalidar a pré-visualização anterior e exigir uma nova análise. Assim, evita-se confirmar um resumo que já não representa a carga real.
Processar em lotes sem estados ambíguos
Processar todas as linhas em uma única transação parece seguro, mas pode manter bloqueios por tempo demais, exceder limites de execução ou transformar uma falha pontual em uma reversão onerosa. Processar uma linha por transação, por outro lado, pode gerar sobrecarga excessiva e dificultar a coordenação de operações relacionadas.
A unidade de trabalho deve ser escolhida conforme a dependência entre registros, o volume e o custo de reverter. Em muitos casos, um lote pequeno e delimitado permite confirmar alterações de forma progressiva. Cada lote deve registrar início, término, número de linhas tratadas e resultado. O worker deve poder ser retomado sem depender de uma sessão HTTP aberta: a carga é confirmada pela interface, mas sua execução ocorre como uma tarefa em segundo plano.
Evite manter arquivos completos na memória. Leia de forma sequencial, normalize cada linha e armazene uma representação de trabalho ou um resultado de validação quando necessário para auditar e retomar. Imponha limites de tamanho, linhas, tempo e concorrência. Um arquivo inesperadamente grande não deve bloquear os recursos que atendem ao trabalho diário.
para cada lote pendente:
marcar lote como em_processamento
para cada linha do lote:
aplicar validações pendentes
persistir ou enviar para quarentena
registrar resultado por linha
confirmar lote
marcar lote como concluídoSe um worker for interrompido, não basta executar novamente o lote às cegas. É necessário um mecanismo de bloqueio com expiração ou recuperação, e o estado por linha deve permitir distinguir o que está pendente do que já foi confirmado.
Isolar erros em quarentena e preservar evidências
A quarentena permite que as linhas inválidas não bloqueiem as corretas sem desaparecer do processo. Uma linha em quarentena deve preservar o número ou identificador de origem, os dados recebidos sob controles de acesso, os dados normalizados, se existirem, códigos de erro, momento da detecção e o estado da revisão.
Nem todos os erros recebem o mesmo tratamento. Um arquivo sem o cabeçalho obrigatório é um erro de arquivo e pode interromper a análise completa. Uma referência a um fornecedor inexistente pode ser uma rejeição de linha. Uma indisponibilidade temporária do banco de dados ou de uma integração é um erro técnico que pode ser repetido e não deve ser rotulado como defeito do dado.
A interface operacional deve permitir filtrar por motivo, exportar apenas as ocorrências autorizadas e compreender qual correção é esperada. Corrigir dentro da aplicação pode ser útil para poucos casos; para muitos registros, geralmente é mais controlável baixar as ocorrências, corrigi-las na origem e enviar uma nova carga. Em ambos os casos, mantenha o histórico: modificar uma linha em quarentena não deve apagar o valor original nem o motivo inicial.
Garantir idempotência e evitar duplicatas
A idempotência significa que repetir uma operação com a mesma intenção não altera o resultado mais de uma vez. Ela é essencial porque novas tentativas ocorrem: ocorre um timeout, um processo é reiniciado ou um operador confirma novamente diante de uma resposta incerta.
Uma chave de idempotência pode ser construída a partir do tipo de importação, da organização de destino e de um identificador externo estável. Ela deve ser respaldada por restrições de unicidade no banco de dados quando o modelo permitir; verificar primeiro e depois inserir não elimina as condições de corrida entre workers concorrentes.
Para atualizações, defina uma política explícita: substituir campos, aplicar apenas valores não vazios, rejeitar conflitos ou exigir uma versão esperada do registro. A última opção ajuda a detectar que um usuário alterou o dado após a pré-visualização. Não use uma impressão digital do arquivo como único mecanismo: um mesmo conteúdo pode representar uma intenção diferente e um arquivo corrigido pode manter muitas linhas já processadas.
Rastreabilidade, novas tentativas e recuperação seletiva

O resultado por linha é a peça central para suporte e recuperação. Registre um estado como pendente, processada, rejeitada, em quarentena, nova tentativa pendente ou ignorada; o identificador externo; o lote; códigos de motivo; timestamps; e uma referência ao registro criado ou atualizado. Proteja dados pessoais e segredos: a rastreabilidade deve ser suficiente para investigar, não uma cópia indiscriminada de informações sensíveis em logs.
As novas tentativas devem ser seletivas. Repita automaticamente erros técnicos transitórios com limites e espera progressiva; não repita indefinidamente uma regra de domínio descumprida. Quando uma referência ausente ou um dado inválido for corrigido, reprocesse apenas as linhas correspondentes em quarentena. Quando um lote falhar, continue a partir das linhas pendentes e use as já processadas como evidência de progresso.
Antes de colocar o fluxo em produção, teste arquivos vazios, cabeçalhos alterados, codificações inesperadas, duplicatas dentro do mesmo arquivo, duplicatas contra o banco de dados, interrupções entre lotes, retomadas e permissões insuficientes. As importações em massa em PHP são confiáveis quando seu comportamento diante de falhas é projetado com a mesma precisão que seu caminho correto.



