Ik zit in de knoop(voor de zoveelste keer).
Ik heb een PHP script om een csv file te exporteren uit mij Mysql database. Zover gat het goed, maar nu wil ik de geexporteerde gegevens beperken tot een bepaalde datum. Dus een HTML formulier waar begin en einddatum wordt gekozen en dan verzonden ter uitvoering van het script. En daar loopt het fout. Ik vermoed dat het in mijn Select query zit. Hier volgt het stukje script
<?PHP
// input ophalen
$FTGdatum1 = DoStripSlashes( $_POST['begindatum'] );
$FTGdatum2 = DoStripSlashes( $_POST['einddatum'] );

// Fetch Record from Database

$output = "";
$table = "eva_tevr";
$sql = mysql_query("select * from $table WHERE datum BETWEEN $FTGdatum1 AND $FTGdatum2");
$columns_total = mysql_num_fields($sql);
?>
Het script werkte goed tot ik //input ophalen erbij heb gevoegd en "Where...." heb toegevoegd en ik vermoed dat ik daar de mist inga. Het is ook de bedoeling dat ik ook maar bepaalde velden exporteer maar dat moet ik het * vervangen door de veldnamen.
Dit is wat voor mij werkt, wat je zelf doet moet je zelf weten. De regels die ik gebruik zijn op een hand te tellen en zijn ondubbelzinnig. Je hoeft bij gebruik (als je eenmaal hebt doorgrond wat er gebeurt) ook niet al teveel na te denken wat ook fijn is ten opzichte van jezelf continu afvragen 'doe ik het wel goed' tijdens het schrijven van code.

Dat lijkt mij nog altijd beter dan om alles plat te spuiten met een prepared statements laag en daarmee aan te moedigen niet verder na te denken over wat je doet.

Tevens: getallen volgen een andere sortering dan strings. Als je je daar in je queries niet bewust van bent kan dit rare resultaten opleveren.
mysql> SELECT '200' BETWEEN '1' AND '3';
+---------------------------+
| '200' BETWEEN '1' AND '3' |
+---------------------------+
|                         1 |
+---------------------------+
1 row in set (0.00 sec)


Ik had laatst serieus een programmeur die gebruik maakte van PDO en zich afvroeg waarom een query geen foutmelding opleverde. Deze query vroeg informatie op uit een tabel middels een id uit de URL. In de URL vulde hij echter zoiets in als ?id=aap. In plaats van een foutmelding leverde dit gewoon geen resultaat op (omdat je tussenlaag van alles voor je aanpast). De programmeur begreep niet waarom.

Je zou dan kunnen stellen dat dit soort lagen hun doel voorbij zijn geschoten, maar ook dat zo'n laag alleen niet genoeg is.

Af en toe behoor je je input gewoon te filteren en vaak (nagenoeg altijd) is het verstandig om output te escapen. Dit is bijna fundamenteel voor het schrijven van "veilige code" dus ik snap niet dat dit wordt afgeraden om aan te leren aan beginners omdat dit te geavanceerd zou zijn.

En tot slot: Wat helemaal funest is, is als je eigenlijk geen weet hebt van wtf je aan het doen bent. Op het moment dat je aan de slag gaat met databases dan moet je je vertrouwd gaan maken (of het al zijn) met een aantal onderwerpen.
Ivo P op 09/03/2015 13:15:18

hij converteert '200' naar 200.

Vervolgens staat er dus WHERE employee_id = 200

dus dan lijkt me daar niets aan de hand

Hieruit blijkt nog steeds niet of het record wordt opgezocht door middel van een index lookup of een full table scan. In extreme gevallen kan dat het verschil zijn tussen het terugkrijgen van het record in een paar milliseconden of een paar minuten.
heb hier blijkbaar ongewild een discussie losgeweekt. In dit geval gaat het enkel om 2 datums waartussen de selectie moet vallen. Qua veiligheid maak ik mij weinig zorgen omdat dit enkel voor intern gebruik zal zijn. Maar toch zou ik graag weten hoe jullie dit als veilig zouden doen. Ik heb dit:
$FTGbegindatum = ( $_POST['begindatum'] );
$FTGeinddatum = ( $_POST['einddatum'] );
en vervolgens dit:
$sql_query = "select datum,factnr,email,verkoper from $table WHERE datum BETWEEN '". $FTGbegindatum ."' AND '". $FTGeinddatum ."'";
Ik begrijp dat dit niet veilig is.
Dus wil ik graag leren en begrijpen wat wel veilig is.
Ten eerste heeft het weinig nut om variabelen te te kopieëren. Waarom zou je $FTGbegindatum willen gebruiken, terwijl je al $_POST['begindatum'] hebt? Onnodig geheugenverspilling!

Verder moet je $_POST, $_GET en $_COOKIE-variabelen in een query altijd escapen met mysql(i)_real_escape_string() om SQL-injection te voorkomen.

Verder gebruiken we voor de leesbaarheid altijd hoofdletter voor MySQL-functies, en bij lange queries kan het geen kwaad om er wat enters tussenin te plaatsen.


<?php
$table = "facturen";
$sql_query = "
SELECT datum,factnr,email,verkoper FROM ".$table." 
WHERE datum BETWEEN '".mysqli_real_escape_string($con, $_POST['begindatum'])."' 
AND '".mysqli_real_escape_string($con, $_POST['einddatum'])."'";
?>
Ik krijg dit maar niet aan de praat.
Dit werkt:
<?php
$sql_query = "SELECT datum,factnr,email,verkoper FROM $table
WHERE datum BETWEEN '2015-02-01' AND '2015-02-28'";

?>
Hier krijg ik netjes de data tussen de 2 datums.

Dit werkt niet:
<?php
$sql_query = "SELECT datum,factnr,email,verkoper FROM $table
WHERE datum BETWEEN '".mysqli_real_escape_string($link, $_POST['date_5ISO8601'])."' AND '".mysqli_real_escape_string($link, $_POST['date_6ISO8601'])."'";
?>
Ik krijg een leeg csv bestand. Ook als ik 'begindatum' en 'einddatum' neem
Dit is het stukje code in het formulier (alleen voor de 1e datum, 2e datum is idem)
Ik gebruik Webplus8 om de site te maken

<html>
<input name="begindatum" class="OBJ-3" type="text" id="date_5" __AddCode="here" style="position:absolute;left:139px;top:27px;width:200px;height:22px;/*Add Style*/">
<script type="text/javascript">
$(function() {
$( "#date_5" ).datepicker({ beforeShow: function(input, inst) { setDatepickerCss(input); } });
$( "#date_5" ).datepicker( "option", $.datepicker.regional[ "nl" ] );
$( "#date_5" ).datepicker( "option", "dateFormat", "yy-mm-dd" );
$( "#date_5" ).datepicker( "option", "prevText", "" );
$( "#date_5" ).datepicker( "option", "nextText", "" );
$( "#date_5" ).datepicker( "option", "altField", "#date_5ISO8601" );
$( "#date_5" ).datepicker( "option", "altFormat", "yy-mm-dd" );
/*Add Script Here*/
});
</script>
<!--Postamble for Form Date Picker date_5-->
<input type="hidden" name="date_5ISO8601" id="date_5ISO8601">
</html>

Als ik dit stukje code uitvoer dan komen de datums wel op het uitvoerscherm dus is het blijkbaar niet aan de $POST gelegen.
<html>
<head>
<title>Form</title>
</head>

<body>

<?php
$FTGdatum1 =($_POST['date_5ISO8601']);
$FTGdatum2 =($_POST['date_6ISO8601']);

echo "<h1>Hello " .$FTGdatum1. " - " .$FTGdatum2. "</h1>";
// input ophalen

?>

</body>
</html>

Misschien nuttig: In de database is het veld datum van het type "date" jaar-maand-dag

Gelukkig ben ik al grijs, mijn haar kan alleen nog uitvallen. ;-)
En als je "yy-mm-dd" verandert in "yyyy-mm-dd"?
Dat is het niet want als ik dat verander in het formulier wordt het 20152015-02-01.Dus niet goed.In de database staat de datum ook als 2015-02-01.
Ik probeer het nog eens met een ander veld zoals verkoper of zoiets. where verkoper = input formulierveld.


[size=xsmall]Toevoeging op 16/03/2015 21:23:19:[/size]

Nog eens op een rijtje:
Uit te voeren script:
<?php


$host = 'xxx'; // MYSQL database host adress
$db = 'xxx'; // MYSQL database name
$user = 'xxx'; // Mysql Datbase user
$pass = 'xxx'; // Mysql Datbase password

// Connect to the database
$link = mysql_connect($host, $user, $pass);
mysql_select_db($db);

require 'exportcsv1.inc.php';

$table="eva_tevr"; // this is the tablename that you want to export to csv from mysql.

exportMysqlToCsv($table);

?>
2e script exportcsv1.inc.php

<?php

function exportMysqlToCsv($table,$filename = 'export.csv')
{
$csv_terminated = "\n";
$csv_separator = ";";
$csv_enclosed = '"';
$csv_escaped = "\\";
$sql_query = "SELECT datum,factnr,email,verkoper,vriendwin,uitleg,crossel,aanbod,conform,opm_winkel FROM $table
WHERE 'verkoper' = '".mysqli_real_escape_string($link, $_POST['verkoper'])."'";


// Gets the data from the database
$result = mysql_query($sql_query);
$fields_cnt = mysql_num_fields($result);


$schema_insert = '';

for ($i = 0; $i < $fields_cnt; $i++)
{
$l = $csv_enclosed . str_replace($csv_enclosed, $csv_escaped . $csv_enclosed,
stripslashes(mysql_field_name($result, $i))) . $csv_enclosed;
$schema_insert .= $l;
$schema_insert .= $csv_separator;
} // end for

$out = trim(substr($schema_insert, 0, -1));
$out .= $csv_terminated;

// Format the data
while ($row = mysql_fetch_array($result))
{
$schema_insert = '';
for ($j = 0; $j < $fields_cnt; $j++)
{
if ($row[$j] == '0' || $row[$j] != '')
{

if ($csv_enclosed == '')
{
$schema_insert .= $row[$j];
} else
{
$schema_insert .= $csv_enclosed .
str_replace($csv_enclosed, $csv_escaped . $csv_enclosed, $row[$j]) . $csv_enclosed;
}
} else
{
$schema_insert .= '';
}

if ($j < $fields_cnt - 1)
{
$schema_insert .= $csv_separator;
}
} // end for

$out .= $schema_insert;
$out .= $csv_terminated;
} // end while

header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Length: " . strlen($out));
// Output to browser with appropriate mime type, you choose ;)
header("Content-type: text/x-csv");
//header("Content-type: text/csv");
//header("Content-type: application/csv");
header("Content-Disposition: attachment; filename=$filename");
echo $out;
exit;

}

?>
Dit loopt goed tot ik er deze WHERE conditie bij zet.

Ik heb nu eens foutmeldingen aangezet. Misschien geraakt er nog iemand wijs uit. Ik in elk geval niet meer.
Om het simpel te maken heb ik nu gekozen voor verkoper. Als je Annelies kiest moet er zeker iets uitkomen.

Maar ik krijg een lege tabel met tabelnamen weliswaar.

Probeer maar eens op www.telecomvanassche.be/resultaten.html

En ik die dacht om het wat simpeler te maken voor mijn collega's.
Je gebruikt twee soorten functies door elkaar. => mysql en mysqli.

En waar komt $link vandaan?
$link komt uit het eerste code fragment
// Connect to the database
$link = mysql_connect($host, $user, $pass);
mysql_select_db($db);

Ik heb daarnet nog zitten googelen en ik kreeg al een donkerblauw vermoeden dat de knoop daar ergens zat. Nu nog uitvlooien hoe ik het kan aanpassen en wat ik moet aanpassen.
Ik heb al geprobeerd om er dit van te maken:

$sql_query = "SELECT datum,factnr,email,verkoper,vriendwin,uitleg,crossel,aanbod,conform,opm_winkel FROM $table
WHERE 'verkoper' = '".mysql_real_escape_string($link, $_POST['verkoper'])."'";

Maar dat is het blijkbaar ook niet.
Het is een function en een $link die buiten de function is aangemaakt is niet bekend in de function.
Dit kan je onder andere oplossen door
global $link;
bovenin de function te zetten.

Reageren