Невежество ИЛИ ошибка в конструкции PHP "foreach"? - PullRequest
2 голосов
/ 22 апреля 2009

У меня есть набор данных, полученный из MySQL, который выглядит следующим образом:

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

(это постобработка, 'timestamp' была действительно временной меткой раньше, но это не имеет значения в любом случае)

Массив хранится в $results, и в середине моего кода я делаю что-то вроде этого:

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

Проблема: $a и $b различны. Первый показывает массив, как он должен, а второй имеет тот же count(), но его четвертый элемент является дубликатом от последнего. Насколько я знаю, я не передаю ничего по ссылке, поэтому $results не предназначен для изменения (возможно, указатель, но не его содержимое). Я использую PHP 5.2.4 на Mac OS X 10.5.2.

Очевидный вопрос: Это как-то предполагаемое поведение, ошибка или я здесь что-то не так делаю? (не логический ответ, пожалуйста;) <ч /> РЕДАКТИРОВАТЬ: Спасибо всем за интерес, я не знаю точно, сколько дополнительного кода я должен публиковать, я не делаю много раньше, за исключением получения данных из БД и foreach для проанализируйте метку времени и создайте новый массив ($new_days) для пропущенных дней. Это все работает нормально.

Этот код идет после того, который я выложил раньше:

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() - это пользовательская функция для генерации массива из столбца в типичном наборе данных, выгруженном из БД) <ч /> РЕДАКТИРОВАТЬ 2: Еще раз спасибо, вот полный фрагмент и вывод из массива $results $a и $b (также упоминается в комментариях к коду).

Ответы [ 6 ]

3 голосов
/ 22 апреля 2009

Проверка вашего фрагмента кода, очень быстро (вот-вот уйти из офиса на день), возможно, это связано с чем-то, передаваемым по ссылке в вашем (первом) цикле. Попробуйте использовать нормальное значение и просто сохранить все в новый массив результатов. (удалит все тайны, которые могут происходить). Могли бы также попытаться сделать вторую строку $ во втором foreach другим именем ... превосходит меня - не могу сказать, действительно ли вы смотрите на это больше.

также эта строка и следующий блок кода не будут выполняться

if ($last_day != $day_before_this_one AND $last_day)

может иметь к этому какое-то отношение, новые дни никогда не заполнятся, и слияние может сделать что-то необычное.

Не назову это ответом, но, пожалуй, это начало, на которое я смотрю

2 голосов
/ 22 апреля 2009

Проблема заключается в первом цикле foreach, как уже упоминалось.

Вот рассуждения ...

<?
// 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] !!!)
?>

Надеюсь, это имеет смысл! В основном, значение от второго до последнего будет повторяться, потому что последнее значение заменяется во втором цикле.

0 голосов
/ 22 апреля 2009

Если я не ошибаюсь, это была ошибка PHP некоторое время назад. Я не знаю деталей, но массивы и ссылки были немного испорчены.

0 голосов
/ 22 апреля 2009

Я думаю, что ваша проблема в том, что результирующий набор на самом деле не является массивом, это объект набора данных MySQL, который действует как массив.

Я думаю, что если вы пройдете каждую строку, присваивая ее новому массиву, а затем выполните слияние, оно будет работать правильно.

0 голосов
/ 22 апреля 2009

Я бы также сказал, что происходит что-то еще.

Я написал это:

<?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);

И получил:

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

Я использую PHP 5.2.8.

0 голосов
/ 22 апреля 2009

Я не могу себе представить, как это подразумевается поведение. Здесь должно быть что-то еще. Можете ли вы выделить поведение для фрагмента кода, который достаточно мал для размещения здесь? Вероятно, если вы сделаете это, ошибка станет очевидной.

...