exporteren naar csv met PHP
Ignace Verschaeve op 02/11/2021 18:05:44:
Ik dacht altijd dat fora er waren om mensen te helpen, hoe dom ze ook zijn.
Ik heb niet gezegd dat je dom bent hoor. Dat zijn jouw eigen woorden haha ;-)
Alle gekheid op een stokje, ik heb nergens gezegd of gesuggereerd dat je dom zou zijn. Ik probeer je alleen wat handvatten te geven om meer resultaat te krijgen door middel van een heldere vraagstelling.
Het gaat erom dat je niet zomaar een code plaatst met de mededeling "er gaat iets mis". Als je een probleem hebt met je auto ga je ook niet naar de garage met de mededeling "er gaat iets mis", maar geef je op z'n minst aan WAT er misgaat. In jouw geval, wat lukt er niet? Waar loop je op vast?
Als iets niet werkt, kun je zelf eens proberen te debuggen. Dan kijk je of de code die je uitvoert het verwachte resultaat oplevert. Op die manier kun je vaststellen op welk punt er iets misgaat.
Ignace Verschaeve op 02/11/2021 18:05:44:
Maar niemand heeft er mij op gewezen dat ik mogelijks geen connectie hebt met mijn database.
We hebben dan ook geen glazen bol. Maar als ik je goed begrijp werkte de databaseconnectie niet? Is het probleem nu dan opgelost?
TS is sterk in het selectief oppikken van opmerkingen, maar nooit het geheel.
Ik gaf een aantal redenen waarom een aanroep van ->query() kan mislukken.
* missende database connectie
* syntaxfout in de query
* aanroep van niet bestaande tabellen in de database
dit zijn enkele mogelijkheden.
Maar een geheel mislukte verbinding zou eigenlijk al een foutmelding moeten geven over de aanroep van ->query() on a boolean, aangezien $conn dan ook geen object was.
Wel kan intussen de verbinding verloren gegaan zijn, of er is verbinding maar niet tot de tabel in de query (ja, het hebben van een verbinding betekent niet dat je toegang hebt tot alle tabellen / rechten hebt om een bepaalde actie uit te voeren op die tabel).
Ik zou, zoals ik al eerder aangaf de quotes in de query aanpassen.
Net zoals dat met de insertquery fout ging op 22 oktober:
https://www.phphulp.nl/php/forum/topic/foutmelding-bij-insert/104143/
Dit is mijn huidige foutmelding:
Quote:
rouwbriefnieuw03000There are 508 rows in my table. Fatal error: Uncaught TypeError: fputcsv(): Argument #2 ($fields) must be of type array, int given in /customers/1/5/0/fv-vl-ardennen.be/httpd.www/beheerder/export_naar_csv.php:38 Stack trace: #0 /customers/1/5/0/fv-vl-ardennen.be/httpd.www/beheerder/export_naar_csv.php(38): fputcsv(Resource id #5, 508) #1 {main} thrown in /customers/1/5/0/fv-vl-ardennen.be/httpd.www/beheerder/export_naar_csv.php on line 38
Dus ik zie dat er wel geconnecteerd wordt naar de database naar de gevraagde IDR en dat er 508 rijen zijn. Tot daar klopt het.
Wat ik nu begrijp is dat het 2e argument in fputcsv($fp,$rows)dus $rows een array moet zijn.
Dus nu ga ik op zoek naar hoe ik die code schrijf om de rijen in een array te steken.
Ondertussen ben ik al een stap verder. Het lukt met onderstaande code, alleen nu nog de juiste manier vinden om de rijen een na een in de .csv te steken. Want nu komt er alleen het eerste record erin.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php
// output headers so that the file is downloaded rather than displayed
//header('Content-Type: text/csv; charset=utf-8');
//header('Content-Disposition: attachment; filename=data.csv');
?>
<!DOCTYPE html>
<html lang="nl">
<head>
<title>Geen</title>
</head>
<body>
<?php
// mysql database connection details
include '../instellingen.php';
// open connection to mysql database
$conn = new mysqli($database_adres, $database_login_naam, $database_login_wachtwoord, $database_naam);
//connectie testen
if ($conn->connect_error)
{
die("verbinding mislukt: ".$conn->connect_error);
}
// gegevens uit een keuzeformulier waar ze bestand en begin en eindrecord kunnen kiezen.
$bestand = mysqli_real_escape_string($conn,$_POST['bestand']); echo $bestand;
$beginrec = mysqli_real_escape_string($conn,$_POST['beginrec']); echo $beginrec;
$eindrec = mysqli_real_escape_string($conn,$_POST['eindrec']); echo $eindrec;
// fetch mysql table rows
$sql = "select * from $bestand WHERE IDR BETWEEN '$beginrec' AND '$eindrec'";
$result = $conn->query($sql);
$rows = mysqli_num_rows($result);
$row = $result -> fetch_array(MYSQLI_NUM);
echo "There are " . $rows . " rows in my table.";
$fp = fopen('books.csv', 'w');
fputcsv($fp,$row);
fclose($fp);
//close the db connection
mysqli_close($conn);
?>
</body>
</html>
// output headers so that the file is downloaded rather than displayed
//header('Content-Type: text/csv; charset=utf-8');
//header('Content-Disposition: attachment; filename=data.csv');
?>
<!DOCTYPE html>
<html lang="nl">
<head>
<title>Geen</title>
</head>
<body>
<?php
// mysql database connection details
include '../instellingen.php';
// open connection to mysql database
$conn = new mysqli($database_adres, $database_login_naam, $database_login_wachtwoord, $database_naam);
//connectie testen
if ($conn->connect_error)
{
die("verbinding mislukt: ".$conn->connect_error);
}
// gegevens uit een keuzeformulier waar ze bestand en begin en eindrecord kunnen kiezen.
$bestand = mysqli_real_escape_string($conn,$_POST['bestand']); echo $bestand;
$beginrec = mysqli_real_escape_string($conn,$_POST['beginrec']); echo $beginrec;
$eindrec = mysqli_real_escape_string($conn,$_POST['eindrec']); echo $eindrec;
// fetch mysql table rows
$sql = "select * from $bestand WHERE IDR BETWEEN '$beginrec' AND '$eindrec'";
$result = $conn->query($sql);
$rows = mysqli_num_rows($result);
$row = $result -> fetch_array(MYSQLI_NUM);
echo "There are " . $rows . " rows in my table.";
$fp = fopen('books.csv', 'w');
fputcsv($fp,$row);
fclose($fp);
//close the db connection
mysqli_close($conn);
?>
</body>
</html>
We zijn op de goede weg.
Gewijzigd op 03/11/2021 11:50:14 door Ignace Verschaeve
Kijk, en zo kom je door het lezen van de foutmelding dus inderdaad een stukje verder.
Als je nog iets verder in de foutmelding kijkt, dan zie je ook dit: fputcsv(Resource id #5, 508)
Let op het getal(!) 508. Je hebt in dit geval niet de rijen met data doorgegeven, maar in plaats daarvan het aantal (een getal) rijen. En dus krijg je een foutmelding dat je een getal hebt doorgegeven in plaats van een (verwachte) array.
>> We zijn op de goede weg.
Inderdaad. Als je leert om foutmeldingen te lezen en interpreteren, kom je vaak een stapje verder.
Gewijzigd op 03/11/2021 12:03:28 door Ozzie PHP
Quote:
Let op het getal(!) 508. Je hebt in dit geval niet de rijen met data doorgegeven, maar in plaats daarvan het aantal (een getal) rijen. En dus krijg je een foutmelding dat je een getal hebt doorgegeven in plaats van een (verwachte) array.
Dat getal is niet belangrijk. Dat was mijn manier om te controleren of er wel degelijk rijen aanwezig zijn. = variabele $rows.
De andere variabele is $row zonder s achteraan. Maar blijkbaar had er ook niemand de foutmelding die er in allereerste instantie al was begrepen. Het correct in een array zetten. Nu probeer ik met een while lus alle records in het bestand te krijgen.
$rows bevat nu het aantal rijen, als een getal (508)
$row bevat nu een array dat met fetch() is getrokken uit de resultset.
Kies je $aantal_records, of desnoods $number_of_rows voor $rows, dan is duidelijk wat je kunt verwachten.
Daarna zou $row inderdaad het opgehaalde record /de regel met data kunnen bevatten.
while() is inderdaad een nuttige constructie om alle records te verzamelen.
---
" Maar blijkbaar had er ook niemand de foutmelding die er in allereerste instantie al was begrepen"
Even terug gekeken: jouw foutmelding had betrekking op het niet ondersteunen van de oude mysql-functies door jouw PHP versie.
En dat was direct in de eerste reactie al aangegeven. Wat probeer je nu eigenlijk te zeggen?
Je hobbelt van foutmelding naar foutmelding.
Mede veroorzaakt door het niet verder bouwen op code die je al hebt (je topic over INSERT query's maakt bijvoorbeeld al gebruik van mysqli, maar nu stap je terug op mysql.)
en ook door lukraak functies te gebruiken zonder uit te zoeken wat erin gaat of eruit kan komen.
Pfff, dat is het dus wel. De functie verwacht namelijk een array en jij geeft een getal door. Snap je dat het dan fout gaat?
>> Maar blijkbaar had er ook niemand de foutmelding die er in allereerste instantie al was begrepen. Het correct in een array zetten.
Wat??? Je gaat nu anderen de 'schuld' geven dat ze iets niet hebben begrepen, terwijl jij zelf continu fouten maakt?
Je zou je misschien eens wat anders, vriendelijker/dankbaarder, kunnen opstellen en de hulp die je krijgt proberen te waarderen. Daar lijkt het nu namelijk geenszins op. Ik wens je in ieder geval veel succes met het oplossen van je problemen.
Eerder werd PHPHulp.nl vergeleken met een soort commerciële klantensupport. Het zou toch kunnen dat hij totaal niet snapt dat PHP open source is, of wat open source überhaupt is, en dat hij een verkeerde aanname heeft gedaan dat dit forum gelieerd is aan PHP. Hij weet kennelijk niet dat er hier alleen mensen berichten plaatsen die enthousiast zijn over PHP en geheel vanuit vrij wil zonder enige vergoeding moeite doen om anderen belangeloos te helpen.
Hij heeft nog geen weet van de mores dat je ook zelf moeite moet doen om iets voor elkaar te krijgen, en dat je al helemaal geen tijd mag claimen van anderen.
En hoe zou hij het ook moeten (niet 'kunnen') weten? Onwetend zondigt men niet. Maar nu bovenstaande kennis hem heeft bereikt, heeft hij ook de verantwoordelijkheid er iets mee te doen.
Dit is de gebruikte code:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php
// output headers so that the file is downloaded rather than displayed
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="rijen.csv"');
ob_start();
// mysql database connection details
include '../instellingen.php';
// open connection to mysql database
$conn = new mysqli($database_adres, $database_login_naam, $database_login_wachtwoord, $database_naam);
//connectie testen
if ($conn->connect_error)
{
die("verbinding mislukt: ".$conn->connect_error);
}
// gegevens uit een keuzeformulier waar ze bestand en begin en eindrecord kunnen kiezen.
$bestand = mysqli_real_escape_string($conn,$_POST['bestand']);
$beginrec = mysqli_real_escape_string($conn,$_POST['beginrec']);
$eindrec = mysqli_real_escape_string($conn,$_POST['eindrec']);
// fetch mysql table rows
$sql = "select * from $bestand WHERE IDR BETWEEN '$beginrec' AND '$eindrec'";
$result = $conn->query($sql);
$rows = mysqli_num_rows($result);
//echo "There are " . $rows . " rows in my table.";
$fp = fopen('books.csv', 'w');
$i=0;
while($row = $result -> fetch_array(MYSQLI_NUM)){
fputcsv($fp,$row);
$i++;
}
fclose($fp);
//close the db connection
mysqli_close($conn);
?>
// output headers so that the file is downloaded rather than displayed
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="rijen.csv"');
ob_start();
// mysql database connection details
include '../instellingen.php';
// open connection to mysql database
$conn = new mysqli($database_adres, $database_login_naam, $database_login_wachtwoord, $database_naam);
//connectie testen
if ($conn->connect_error)
{
die("verbinding mislukt: ".$conn->connect_error);
}
// gegevens uit een keuzeformulier waar ze bestand en begin en eindrecord kunnen kiezen.
$bestand = mysqli_real_escape_string($conn,$_POST['bestand']);
$beginrec = mysqli_real_escape_string($conn,$_POST['beginrec']);
$eindrec = mysqli_real_escape_string($conn,$_POST['eindrec']);
// fetch mysql table rows
$sql = "select * from $bestand WHERE IDR BETWEEN '$beginrec' AND '$eindrec'";
$result = $conn->query($sql);
$rows = mysqli_num_rows($result);
//echo "There are " . $rows . " rows in my table.";
$fp = fopen('books.csv', 'w');
$i=0;
while($row = $result -> fetch_array(MYSQLI_NUM)){
fputcsv($fp,$row);
$i++;
}
fclose($fp);
//close the db connection
mysqli_close($conn);
?>
Misschien moet ik via een omweg werken en die outputheaders weglaten en met een downloadebel link werken.
Afgezien van je headers op regel 3 en 4.
---
En bedenk ook, dat als je eerst je headers stuurt en je op regel 14 een foutmelding stuurt, die als csv opgevat wordt.
Er staat daar een bestandje books.csv met de inhoud die ik vraag. Die headers zorgen er wel voor dat ik een schermpje krijg met de keuze om het bestand te openen met excell of het weg te schrijven naar een map op mijn PC maar dat bestandje is leeg. Alle bronnen die ik tot nu toe geraadpleegd heb houden diezelfde header syntax aan.
https://stackoverflow.com/questions/16251625/how-to-create-and-download-a-csv-file-from-php-script
Heb ik dit gemaakt :
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php
function array_csv_download( $array, $filename = "export.csv", $delimiter=";" )
{
header( 'Content-Type: application/csv' );
header( 'Content-Disposition: attachment; filename="' . $filename . '";' );
// clean output buffer
ob_end_clean();
$handle = fopen( 'php://output', 'w' );
// use keys as column titles
fputcsv( $handle, array_keys( $array['0'] ) , $delimiter );
foreach ( $array as $value ) {
fputcsv( $handle, $value , $delimiter );
}
fclose( $handle );
// flush buffer
ob_flush();
// use exit to get rid of unexpected output afterward
exit();
}
include('class_login_credentials.php');
$db = new mysqli($dblogin['host'],$dblogin['user'],$dblogin['pass'],$dblogin['db'],$dblogin['port']);
$db->set_charset("utf8mb4");
$query = "SELECT *
FROM `make_models_2_7_15`
LIMIT 50";
$result = $db->query( $query );
$models = $result->fetch_all(MYSQLI_ASSOC);
//echo '<pre>' . print_r( $models, TRUE ) . '</pre>';
array_csv_download( $models );
?>
function array_csv_download( $array, $filename = "export.csv", $delimiter=";" )
{
header( 'Content-Type: application/csv' );
header( 'Content-Disposition: attachment; filename="' . $filename . '";' );
// clean output buffer
ob_end_clean();
$handle = fopen( 'php://output', 'w' );
// use keys as column titles
fputcsv( $handle, array_keys( $array['0'] ) , $delimiter );
foreach ( $array as $value ) {
fputcsv( $handle, $value , $delimiter );
}
fclose( $handle );
// flush buffer
ob_flush();
// use exit to get rid of unexpected output afterward
exit();
}
include('class_login_credentials.php');
$db = new mysqli($dblogin['host'],$dblogin['user'],$dblogin['pass'],$dblogin['db'],$dblogin['port']);
$db->set_charset("utf8mb4");
$query = "SELECT *
FROM `make_models_2_7_15`
LIMIT 50";
$result = $db->query( $query );
$models = $result->fetch_all(MYSQLI_ASSOC);
//echo '<pre>' . print_r( $models, TRUE ) . '</pre>';
array_csv_download( $models );
?>
Gewijzigd op 03/11/2021 17:50:13 door Adoptive Solution
Dat je script een bestand aanmaakt, wil niet zeggen dat er iets naar de browser gaat. Zoals je zegt: dat bestand wordt op de server aangemaakt.
Maar de output van je script zou ook kunnen zijn "he gebruiker, het is gelukt".
Het is niet zo dat dat bestandje magisch naar de browser gestuurd wordt. Stel dat je 2 bestanden aanmaakt, een csv een een gifje: welke moet dan naar de browser?
Het voorbeeld van Adoptive doet wel iets magisch:
de regel
$handle = fopen( 'php://output', 'w' );
Zegt: doe net of je een bestand aanaakt, maar stuur de inhoud naar de standaard output van PHP (de browser).
Het bestand wordt in dat geval niet opgeslagen op de server.
Je zou als dat wel nodig is, het bestand ook op kunnen slaan op de server en dan met https://www.php.net/readfile het naar de browser sturen.
https://code.iamkate.com/php/creating-downloadable-csv-files/
En ik her er nu dit van gemaakt:
En nu werkt het wel. Het doel moet niet zijn 'books.csv' maar 'php://output'.
Nu nog eens zoeken hoe ik de separator die standaard op "," (komma) staat kan veranderen naar ";". Dat is in elk geval het derde argument in de fputcsv('file','fields','separator'). Dit '";"' werkt blijkbaar niet ook dit 'chr(59)' niet zoals ik al een suggestie vond.
Ondertussen nog eens gekeken naar een van mijn eerste linken waarmee het gestart is. En ik her er nu dit van gemaakt:
En nu werkt het wel. Het doel moet niet zijn 'books.csv' maar 'php://output'.
Nu nog eens zoeken hoe ik de separator die standaard op "," (komma) staat kan veranderen naar ";". Dat is in elk geval het derde argument in de fputcsv('file','fields','separator'). Dit '";"' werkt blijkbaar niet ook dit 'chr(59)' niet zoals ik al een suggestie vond.
Je geeft aan hoe je dat moet doen en dan nog lukt het je om het fout te doen.
Wijzig dit :
In dit :
Gewijzigd op 04/11/2021 07:35:33 door Ignace Verschaeve
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
<?php
// output headers so that the file is downloaded rather than displayed
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=data.csv');
// create a file pointer connected to the output stream
$output = fopen('php://output', 'w');
// output the column headings
fputcsv($output, array('Column 1', 'Column 2', 'Column 3'), ';');
fputcsv($output, array('data 1', 'data 2', 'data 3'), ';');
?>
// output headers so that the file is downloaded rather than displayed
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=data.csv');
// create a file pointer connected to the output stream
$output = fopen('php://output', 'w');
// output the column headings
fputcsv($output, array('Column 1', 'Column 2', 'Column 3'), ';');
fputcsv($output, array('data 1', 'data 2', 'data 3'), ';');
?>
Krijg ik deze output naar een bestand :
Dus bij deze opgelost. Bedankt allemaal voor het geduld.