PHP|HTMLと混在させる場合のインデントを考える

インデントの乱れは心の乱れ。可読性を損ないミスを誘発する――というかもうなんか生理的にやだ、美しくない。

いつも悩むのがPHP。PHPを埋め込みで使う場合、インデントについてのベストプラクティスがない。

PHPの記述は自由度が高い、というよりは無法であり世紀末のモヒカンがヒャッハーする世界のそれなので、インデント以外にもなにかと悩まされる。いろいろと俺々ルールの必要に迫られ、私においては以下のルールに従っている。

  • 波括弧({})を使わない。
  • echoは省略形(<?= ?>)を使う。
  • echo(<?= ?>)はHTMLとしてインデントする。
  • セミコロンを使わない。 → 一つのPHPタグ内に複数の文を書かない。
  • インデント:T.B.D.
<?php
// こういうとこはルール対象外
$args = [];
// (略)なんやかんやの処理
$items = getItems($args);
?>
<?php // 以下、ルール適用箇所 ?>

<main>
<?php // T.B.D. foreach($item as $items): ?>
  <section>
    <h1><?= $item['title'] ?></h1>
<?php // T.B.D. if (count($item['values']) > 0): ?>
    <ul>
<?php // T.B.D. foreach($item['values'] as $value): ?>
      <li<?= $value['flag'] ? ' class="hoge"' : '' ?>><?= $value['text'] ?></li>
<?php // T.B.D. endforeach ?>
    </ul>
<?php // T.B.D. endif ?>
    <?= $item['content'] ?>
  </section>
<?php // T.B.D. endforeach ?>
</main>

問題はT.B.D.としている<?php foreach($item as $items): ?>みたいな埋め込み構文のインデントである。これについてはなかなか答えが出ない。これらのインデントは、どうすれば美しくなるのか。

試行錯誤①|PHPもHTMLもとにかくインデント

<main>
  <?php foreach($item as $items): ?>
    <section>
      <h1><?= $item['title'] ?></h1>
      <?php if (count($item['values']) > 0): ?>
        <ul>
          <?php foreach($item['values'] as $value): ?>
            <li<?= $value['flag'] ? ' class="strong"' : '' ?>><?= $value['text'] ?></li>
          <?php endforeach ?>
        </ul>
      <?php endif ?>
      <?= $item['content'] ?>
    </section>
  <?php endforeach ?>
</main>

これはない。テキストとしては綺麗だが、論理的に汚い。PHPとHTMLどちらも構造を表せておらず、ネストも深くなって読みづらい。

試行錯誤②|HTMLでインデント、PHPは添えるだけ

<main>
  <?php foreach($item as $items): ?>
  <section>
    <h1><?= $item['title'] ?></h1>
    <?php if (count($item['values']) > 0): ?>
    <ul>
      <?php foreach($item['values'] as $value): ?>
      <li<?= $value['flag'] ? ' class="strong"' : '' ?>><?= $value['text'] ?></li>
      <?php endforeach ?>
    </ul>
    <?php endif ?>
    <?= $item['content'] ?>
  </section>
  <?php endforeach ?>
</main>

主役はHTMLだと考えているので、一時期はこれを採用していた。HTMLは綺麗である。しかしPHPがどこにあるのかわかりづらく、ロジックのミスを招きがちだった。

試行錯誤③|PHPとHTMLを別でインデント

<main>
<?php foreach($item as $items): ?>
  <section>
    <h1><?= $item['title'] ?></h1>
  <?php if (count($item['values']) > 0): ?>
    <ul>
    <?php foreach($item['values'] as $value): ?>
      <li<?= $value['flag'] ? ' class="hoge"' : '' ?>><?= $value['text'] ?></li>
    <?php endforeach ?>
    </ul>
  <?php endif ?>
    <?= $item['content'] ?>
  </section>
<?php endforeach ?>
</main>

PHPとHTMLを別世界でインデントしてみる。トリッキーな気もするが悪くない、と思いこれでコーディングしてみたのだが、タグの状況次第では非常に見づらくなることがわかった。HTMLとPHPの階層がかぶった場合、PHPタグがどこにあるのかわかりづらい。PHPタグは行頭に置くべきかもしれない。

試行錯誤④|PHPタグの中でインデント

<main>
<?php foreach($item as $items): ?>
  <section>
    <h1><?= $item['title'] ?></h1>
<?php   if (count($item['values']) > 0): ?>
    <ul>
<?php     foreach($item['values'] as $value): ?>
      <li<?= $value['flag'] ? ' class="hoge"' : '' ?>><?= $value['text'] ?></li>
<?php     endforeach ?>
    </ul>
<?php   endif ?>
    <?= $item['content'] ?>
  </section>
<?php endforeach ?>
</main>

完全に迷走している。可読性は高いがさすがに書きづらいだろう。タブキーでインデント変えられないもの。

試行錯誤⑤|PHPはインデントしない

<main>
<?php foreach($item as $items): ?>
  <section>
    <h1><?= $item['title'] ?></h1>
<?php if (count($item['values']) > 0): ?>
    <ul>
<?php foreach($item['values'] as $value): ?>
      <li<?= $value['flag'] ? ' class="hoge"' : '' ?>><?= $value['text'] ?></li>
<?php endforeach ?>
    </ul>
<?php endif ?>
    <?= $item['content'] ?>
  </section>
<?php endforeach ?>
</main>

行き着いたシンプルな答え、インデントしない。書いてみて気づいたが、埋め込みのPHPはさほど複雑なロジックを書かないのでインデントしなくても読める。

  • PHPタグを見落とさない
  • HTMLの階層が一目でわかる

に重点を置いている。ついでに出力するHTMLもガタガタにならないという副産物も得られる(どうでもいいですか?)。これがベストプラクティスだなんて全然思わないが、しばらくはこれでコーディングしてみよう。

――あれ? これ最初のT.B.D.のやつと同じじゃないか?