Az egyik általam készített Drupal alapú webáruház termékeinek adminisztrálása CSV alapon működik. Ez annyit jelent, hogy van egy exportáló felület, ahol a site admin lementheti a termékeit egy csv fájlba, amit aztán valamilyen csv-t kezelő programban (általában Microsoft Excel) átszerkeszt, és egy importáló felületen feltölt. Ezután az oldal feldolgozza és érvénybe lépnek a változtatások.

Ez így mind szép és jó, csak egy gond van vele. A windows felhasználók nagy része, ISO-8859-2-es karakterkódolást használ, míg a Drupal UTF-8-at. Hogy a címek és egyéb karakterkódolástól függő érték problémáját kiküszöböljük, szükség van az mb_convert_encoding() fgv-re, amely segítségével az ISO-8859-2 karakterkódolású részeket, át tudjuk konvertálni a Drupal-nak is használható UTF-8-as karakterkódolásba.

Egyszercsak jelentkezett egy probléma. Azon kezdőbetűk amelyek ékezetesek egyszerűen elvesztek. Tehát például az “Öntapadó” szóból, “ntapadó” lett.
Elkezdtem debuggolni, és azt vettem észre, hogy a feldolgozásra használt beépített fgetcsv() PHP fgv. hibásan működik az ISO-8859-2-es karakterkódólásű fájlok feldolgozásában. A probléma az volt, hogy már a beolvasáskor elvesztek ez ékezetes kezdőbetűk, tehát még az átkonverálás előtt. Ha pedig már akkor elveszett, akkor utólag már nem lehet neki mit csinálni.

Úgyhogy az explode() fgv-t segítségül hívva írtam egy saját, egyszerűsített csv feldolgozó fgv-t, ami erre a célra pont alkalmas:

  1. <?php
  2. function fgetcsv_iso_8859_2($handle, $length, $separator) {
  3.  
  4.   if (!feof($handle)) {
  5.     return explode($separator, fgets($handle, $length));
  6.   } else {
  7.     return false;
  8.   }
  9.  
  10. }
  11. ?>

Persze ez így nem kezeli azon csv fájlokat, amikben mondjuk a mezők értékei ” (macskaköröm) között helyezkednek el, ám az én esetemben erre nem volt szükség. Ha mégis kellene, ki lehet egészíteni a fgv-t:

  1. <?php
  2. function fgetcsv_iso_8859_2($handle, $length, $separator) {
  3.   $enclosed = '"';
  4.   $out      = array();
  5.  
  6.   if (!feof($handle)) {
  7.     $fields = explode($separator, fgets($handle, $length));
  8.     foreach ($fields as $field_data) {
  9.       if (preg_match("/^\\$enclosed/i", $field_data)) {
  10.         $field_data = preg_replace("/(^\\$enclosed|\\$enclosed$)/i","", $field_data);
  11.       }
  12.       $out[] = $field_data;
  13.     }
  14.     return $out;
  15.   } else {
  16.     return false;
  17.   }
  18.  
  19. }
  20. ?>

Leave a Reply