【PHP】for文の繰り返し処理をカスタムフィールドで利用する【WordPress】

ある日の作業で。

同じような内容を入力するけど、パターンによって入力に必要なフィールド数が違う場合がありました。

内容は同じなので、ラベルは「test-1」のような数字分類で良いですが。

実際にフィールドを用意使用とすると、

・投稿済の値を呼び出すコード×10行
・フィールドを表示するHTML×20行(ラベル行とフォーム行×10)
・値を保存するコード×40行(保存のコード4行×10)

・・・と気が遠くなりました。

1つか2つ・・・個人的には3つくらいまでなら、ガリガリ書いてしまうんですが。

流石にこの量を書くのは、同じ処理を書いてるので無駄だなぁと。

なので、for分を使うことにしました。

for文とは

PHPで使用するfor文は、簡単に言うと「回数が決まっているループ処理」に使用します。

ワードプレスのループというと、クエリ操作をして、投稿の内容を表示するメインループやサブループが思い浮かびますが。

投稿件数は増え続けるもので、決まったものではないですからね。

それに、表示件数をクエリで指定できるので無理に使う必要もありません。

が。最近週間表示やら◯行やら回数が決まっているコードを書くことが多いので、「forは便利だなぁ」とか思ってたところだったり。

for文の基本形はこんな感じです。

for( 式1; 式2; 式3 ){
    //処理内容
}

「式1」は「初期値」とも言えます。ループの開始となる値を決めます。

「式2」はループが終了となる条件を決めます。

「式3」で「式1」がどのように変化するかを決めます。

よく見る例では、数字を順番に表示する例でしょうか。

for( $i = 1; $i <= 10; $i++ ){
    echo $i . '<br/>';
}

これで、1から10までの数値が縦並びで表示されます。

「式1」は変数$iに格納された1を初期値にしています。
「式2」は$iが10以下なら、$iの値を表示する処理をするという条件です。
「式3」は「式2」の条件に当てはまり、処理内容が実行された後に、$iを1ずつ増やします。

「式1」で指定した$iの値が「式3」の変化で「式2」の条件になるまで、処理が繰り返されます。

という感じです。

カスタムフィールドの入力フォームの表示でfor文

では、実際に作ろうとしていた3つの条件でここからコードにしてみようと思いますが。

ここから先はカスタムフィールドを自作した前提に進めるので、該当部分のコードのみ記載します。

カスタムフィールドの自作方法については、以前に書いた記事をご覧いただければと。

まずは、投稿画面に表示するカスタムフィールドですね。

例えば料理のレシピページで、使う野菜の種類と数の入力を簡略化するためにカスタムフィールドを用意するとします。

<?php for ($i = 1; $i <= 10; $i++): ?>
    <div style="padding: 5px 5px 5px 5px;<?php echo $i % 2 == 0 ? '' : 'background: lightgray;'; ?>">
        <label for="vegetable_name<?php echo $i; ?>">野菜名<?php echo $i; ?></label>
            <input id="vegetable_name<?php echo $i; ?>" name="vegetable_name<?php echo $i; ?>" type="text" value="<?php echo get_post_meta( $post->ID, 'vegetable_name' . $i, true ); ?>" style="width: 100%; max-width: 100%;">
        <label for="amount_to_use<?php echo $i; ?>">使用量<?php echo $i; ?></label>
            <input id="amount_to_use<?php echo $i; ?>" name="amount_to_use<?php echo $i; ?>" type="text" value="<?php echo get_post_meta( $post->ID, 'amount_to_use' . $i, true ); ?>" style="width: 100%; max-width: 100%;">
    </div>
<?php endfor; ?>

これで、野菜名を入力するフィールドと、使用量を入力するフィールドを用意できます。

ラベルにも$iをつけ、「野菜1」「使用量1」と数字で見分けやすくしています。

また、2行目のstyle属性で

<?php echo $i % 2 == 0 ? '' : 'background: lightgray;'; ?>

と指定することで、奇数回数の繰り返し処理時に背景が灰色になるようにしています。

ストライプ表示でまとまりを分かりやすくという感じ。

値の更新でfor文

見出しを分ける必要も無いかもしれませんが。

カスタムフィールドに限ったことではありませんが、ワードプレスで入力した内容は送信することで登録され、反映されます。

なので、先程のカスタムフィールドの値を送信して、サーバーが値を受け取り、name属性に応じて値を更新または登録するという流れに。

フォームで送信された値受け取るのは$_GETや$_POSTなので、ここで指定するname属性にループの$iの値を連結して、取得・更新させましょう。

<?php
for( $i = 1; $i <= 10; $i++ ){
        if( isset($_POST['vegetable_name' . $i] ) ){
            $data = sanitize_text_field( $_POST['vegetable_name' . $i] );
            update_post_meta( $post_id, 'vegetable_name' . $i, $data );
        }
        if( isset($_POST['amount_to_use' . $i] ) ){
            $data = sanitize_text_field( $_POST['amount_to_use' . $i] );
            update_post_meta( $post_id, 'amount_to_use' . $i, $data );
        }
    }
?>

値を取得するfor文

値を取得する場合・・・というか、フォーム表示のvalue値ということにもなりますね。

先程のHTMLの方では、get_post_meta()を利用して直接呼び出しましたが、変数に渡すことも可能です。

その場合は、変数の配列にわたすようなイメージです。

<?php
for( $i = 1; $i <= 10; $i++ ){
        $vegetable_name[$i] = get_post_meta( $post->ID, 'vegitable_name' . $i, true );
        $amout_to_use[$i] = get_post_meta( $post->ID, 'amount_to_use' . $i, true );
    }
?>

なので、HTMLの方もこのように変えられます。

<?php for ($i = 1; $i <= 10; $i++): ?>
    <div style="padding: 5px 5px 5px 5px;<?php echo $i % 2 == 0 ? '' : 'background: lightgray;'; ?>">
        <label for="vegetable_name<?php echo $i; ?>">野菜名<?php echo $i; ?></label>
            <input id="vegetable_name<?php echo $i; ?>" name="vegetable_name<?php echo $i; ?>" type="text" value="<?php echo $vegetable_name[$i]; ?>" style="width: 100%; max-width: 100%;">
        <label for="amount_to_use<?php echo $i; ?>">使用量<?php echo $i; ?></label>
            <input id="amount_to_use<?php echo $i; ?>" name="amount_to_use<?php echo $i; ?>" type="text" value="<?php echo $amount_to_use[$i]; ?>" style="width: 100%; max-width: 100%;">
    </div>
<?php endfor; ?>

回数が決まっている場合は便利

コードはある程度スッキリさせて、視認性を良くしておきたいので。

for文を利用することでコードの量を減らしつつ、読みやすい状態が作れますね。

ただ、今回はループする回数が決まっていたのでfor文を使いましたが。

回数があやふやな場合は無理に自作するよりも、ACFの有料機能である「繰り返しフィールド」を開放しちゃった方が良い気もします。

JSで動的に増減するカスタムフィールドの自作をすれば、似たようなものにはなりますが。

既にあるものに労力を使うのもなぁ。

参考:for-PHPリファレンス
参考:【PHP for文】初心者が覚えておくべき3つのポイントとは‐侍エンジニア