銀河鉄道

【PHP】ul/liタグをforeachで関数化して出力する

サムネイル
foreachで動的な ul タグ

箇条書きスタイルは、ulタグとliタグで作るよね。

●タイトル1
>>テキスト1-1
*テキスト1-1-1
●タイトル2
>>テキスト2-1

ulとliって、繰り返し処理にできないのかな。

foreachで試してみよう。

箇条書きの中身を、「多次元配列」に格納する

箇条書きの中身を、配列で設定するよ。

// text:画面に表示させる文字
// text_tag:テキストにタグを付けたい場合
// class:個別に設定したいクラス名
// url:リンク先(無い場合は空にする)

// *parentには紐付けるid番号を指定する*
// 親の場合は、空("")にする
// 子の場合は、紐付ける親のid番号
// 孫の指定も可能(子のid番号と紐付ける)

$arr = array(
  // 1つ目
  [
      "text"   => "タイトル1",
      "text_tag" => "h3",
      "class"  => "aaa",
      "url"    => "#",
      "id"     => "1",
      "parent" => "",
  ],
  [
      "text"   => "テキスト1-1",
      "text_tag" => "",
      "class"  => "bbb",
      "url"    => "#",
      "id"     => "11",
      "parent" => "1",
  ],
  [
      "text"   => "テキスト1-1-1",
      "text_tag" => "",
      "class"  => "ccc",
      "url"    => "#",
      "id"     => "7",
      "parent" => "11",
  ],

  // 2つ目
  [
      "text"   => "タイトル2",
      "text_tag" => "h3",
      "class"  => "aaa",
      "url"    => "#",
      "id"     => "2",
      "parent" => "",
  ], 
  [
      "text"   => "テキスト2-1",
      "text_tag" => "",
      "class"  => "bbb",
      "url"    => "#",
      "id"     => "12",
      "parent" => "2",
    ],
);

// 共通のクラス名
$class = [
  "ul_parent" => "parent-list"; // ul親クラス
  "ul_child" => "child-list";  // ul子クラス
  "li_title" => "parent"; // li親クラス
  "li_item" => "child";  // li子クラス
]


// 関数に配列を渡す
echo create_list_block($arr, $class);

テキストもクラス名も配列にすれば、呼び出し元ではタグを書かなくて済むんだね。

ul タグ出力の関数を作成

渡された配列を、関数の中で展開するよ。

<?php
// ↓出力結果↓ ※タグ数は配列の要素数により動的に生成
// <ul class="(ul_parent)">
//   <li class="(li_title)"> →→ ★first loop
//     タイトル
//     <ul class="(ul_child)">
//       <li class="(li_item)"> →→ ★after loop(ulが1つだけのときは、liはafterが適用される)
//         <a href="">テキスト</a>
//       </li>
//     </ul>
//   </li>
// </ul>
// ↑出力結果↑


// **
// ★first loop(最初の呼び出し関数)
// @param array $arr:出力するデータ配列
// @param array $class:クラス名
// **
function create_list_block($arr, $class) {
  // 配列から親だけを抽出
  $parents = array_filter($arr, function ($item) { return !$item['parent'];});
?>
    <ul class="<?php echo $class['ul_parent'];?>">
      <?php my_loop($parents, $class, $arr);?>
    </ul>
<?php
};


// **
// ★after loop(2回目以降のループ)
// **
function create_li_tag($item, $class, $arr) {
  $flag_ul_child = true;
  // 親の場合
  if ($item['parent'] === "") {
    // タイトル無しの場合は子のulを無しにする
    if ($item['text'] =="") {
      $flag_ul_child = false; // flagをfalseにする
      goto skip;

    // タイトル有りの場合はテキスト設定
    } else {
      $flag_ul_child = true;
      $li_class = $class['li_title'] . ' ' . $item['li_class']; // 共通クラス+個別クラス
      $li_text = set_li_text($item);// テキスト設定
     }

  // 子の場合
  } else {
    $li_class = $class['li_item'] . ' ' . $item['li_class'];
    $t_item = set_li_text($item);// テキスト設定
    $li_text = '<a class="'. $item['a_class'] .'" href="'. $item['url'] .'" target="'. $item['a_target'] .'">'. $t_item .'</a>';
  };

  echo '<li class="'. $li_class .'">'. $li_text;

  skip:

  // 配列から子だけを抽出
  $children = array_filter($arr, function ($i) use ($item) { return $i['parent'] == $item['id']; });

  if (!empty($children)) {
    // タイトル有りならulタグ生成
    if($flag_ul_child) {
      echo '<ul class="'. $class['ul_child'] .'">';
    }

    my_loop($children, $class); // 子のループ

    if($flag_ul_child) {
      echo '</ul>';
    }
  }
};



// **
// ループ
// **
function my_loop($lists, $class, $arr) {
    foreach ($lists as $list) {
        create_li_tag($list, $class, $arr);
    }
};


// **
// テキスト設定(タグ指定があればタグを付ける)
// **
function set_li_text($item) {
    switch($item['text_tag']) {
        case "":
            $text = $item['text']; //タグ指定なければテキストのみ
            break;
        default:
            $tag = $item['text_tag'];
            $text = '<'. $tag .' class="'. $item['text_class'] .'">'. $item['text'] . '</'. $tag .'>';
            break;
    }
    return $text;
};

ちょっと複雑だけど、よく見ると、配列の中身をechoしてるだけだね。

functions.phpに関数を呼び出し

関数はfunctions.phpに呼び出しておこう。

include(get_template_directory() . 'create_list_block.php');

出力結果

上の配列と関数は、HTMLではこう出力される。

<ul class="parent-list">
  <li class="parent aaa">
    <h3>タイトル1</h3>
    <ul class="child-list">
      <li class="child bbb">
        <a href="#">テキスト1-1</a>
          <ul class="child-list">
            <li class="child ccc">
              <a href="#">テキスト1-1-1</a>
            </li>
          </ul>
       </li>
     </ul>
  </li>
  <li class="parent aaa">
    <h3>タイトル2</h3>
    <ul class="child-list">
      <li class="child bbb">
        <a href="#">テキスト2-1</a>
       </li>
     </ul>
  </li>
</ul>

参考にしたのはこちらです。

【参考】

リストの数が決まっていれば、forループで

上の関数ではリストの数を動的に増やせるけど、数が決まってるならforループだけで。

<?php
$lists = ["A", "B", "C"];
$count = count($lists);
?>

<ul>
  <?php for ($i = 0; $i < $count; $i++): ?>
    <li><?php echo $lists[$i]; ?></li>
  <?php endfor; ?>
</ul>

<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
</ul>

とりあえず、繰り返すものがあったら、for か foreach だね。

著者

author
月うさぎ

編集後記:
この記事の内容がベストではないかもしれません。