PHP foreach и ссылки - PullRequest
       307

PHP foreach и ссылки

3 голосов
/ 24 ноября 2010

Я пытаюсь изменить значения, используя указатели внутри вложенных циклов foreach в PHP .. Однако следующая строка не работает:

// Assign a the attribs value to the array
$link_row['value'] = $args[ $u_value ];

переменная $ args [$ u_value]; заполнен и может быть выведен без проблем, но когда я добавил его в ссылку $ link_row, он просто не устанавливается ..

  foreach ($unique_links as $link_id => &$link_attr)
  {
     foreach($link_attr as &$link_row)
     {
        foreach($link_row as $u_attr => &$u_value)
        {
           if ($u_attr == 'attribute_name') 
           {               

              // Assign a the attribs value to the array
              $link_row['value'] = $args[ $u_value ];

              // If one of the values for the unique key is blank,  
              // we can remove the entire 
              // set from being checked
              if ( !isset($args[ $u_value ]) ) 
              {
                 unset($unique_links[$link_id] );
              }
           }
        }
     }
  }

Ответы [ 3 ]

4 голосов
/ 09 декабря 2010

Вы должны всегда сбрасывать переменные после их использования в foreach. Даже если у вас есть два foreach(..) заявления один за другим. Даже если у вас есть foreach(..) внутри другого foreach(..). Без исключений!

foreach ($unique_links as $link_id => &$link_attr)
{
 foreach($link_attr as &$link_row)
 {
    foreach($link_row as $u_attr => &$u_value)
    {
       if ($u_attr == 'attribute_name') 
       {               

          // Assign a the attribs value to the array
          $link_row['value'] = $args[ $u_value ];

          // If one of the values for the unique key is blank,  
          // we can remove the entire 
          // set from being checked
          if ( !isset($args[ $u_value ]) ) 
          {
             unset($unique_links[$link_id] );
          }
       }
    }
    unset($u_value);  // <- this is important
 }
 unset($link_row);  // <- so is this
}
unset($lnk_attr);  // <- and so is this, even if you reached the end of your program or the end of a function or a method and even if your foreach is so deeply indented or on such a long line that you're not sure what code might follow it, because another developer (maybe even you) will come back and read the code and he might not see that you used a reference in a foreach

Вот еще один забавный фрагмент кода, который недавно испортил большой проект:

foreach ($data as $id => &$line) {
    echo "This is line {$id}: '{$line}'\n";
    $line .= "\n";
}

echo "And here is the output, one line of data per line of screen:\n";

foreach ($data as $id => &$line) {
    echo $line;
}

Тот факт, что кто-то не unset($line) сразу после первого foreach(..) действительно испортил данные в массиве, потому что &$line был ссылкой, а второй foreach(..) присвоил ему другое значение при зацикливании через данные, и он продолжал перезаписывать последнюю строку данных.

0 голосов
/ 24 ноября 2010

Поскольку я не вижу ваши массивы, я не знаю, какие из них являются целыми, какие ассоциируются и т. Д.

Насколько я понимаю, нет причин для ссылки на $ u_value.Это не приносит никакого вреда, но в любом случае не имеет значения.

Что еще более важно, каждый раз, когда вы выполняете второе условие, если вы выполняете условие, у вас будет ошибка, прежде чем вы достигнете его в строке

 $link_row['value'] = $args[ $u_value ];

возможно, вы захотите использовать

$link_row['value'] = isset($args[$u_value]) ? $args[ $u_value ] : "NOT PRESENT";

Строка, которую вы упоминаете, кажется, работает просто отлично.

Мой код:

    $args = array(100,200,300,400,500);
    $unique_links = array (array(   'a' => array('attribute_name' => 1,'x' => 2, 'y' => 3, 'z' =>4), 
                                    'b' => array('attribute_name' => 3,'x' => 2, 'y' => 3, 'z' =>4),
                                    'c' => array('attribute_name' => 0,'x' => 2, 'y' => 3, 'z' =>4),
                                    'd' => array('attribute_name' => 7,'x' => 2, 'y' => 3, 'z' =>4),
                                    'e' => array('attribute_name' => 1,'x' => 2, 'y' => 3, 'z' =>4)

                                    ));                                 
    echo_r($unique_links);
    foreach ($unique_links as $link_id => &$link_attr)
    {
        foreach($link_attr as &$link_row)
        {
            foreach($link_row as $u_attr => $u_value)
            {
                echo "&nbsp&nbsp&nbsp&nbsp $u_attr is $u_value <br />";
                if ($u_attr == 'attribute_name')
                {

                    // Assign a the attribs value to the array
                    $link_row['value'] = isset($args[$u_value]) ? $args[ $u_value ] : "NOT PRESENT";

                    // If one of the values for the unique key is blank, we can remove the entire
                    // set from being checked
                    if ( !isset($args[ $u_value ]) )
                    {
                        //echo "want to kill: $link_id <br />";
                        //unset($unique_links[$link_id] );
                    }
                }
            }
            echo "<br />";
        }
    }
    echo_r($unique_links);

Мой вывод:

Array
(
[0] => Array
    (
        [a] => Array
            (
                [attribute_name] => 1
                [x] => 2
                [y] => 3
                [z] => 4
            )

        [b] => Array
            (
                [attribute_name] => 3
                [x] => 2
                [y] => 3
                [z] => 4
            )

        [c] => Array
            (
                [attribute_name] => 0
                [x] => 2
                [y] => 3
                [z] => 4
            )

        [d] => Array
            (
                [attribute_name] => 7
                [x] => 2
                [y] => 3
                [z] => 4
            )

        [e] => Array
            (
                [attribute_name] => 1
                [x] => 2
                [y] => 3
                [z] => 4
            )

    )

)

 attribute_name is 1
 x is 2
 y is 3
 z is 4
 value is 200

 attribute_name is 3
 x is 2
 y is 3
 z is 4
 value is 400

 attribute_name is 0
 x is 2
 y is 3
 z is 4
 value is 100

 attribute_name is 7
 x is 2
 y is 3
 z is 4
 value is NOT PRESENT

 attribute_name is 1
 x is 2
 y is 3
 z is 4
 value is 200

Array
(
[0] => Array
    (
        [a] => Array
            (
                [attribute_name] => 1
                [x] => 2
                [y] => 3
                [z] => 4
                [value] => 200
            )

        [b] => Array
            (
                [attribute_name] => 3
                [x] => 2
                [y] => 3
                [z] => 4
                [value] => 400
            )

        [c] => Array
            (
                [attribute_name] => 0
                [x] => 2
                [y] => 3
                [z] => 4
                [value] => 100
            )

        [d] => Array
            (
                [attribute_name] => 7
                [x] => 2
                [y] => 3
                [z] => 4
                [value] => NOT PRESENT
            )

        [e] => Array
            (
                [attribute_name] => 1
                [x] => 2
                [y] => 3
                [z] => 4
                [value] => 200
            )

    )

)

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

0 голосов
/ 24 ноября 2010

Я думаю, вы можете перезаписать значение в цикле.Чтобы проверить это, вы можете сделать что-то вроде этого

$link_row['value'] = $args[ $u_value ];

Измените это на

$link_row[] = $args[ $u_value ];

Затем за пределами цикла добавьте это

<code>echo "Link Row Value(s):<pre>".print_r($link_row,true)."
\ n ";

Это покажет все значения, которые преобразуются / устанавливаются в $ link_row ['value'], если вы видите более одного индекса, значения перезаписываются

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...