PHP のファイルから PHP の文と式だけを抜き出す

PHP ファイルに Syntax error があると、該当箇所を見つけるのはかなり困難である。理由は簡単で、HTML と PHP コードとが混じっているから。
たとえば <?php foreach ($list as $item) { ?> と <?php } ?> のあいだにたくさんの HTML タグが入っていると、それだけで '{' と '}' の対応を確認するのが難しくなる。

例えば次のような PHP ファイル (hoge.php) を考える (htmlspecialchars() は省略)。

<html>
  <body>
    <h1><?php echo $title; ?></h1>
    <?php if (! $list) { ?>
    <p>not found.</p>
    <?php } else { ?>
    <table>
      <thead>
        <tr>
          <th>#</th>
          <th>Name</th>
          <th>Site</th>
        </tr>
      </thead>
      <tbody>
        <?php $i = 0; ?>
        <?php foreach ($list as $item) { ?>
        <?php   $i += 1; ?>
        <?php   $color = i % 2 == 1 ? '#FFCCCC' : '#CCCCFF'; ?>
        <tr bgcolor="<?php echo $color; ?>">
          <td><?php echo $i; ?></td>
          <td><?php echo $item->name; ?></td>
          <?php if ($item->url) { ?>
          <td><a href="<?php echo $item->url; ?>"><?php $item->url; ?></a></td>
          <?php } else { ?>
          <td>-</td>
          <?php } ?>
        </tr>
      </tbody>
    </table>
    <?php } ?>
  </body>
</html>


この hoge.rhtml には Syntax error がある。それは次のようにして確かめることができる。

$ php -l hoge.php

Parse error: syntax error, unexpected $end in hoge.php on line 34
Errors parsing hoge.php


しかし、実際にどこが原因で Syntax error になっているのかは分からない。hoge.php をみても、HTML と PHP コードが入り交じっていて、見つけるのが困難である。

こんなときは、phpTenjin を使うとよい。phpTenjin は PHP で作られた高速なテンプレートエンジンで、式を「[= $var =]」(HTML エスケープあり) と「[== $var =]」(HTML エスケープなし) で書く以外はほぼ PHP そのままなテンプレートを使う。そして、phpTenjin には PHP コードだけを抜き出すオプション -S が用意されている。

$ phptenjin -S hoge.php
<?php 

         echo $title; 
     if (! $list) { 

     } else { 









         $i = 0; 
         foreach ($list as $item) { 
           $i += 1; 
           $color = i % 2 == 1 ? '#FFCCCC' : '#CCCCFF'; 
                      echo $color; 
               echo $i; 
               echo $item->name; 
           if ($item->url) { 
                        echo $item->url;    $item->url; 
           } else { 

           } 



     } 


?>


また -U をつけると連続する空行を圧縮し (uniq)、-C をつけると空行を取り除き (compact)、-N をつけると行番号が表示される (number)。

$ phptenjin -SNC hoge.php
    1:  <?php 
    3:           echo $title; 
    4:       if (! $list) { 
    6:       } else { 
   16:           $i = 0; 
   17:           foreach ($list as $item) { 
   18:             $i += 1; 
   19:             $color = i % 2 == 1 ? '#FFCCCC' : '#CCCCFF'; 
   20:                        echo $color; 
   21:  	       echo $i; 
   22:                 echo $item->name; 
   23:             if ($item->url) { 
   24:                          echo $item->url;    $item->url; 
   25:             } else { 
   27:             } 
   31:       } 
   34:  ?>


これを見れば一目瞭然。17 行目の foreach 文に対応する '}' が抜けていることがわかる。

このように、phpTenjin の -S オプションを使うと PHP のコードだけを抜き出してくれるので、チェックが簡単になる (同様の機能はErubisにもある)。ただし、<? ?> や <?= ?> を使っているとその部分はチェックできない。あくまで <?php ?> となっている部分だけが対象である。

なお Tenjin では -z を指定すると Syntax error をチェックしてくれる。これは php -l hoge.phpと比べると、複数ファイルを一度にチェックできるという利点がある。

### php -l だと Syntax error があればそれ以降はチェックされない
$ php -l hoge.php hoge2.php hoge3.php

Parse error: syntax error, unexpected $end in hoge.php on line 34
Errors parsing hoge.php

### phptenjin -z だとすべてのファイルをチェックしてくれる
$ phptenjin -z hoge.php hoge2.php hoge3.php
[NG] hoge.php
Parse error: syntax error, unexpected $end in hoge.php on line 35
Errors parsing hoge.php
[NG] hoge2.php
Parse error: syntax error, unexpected $end in hoge2.php on line 35
Errors parsing hoge2.php
[NG] hoge3.php
Parse error: syntax error, unexpected $end in hoge3.php on line 35
Errors parsing hoge3.php


追記: Ruby on Rails を使っている人はこちらをどうぞ。