目的
「php foreach 最初と最後」「php foreach 最後」「php foreach last」などで検索すると、少し微妙な例ばかり出てきたので書いてみました。
なるべくベストパターンを載せるように努めていますが、何かあれば編集リクエストもしくはコメントを送っていただけると助かります。
PHP 7.3以上の場合
実装
$array = ['a', 'b', 'c', 'a']; // 0始まりでない配列や連想配列でもOK
foreach ($array as $index => $value) {
    if ($index === array_key_first($array)) {
        // 最初(始端処理)
        echo 'おはよう!', '<br>';
    }
    echo $value, '<br>';
    if ($index === array_key_last($array)) {
        // 最後(終端処理)
        echo 'おやすみ。', '<br>';
    }
}
結果
おはよう!
a
b
c
a
おやすみ。
PHP 7.3未満の場合
公式にPolyfillが載っているため、それに従いましょう。
(array_key_lastの方はUser Contributed Noteですが)
PHP: array_key_first
https://www.php.net/manual/ja/function.array-key-first.php#refsect1-function.array-key-first-notes
PHP: array_key_last
https://www.php.net/manual/ja/function.array-key-last.php#123016
実装
// 関数定義
if (!function_exists('array_key_first')) {
    function array_key_first(array $arr) {
        foreach($arr as $key => $unused) {
            return $key;
        }
        return NULL;
    }
}
if (!function_exists("array_key_last")) {
    function array_key_last(array $arr) {
        if (empty($arr)) {
            return NULL;
        }
        return array_keys($arr)[count($arr) - 1];
    }
}
// メイン処理
$array = ['a', 'b', 'c', 'a']; // 0始まりでない配列や連想配列でもOK
foreach ($array as $index => $value) {
    if ($index === array_key_first($array)) {
        // 最初(始端処理)
        echo 'おはよう!', '<br>';
    }
    echo $value, '<br>';
    if ($index === array_key_last($array)) {
        // 最後(終端処理)
        echo 'おやすみ。', '<br>';
    }
}
結果
おはよう!
a
b
c
a
おやすみ。
アンチパターン集
reset, endを使うパターン
バグるので絶対に使ってはいけません。
reset()は配列の最初の要素を返すため、要素に重複があると複数回実行されてしまいます。
end()も同様です。
実装
$array = ['a', 'b', 'c', 'a'];
foreach ($array as $value) {
    if ($value === reset($array)) {
        // 最初(始端処理)
        echo 'おはよう!', '<br>';
    }
    echo $value, '<br>';
    if ($value === end($array)) {
        // 最後(終端処理)
        echo 'おやすみ。', '<br>';
    }
}
結果
おはよう!
a
おやすみ。
b
c
おはよう!
a
おやすみ。
現在のインデックスをインクリメントするパターン
最後の判定だけ行うやつです。
インクリメントが冗長だしトレースがだるいのでおすすめしません。
実装
$array = ['a', 'b', 'c', 'a'];
$i = 0;
foreach ($array as $value) {
    echo $value, '<br>';
    $i++;
    if ($i === count($array)) {
        // 最後(終端処理)
        echo 'おやすみ。', '<br>';
    }
}
結果
a
b
c
a
おやすみ。
動作環境
- PHP 7.4.1