毎日PHPを使用してプログラミングする場合、多くの開発者が問題に遭遇した可能性があります。ForeachLoopでは、 end()を使用して配列の最後の要素を取得しようとしますが、結果は予想されていません。この質問は簡単に思えますが、PHPの根底にある行動理解が含まれます。この記事では、この現象を詳細に分析し、あなたのアイデアを明確にし、落とし穴にとらわれないようにするのに役立ちます。
最初にコードを見てみましょう:
$data = ['a', 'b', 'c', 'd'];
foreach ($data as $key => $value) {
echo "現在の値: $value\n";
echo "最後の要素はです: " . end($data) . "\n";
}
次のように出力が期待される場合があります。
現在の値: a
最後の要素はです: d
現在の値: b
最後の要素はです: d
...
しかし、実際には、そうでない場合があることがわかります。 end()とkey()を使用してループに結合したとしても、要素dを取得することはなく、他の値を取得できます。これは、コアの質問をもたらします。
PHPのend()関数は、配列の「最後の値」を直接取得しません。その機能は次のとおりです。
配列の内部ポインターを最後の要素に移動し、その要素の値を返します。
この文の焦点は、「ポインターの移動」です。 「ポインター」はPHPアレイ内で維持され、次() 、 prev() 、 reset() 、およびend()の使用は、このポインターの位置に影響します。言い換えれば、 end()には副作用があります。
ForeachはPHPの言語構造です。配列を繰り返すときに、この「内部ポインター」を使用しません。つまり、
Foreachを使用して$データを繰り返すと、PHPはバックグラウンドでコピーまたはスナップショットを作成します。
foreachでend()を使用するという理由だけで、 foreachの反復挙動には影響しません。
ただし、 foreachでend()を使用すると、元の配列の内部ポインターが変更されます。
この「ポインターは互いに干渉しません」は、 each ()でend()を呼び出しますが、 key()やcurrent()などの他の関数と組み合わせて使用すると、矛盾または論理的エラーさえも誤りがあります。
次のコードは、混乱するシナリオを示しています。
$urls = [
'http://m66.net/page1',
'http://m66.net/page2',
'http://m66.net/page3',
];
foreach ($urls as $url) {
if ($url === end($urls)) {
echo "これが最後のページです: $url\n";
} else {
echo "処理: $url\n";
}
}
このコードは、それが最後のURLであるかどうかを知ることができると思うかもしれません。実際、 end()がアレイポインターを最後の要素に移動するため、最初のものが「最後のもの」であると常に決定する可能性が高いが、ループの内部$ URLはスナップショットコピーであり、判断ロジックは無効である。
それがforeachの最後の要素であるかどうかを判断するには、いくつかの推奨方法があります。
$count = count($urls);
for ($i = 0; $i < $count; $i++) {
$url = $urls[$i];
if ($i === $count - 1) {
echo "これが最後のページです: $url\n";
} else {
echo "処理: $url\n";
}
}
$last = end($urls);
reset($urls); // 後でそれを通過する必要がある場合
foreach ($urls as $url) {
if ($url === $last) {
echo "これが最後のページです: $url\n";
} else {
echo "処理: $url\n";
}
}
この方法も問題ありませんが、注意してください。配列に値が重複している場合、2つのURLが同じであるなど、誤解される可能性があります。
end($urls);
$lastKey = key($urls);
reset($urls);
foreach ($urls as $key => $url) {
if ($key === $lastKey) {
echo "最後のアイテム: $url\n";
} else {
echo "処理: $url\n";
}
}
これはより安全な方法であり、連想配列または配列値が繰り返される場合に推奨されます。
foreachループでend()を使用すると、PHPのアレイポインターメカニズムとforeach反復メカニズムが分離されているため、予想どおりに機能しない場合があります。これを理解すると、潜在的なバグや論理エラーを回避できます。
一般に、 End()は副作用を持つ関数です。それが最後の要素であるかどうかを判断する必要がある場合、カウント、一時的な変数、または重要な比較など、より信頼性の高い方法を使用する必要があります。
この記事がPHPのこの「素晴らしい」振る舞いをよりよく理解するのに役立つことを願っています!