Importazione dati in PHP, occhio al formato UTF8

Importazione dati in PHP, occhio al formato UTF8

Ogni volta che devo migrare dati da un database ad un altro mi trovo di fronte a problemi sempre diversi. In questa occasione mi sono ritrovato a dover usare un tool scritto in PHP per importare dei dati tra due database MySQL ma che mi ha dato alcuni grattacapi.

In particolare la procedura era suddivisa in più passaggi:

  1. Per prima cosa ho dovuto prima esportare i dati dal database di partenza in più file CSV.
  2. Poi li ho dovuti convertire in formato ODS perché dovevano essere riveduti e corretti "manualmente".
  3. Dopodiché li ho ri-convertiti in CSV.
  4. Infine, con il tool in PHP sopracitato, ho importato i CSV nel database di destinazione.

Sembrava funzionare tutto alla grande ma ad un certo punto, nel passaggio finale dell'importazione, ho riscontrato degli errori. Ovviamente i log generati dal programma di importazione erano inutili e quindi mi sono dovuto rimboccare le maniche.

Con una procedura molto semplice ho isolato i record che restituivano gli errori e li ho analizzati. A prima vista non ho riscontrato problemi. Ho "debuggato" un po' il processo di importazione e ancora nulla. Chiaramente c'era qualcosa nei dati che non andava, ma cosa?

Ho quindi pazientemente provato ad eseguire delle mini importazioni suddividendo i dati in piccole parti finché sono riuscito a stabilire che dei campi di testo impedivano l'importazione. La causa erano alcuni caratteri multibyte in formato UTF-8. Però queste stringhe, a rigor di logica, non avrebbero dovuto bloccare così il processo di importazione dati.

A questo punto ho avuto il sospetto che le funzioni di importazione stessero combinando qualcosa di sbagliato.

Così ho analizzato il codice sorgente e finalmente ho trovato la causa del problema: ad un certo punto veniva usata la funzione PHP mb_strlen() al posto di strlen(). Entrambe restituiscono il numero di caratteri che compongono una stringa, ma la prima tiene conto dei caratteri multibyte. Questo significa che mb_strlen() indica il numero esatto di caratteri indipendentemente dal numero di byte usati per rappresentarli invece strlen() assume che i caratteri siano sempre in ASCII. Ciò causava delle incongruenze tra degli indici usati per la scansione del file CSV e di conseguenza il record non veniva importato. Dopo aver corretto questo errore l'importazione è stata completata con successo.

Insomma, quando si lavora con le stringhe bisogna sempre tener conto anche di questi dettagli: non si possono usare queste funzioni a caso.