2009-04-22 11 views
2

Ich habe einen Datensatz von MySQL erhalten, das so geht:Ignoranz ODER Fehler in PHPs "foreach" -Konstrukt?

 
Array 
(
    [0] => Array 
     (
      [views] => 14 
      [timestamp] => 06/04 
      [views_scaled] => 4.9295774647887 
      [unix_time] => 1239022177 
     ) 

    [1] => Array 
     (
      [views] => 1 
      [timestamp] => 19/04 
      [views_scaled] => 0.35211267605634 
      [unix_time] => 1240194544 
     ) 

     ... 
     ... 
     ... 

) 1 

(es ist nachbearbeitet, ‚Zeitstempel‘ war wirklich ein Zeitstempel vor, aber das spielt keine Rolle, sowieso)

Das Array auf $results gespeichert sind, und in der Mitte meines Code ich mache das so etwas wie:

 
$results = array_merge($results, $new_days); 
$a = $results; 
foreach ($results as $row) 
{ 
    $unix_time[] = $row['unix_time']; 
} 
$b = $results; 

Das Problem:$a und $b ar Beide sind verschieden. Der erste zeigt das Array, wie es soll, und der zweite hat das gleiche count(), aber das vierte Element ist ein Duplikat vom letzten. Soweit ich weiß, übergebe ich nichts als Referenz, also $results soll nicht ändern (vielleicht der Zeiger, aber nicht der Inhalt). Ich verwende PHP 5.2.4 unter Mac OS X 10.5.2.

Die offensichtliche Frage: Ist das irgendwie das beabsichtigte Verhalten, ein Bug oder mache ich hier etwas falsch? (keine boolesche Antwort bitte;)


EDIT: Vielen Dank für das Interesse, ich weiß nicht genau, wie viel zusätzlichen Code ich posten sollte, mache ich nicht viel vorher außer dem Abrufen der Daten von der DB und eine foreach, um den Zeitstempel zu analysieren und ein neues Array ( $new_days) für die fehlenden Tage zu erstellen. Das funktioniert alles gut.

Dieser Code geht nach der, die ich früh gebucht haben:

 
array_multisort($unix_time, SORT_ASC, $results); 
$days = implode('|', array_pluck('timestamp', $results)); 
$views = implode('|', array_pluck('views', $results)); 
$views_scaled = implode(',', array_pluck('views_scaled', $results)); 

(array_pluck() ist eine benutzerdefinierte Funktion ein Array aus einer Spalte in einem typischen DB-dumped-Datensatz zu erzeugen)


EDIT 2 : Nochmals vielen Dank, hier ist the full snippet und die Ausgabe von $results Array $a und $b (auch in den Kommentaren des Codes verwiesen).

+0

Das ist definitiv nicht das beabsichtigte Verhalten des Codes, den Sie enthalten haben. Und es ist auch kein Fehler in foreach. Sie sollten den _exact_ Code verwenden, den Sie verwenden, zwischen $ a = $ results; und wenn du endlich $ a und $ b druckst. – Calvin

+0

Dass mein Freund, so komisch das klingen mag, ist der genaue Code. Ich habe exit (print_r()) für jeden Punkt verwendet, den ich mit einer Variablen in diesem Code ($ a und $ b) dargestellt habe. – lima

+0

Was ist der Inhalt von $ new_days, welche Funktion verwenden Sie, um den Zeitstempel zu analysieren? Können wir den Code sehen, der für die Zeitstempel verwendet wird? Was passiert mit dem, was Sie mit dem Array tun, bevor Sie seine Ausgabe sehen? Können Sie Abzüge der Arrays direkt nach diesem Abschnitt, den Sie uns bisher gezeigt haben, ablegen? – Louis

Antwort

3

Überprüfen Sie Ihr Code-Snippet, wirklich schnell (nur um das Büro für den Tag zu verlassen), ist es wahrscheinlich mit etwas zu tun, das durch Verweis in Ihrer (ersten) Schleife.Versuchen Sie, normal nach Wert zu verwenden und alles in einem neuen Ergebnis-Array zu speichern. (wird alle Geheimnisse entfernen, die passieren könnten). Könnte auch versuchen, die zweite $ -Reihe in der zweiten für einen anderen Namen zu machen .. Beats me - kann ich dir nicht sagen, wenn ich mir das genauer anschaue.

auch diese Zeile und folgender Code-Block nicht

if ($last_day != $day_before_this_one AND $last_day) 
ausführen werden

etwas damit zu tun haben könnte, werden neue Tage füllen nie auf und die Zusammenführung könnte etwas zu tun, flippig sein.

Wäre das nicht nennen eine Antwort, aber es ist ein Anfang, betrachten ich

+0

Danke Lou, ich werde deine Vorschläge versuchen und es alle wissen lassen. Aber in der Zwischenzeit wird die von Ihnen hervorgehobene Zeile * ausgeführt, nicht das erste Mal (dies soll offensichtlich eine Endlosschleife vermeiden). Es ist derjenige, der dafür verantwortlich ist, das $ new_days-Array zu füllen, das am Ende ein Teil von $ result ist. – lima

+0

Ich habe den Namen der Wertvariablen in der zweiten foreach-Schleife geändert, von $ row nach $ row2 und es hat perfekt funktioniert! Vielen Dank und danke allen für Ihre Beiträge. Ich denke immer noch, dass dies ein Workaround für einen Bug ist, den Evert vorgeschlagen hat, aber wenn jemand die inneren Abläufe dieser Situation besser versteht, würde ich mich freuen, sie zu lesen. Ich bin einfach nicht abenteuerlustig genug, um auf bugs.php.net zu gehen und die TPS-Berichte auszufüllen. – lima

+1

Es wurde bereits eingereicht, und der Status ist "Bogus" - http://bugs.php.net/bug.php?id=29992 – Calvin

0

Ich kann mir nicht vorstellen, wie das beabsichtigte Verhalten ist. Da muss noch etwas anderes los sein. Können Sie das Verhalten auf einen Code beschränken, der klein genug ist, um hier zu posten? Wahrscheinlich wird der Bug dann offensichtlich.

0

Ich würde auch sagen, dass etwas anderes los ist.

Ich schrieb dies:

<?php 

$a = array('bob','sam','tom','harry'); 
$b = array(); 
$c = array(); 

foreach($a as $item) { 
     $c[] = $item; 
} 
$b = $a; 

print_r($a); 
print_r($b); 

Und bekam:

php ./test.php 
Array 
(
    [0] => bob 
    [1] => sam 
    [2] => tom 
    [3] => harry 
) 
Array 
(
    [0] => bob 
    [1] => sam 
    [2] => tom 
    [3] => harry 
) 

ich PHP 5.2.8 laufen lasse, though.

+0

Danke für die Prüfung! – lima

0

Ich denke, dein Problem ist, dass die Ergebnismenge nicht wirklich ein Array ist, es ist ein mysql resultset-Objekt, das wie ein Array funktioniert.

Ich denke, wenn Sie durch jede Zeile gehen, ein neues Array zuweisen, dann führen Sie die Zusammenführung, wird es richtig handeln.

+0

Ich glaube nicht, da es von CodeIgniter-Funktion result_array() abgerufen wird, und es nach der Zusammenführung in Ordnung aussieht, tritt das Problem nach der foreach-Schleife auf. – lima

0

erraten Wenn ich nicht irre, das vor einiger Zeit ein PHP-Fehler war. Ich kenne die Details nicht, aber Arrays und Referenzen wurden für ein bisschen vermasselt.

+0

Es ist kein Fehler: http://bugs.php.net/bug.php?id=29992 – Calvin

+0

Danke für die Referenz Calvin! – lima

+0

Ja, np. Auf der Oberfläche ist es eine Art kontraintuitives Verhalten, aber der 3. bis letzte Fehlerberichtskommentar gibt einen ziemlich guten Überblick über das, was vor sich geht. – Calvin

2

Das Problem ist die erste foreach-Schleife, wie bereits erwähnt wurde.

Hier ist die Argumentation ...

<? 
// set up an example array and loop through it using references (&) 
$my_array = array(1,2,3,4); 
foreach($my_array as &$item) 
{ 
    $item = $item+.1; 
} 
// 1st loop, $item points to: $my_array[0], which is now 1.1 
// 2nd, $item -> $my_array[1], which is now 2.1 
// 3rd, $item -> $my_array[2], which is now 3.1 
// 4th, $item -> $my_array[3], which is now 4.1 
// looping done, but $item is still pointing to $my_array[3] 

// next foreach loop 
foreach($my_array as $item) 
{ 
    var_dump($my_array); 
    print $item."<br>"; 
} 
// notice the & in the output of the var_dump, if you actually run this code. 
// 1st loop: the value of $my_array[0] is assigned to $item, which is still a pointer/reference to $my_array[3] 
// first loop.. array(1.1,2.1,3.1,1.1) // grabbing [0] and putting into [3] 
// next loop... array(1.1,2.1,3.1,2.1) // grabbing [1] and putting into [3] 
// next loop... array(1.1,2.1,3.1,3.1) // grabbing [2] and putting into [3] (here's where the magic happens!) 
// last loop... array(1.1,2.1,3.1,3.1) // grabbing [3] and putting into [3] (but [3] is the same as [2] !!!) 
?> 

Ich hoffe, das macht Sinn! Grundsätzlich wird der zweitletzte Wert wiederholt, da der letzte Wert während der zweiten Schleife ersetzt wird.

+0

Danke Josh, es macht tatsächlich Sinn und ich weiß, was dort vor sich geht. Definitiv irreführendes und nicht korrekt dokumentiertes Verhalten. Faustregel: Verwenden Sie für Variablen, die als Referenz übergeben wurden, unterschiedliche Namen (oder löschen Sie sie, bevor Sie sie ein zweites Mal verwenden). – lima

+0

kann ich die richtige antwort bekommen? :) –