in_array gibt true, dürfte es aber nicht

HoPi

Mitglied
Moin,

ich bin dabei, eine CSV-Liste von Nummern zu importieren. Dazu prüfe ich erstmal, ob die Nummern, die in der Liste sind, eindeutig sind. In der Theorie sollte das kein Problem sein, in der Praxis ... seht selbst. Hab alles an Fehlerüberprüfung rausgenommen und mich auf's wesentliche beschränkt.

csv_import.php:
PHP:
<?php

if (isset($_FILES['csv_file'])) {

	$file = fopen($_FILES['csv_file']['tmp_name'], "r");
	$data_csv = array();

	while (($row = fgetcsv($file, 1024, ";")) !== FALSE) {

		if (!in_array($row[0], $data_csv)) {
			echo $row[0] ." written to array<br />";
			$data_csv[] = $row[0];
		} else
			echo $row[0] ." already in array<br />";

	}

	die();
}

?>
<form method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>" enctype="multipart/form-data">
	<input type="hidden" name="MAX_FILE_SIZE" value="500000">
	<input type="file" name="csv_file">
	<input type="submit" value="submit">
</form>

data.csv (meine Testdaten):
Code:
12312312311518
12312312301581
12312312301415
12312312312312352619
12312312312312352627
12312312312312352726
12312312312312352676
12312312312312352091

Und die Ausgabe im Browser nach Angabe der CSV-Datei:
Code:
12312312311518 written to array
12312312301581 written to array
12312312301415 written to array
12312312312312352619 written to array
12312312312312352627 already in array
12312312312312352726 already in array
12312312312312352676 already in array
12312312312312352091 already in array

Kann mir jemand erklären, wo der Fehler liegt? Prüft in_array nur auf x Zeichen oder sowas? Danke im Voraus.
 
Die Lösung ist relativ einfach, deine Zahlen sind zu lang für einen integer Typ, deshalb werden sie in ein Float (Gleitkommazahl) umgewandelt, die dann ungefähr so aussieht:

1.23123123123E+19

Und die der anderen Zahlen sieht genauso aus...

Die Lösung sieht so aus:

PHP:
<?php

if (isset($_FILES['csv_file'])) {

    $file = fopen($_FILES['csv_file']['tmp_name'], "r");
    $data_csv = array();

    while (($row = fgetcsv($file, 1024, ";")) !== FALSE) {

        if (!in_array($row[0], $data_csv, true)) {
            echo $row[0] ." written to array<br />";
            (string)$data_csv[] = $row[0];
        } else
            echo $row[0] ." already in array<br />";

    }
	exit();
}

?>
<form method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>" enctype="multipart/form-data">
    <input type="hidden" name="MAX_FILE_SIZE" value="500000">
    <input type="file" name="csv_file">
    <input type="submit" value="submit">
</form>
 
Da die Daten Zeichenketten sind, ist eine mögliche Längenbeschränkung von Integer-Werte irrelevant. Eine andere mögliche Ursache kann ich aber leider auch nicht nennen. Du könntest aber einfach alle Werte im Array sammeln und anschließend array_unique() mehrfach vorkommende Werte herausfiltern.
 
Die Umwandlung von Zahlen im String zu einem Integer-, Float- oder Double-Wert war mal ein Bug von der Funktion (soweit ich gelesen hab: http://bugs.php.net/bug.php?id=8409) und wurde direkt mit dem Release Candidate 4.0 (bisschen komisch) behoben, indem einfach der dritte Parameter angehängt wurde: http://bugs.php.net/bug.php?id=4753

Der dritte Parameter ($strict) sorgt seitdem dafür, dass der Typ nicht geändert wird.
Ist $strict false (oder nicht angegeben), ändert in_array im Hintergrund den Typ, so dass aus deinem langen String aus Zahlen wirklich ein Integer wird ohne das man es merkt.

Merkt man auch bei:
PHP:
$a = array( "001", "002", "007");
print_r( in_array(7, $a) );  // wird true ausgeben
print_r( in_array(7, $a, true) );  // wird false ausgeben
 
Zuletzt bearbeitet:
Zurück