Malheureusement il est moins souple a manipuler et filter qu'une base SQL, Mysql propose nativement le stockage en CSV, et quelques astuces pour pouvoir en manipuler un directement, mais qui nécessite un accès complet au serveur puisqu'il faut directement agir sur le dossier /data.
Ici on va voir une méthode un peu plus passe partout et rapide grâce a SQLite, qui propose d'ouvrir une base en mémoire avec :memory: (et si la base est trop grosse rien n'empêche de créer un fichier temporaire .db).
On va donc utiliser 2 classe : PDO et SplFileObject, donc PHP 5 , SQLite étant compiler par défaut avec PDO pas de soucis a se niveau la (même chez free).
- PDO aura l'avantage de la requête preparé (qui existe aussi sous Sqlite3), et commence à être connu de tous.
- SplFileObject fait partie de la lib SPL, parcourir du CSV sera donc beaucoup rapide (et plus simple)
Pour le CSV (test.csv) :
Jean|Machin|Paris
Jean|Truc|Nice
Paul|Bla|Nice
Pour le code :try
{
$dbh = new PDO('sqlite::memory:');
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
}
catch(PDOException $e)
{
exit($e->getMessage());
}
$file = new SplFileObject('test.csv');
$file->setFlags(SplFileObject::READ_CSV | SplFileObject::SKIP_EMPTY);
$file->setCsvControl('|');
$dbh->exec("CREATE TABLE test (lastname, firstname, city)");
$stmt = $dbh->prepare("INSERT INTO test VALUES (?, ?, ?)");
foreach($file as $row)
{
$stmt->execute($row);
}
$query = $dbh->query("SELECT * FROM test ORDER BY firstname");
echo '<table>';
while($row = $query->fetch(PDO::FETCH_ASSOC))
{
echo '<tr><td>' . implode('</td><td>', $row) . '</td></tr>';
}
echo '</table>';
les 3 parties différentes :
la connexion : ici pas de mystères, c'est du PDO classique, avec un DSN SQLite, la base étant :memory:, elle sera donc effacer a la fin du script
try
{
$dbh = new PDO("sqlite::memory:");
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
}
catch(PDOException $e)
{
exit($e->getMessage());
}
l'import : - On crée un SplFileObject avec un flag CSV pour lu dire que c'est du CSV, et le flag SKIP_EMPTY pour omettre les lignes vierges (souvent a la fin) , avec setCsvControl on lui passe son séparateur, ici c'est le |
- On crée la table manuellement
- On crée notre requête préparer pour les INSERT
- On boucle sur l'iterator, chaque $row étant l'array de la ligne CSV
$file = new SplFileObject('test.csv');
$file->setFlags(SplFileObject::READ_CSV | SplFileObject::SKIP_EMPTY);
$file->setCsvControl('|');
$dbh->query("CREATE TABLE test (lastname, firstname, city)");
$stmt = $dbh->prepare("INSERT INTO test VALUES (?, ?, ?)");
foreach($file as $row)
{
$stmt->execute($row);
}
la manipulation : la base étant créee et les données importées, à vous de faire ce que bon vous semble $query = $dbh->query("SELECT * FROM test ORDER BY firstname");
echo '<table>';
while($row = $query->fetch(PDO::FETCH_ASSOC))
{
echo '<tr><td>' . implode('</td><td>', $row) . '</td></tr>';
}
echo '</table>';
Astuce : si le CSV a une taille assez conséquente, ou que vous devez économisé de la RAM, on peux mettre la base dans un fichier temporaire php qui sera effacer a la fin du script$temp = tmpfile();
$info = stream_get_meta_data($temp);
try
{
$dbh = new PDO("sqlite:{$info['uri']}");
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
}
catch(PDOException $e)
{
exit($e->getMessage());
}