【PHP】ul/liタグをforeachで関数化して出力する
記事更新日:2022-04-10
箇条書きスタイルは、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>
参考にしたのはこちらです。
【参考】
- 参考にしたサイト
- array_filterとは?
リストの数が決まっていれば、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 だね。
2022-04-10
編集後記:
この記事の内容がベストではないかもしれません。