【WordPress】カスタムフィールドの値を行ごとにliタグで囲んでリスト表示する方法

カスタムフィールドに複数行のテキスト(箇条書きにしたい項目など)を入力しておき、テンプレート側で1行ずつ <li> で囲んでリスト表示する方法を解説します。ポイントは改行コードの扱い(\r\n対応)空行・空値の処理です。

この記事でわかること

  • get_post_meta() で複数行の値を取得する
  • preg_split() で改行分割する(explodeではダメな理由)
  • 空行の除去と、フィールドが空のときのガード
  • esc_html() で安全にリスト出力する
スポンサーリンク

カスタムフィールドの値を取得する

まず get_post_meta() で現在の投稿のカスタムフィールド値を取得します。

PHP:カスタムフィールドの値を取得
$post_id = get_the_ID();
$custom_field_value = get_post_meta($post_id, 'custom_field_name', true);

get_post_meta() の詳しい使い方はカスタムフィールドのテキストを表示する方法(get_post_meta完全ガイド)を参照してください。

改行で分割する(explodeではなくpreg_split)

explode(“\n”) では \r が残る
テキストエリアの改行コードは環境によって \n だけでなく\r\n(Windows系)のことがあります。explode("\n", $value) で分割すると各行末に \r が残り、文字列比較や空行判定が誤動作する原因になります。preg_split() で3種類の改行にまとめて対応しましょう。
PHP:改行コードの違いに対応して分割
// \r\n(Windows)・\r(旧Mac)・\n(Unix)のどれでも分割できる
$lines = preg_split('/\r\n|\r|\n/', $custom_field_value);

空行を除いて各行をliタグで囲む

値の末尾の改行や途中の空行をそのまま処理すると、空の <li></li> ができてしまいます。trim()array_filter() で空行を除いてから、esc_html() でエスケープして <li> で囲みます。

PHP:空行除去+エスケープしてli化
// 各行をtrimして空行を除去
$lines = array_filter(array_map('trim', $lines), function ($line) {
  return $line !== '';
});

// 各行をエスケープして <li> で囲む
$li_elements = array_map(function ($line) {
  return '<li>' . esc_html($line) . '</li>';
}, $lines);
エスケープは esc_html() で
WordPress開発では htmlspecialchars() よりも、WP標準の esc_html() を使うのが慣例です。入力値にHTMLタグが含まれていても文字として表示され、安全に出力できます。

ulリストとして出力する

implode() で結合し、<ul> で囲んで出力します。リストが空のときは <ul> 自体を出さないようにガードします。

PHP:空でないときだけリストを出力
if (!empty($li_elements)) {
  echo '<ul>' . implode('', $li_elements) . '</ul>';
}

完全なコード例(コピペ用)

取得から出力まで、空値・空行のガードを含めた完全版です。テンプレート(single.php など)のループ内に設置してください。

PHP:完全版(\r\n対応・空行除去・空値ガード付き)
<?php
$custom_field_value = get_post_meta(get_the_ID(), 'custom_field_name', true);

// フィールドが空なら何も出力しない
if ($custom_field_value) {

  // 改行コード(\r\n / \r / \n)に対応して分割
  $lines = preg_split('/\r\n|\r|\n/', $custom_field_value);

  // trimして空行を除去
  $lines = array_filter(array_map('trim', $lines), function ($line) {
    return $line !== '';
  });

  // エスケープして <li> で囲む
  $li_elements = array_map(function ($line) {
    return '<li>' . esc_html($line) . '</li>';
  }, $lines);

  // 空でなければ <ul> で出力
  if (!empty($li_elements)) {
    echo '<ul class="meta-list">' . implode('', $li_elements) . '</ul>';
  }
}
?>

「フィールドに値があるときだけ見出しごと表示したい」といった出し分けはカスタムフィールドの入力有無に応じて表示を切り替える方法が参考になります。

よくある質問(FAQ)

Qカスタムフィールドが配列で保存されている場合は?
Aget_post_meta($id, 'list_field', false) のように第3引数を false にすると同じキーの値を配列で取得できます。あとは foreachecho '<li>' . esc_html($item) . '</li>'; と回すだけです。取得の基本は投稿のカスタムフィールドを取得する方法を参照してください。
QACFのリピーターフィールドをリスト表示するには?
AACFでは have_rows() / the_row() でループします。if (have_rows('repeater')) { echo '<ul>'; while (have_rows('repeater')) { the_row(); echo '<li>' . esc_html(get_sub_field('item')) . '</li>'; } echo '</ul>'; } のように書きます。
Q値が未入力のときにデフォルトのリストを出すには?
A$value = get_post_meta(get_the_ID(), 'field', true) ?: "デフォルト値"; のように空のときの代替値を設定できます。ただし「空なら何も表示しない」のが自然な場面が多いため、この記事の完全版のように if ($value) でガードする形を基本にしてください。

まとめ

  • 分割preg_split('/\r\n|\r|\n/', $value)(explodeだと \r が残る)
  • 空行除去array_filter(array_map('trim', $lines), ...)
  • エスケープ:各行を esc_html() してから <li> で囲む
  • ガード:フィールドが空なら <ul> 自体を出力しない

改行コードと空行・空値のケアまで入れておけば、どの環境で入力された値でも崩れないリスト表示になります。