PHP初心者でも簡単にPerlに移行するための妙妙案

PHPが何で扱いやすいかわかったよ!PHPタグに真理があったんだよ!

<html>
  <body>
<?php $name = "fbis" ?>
    僕の名前は<?php print $name; ?>です。
    年齢は<?php print $_REQUEST['age']; ?>歳です。
  </body>
</html>

これだけで動くんだもんそりゃ便利だし分かりやすいよ。

なのでPerlでもPHPタグ使えるようにしてみました。

package PHP::Block;
use strict;
use warnings;
use Module::Compile -base;

sub conver_print {
    my $str = shift;
    return '' unless $str;
    $str =~ s{\x27}{\x5C\x27}g;
    $str = ';header() if @_HEADER;print \''.$str.'\';';
    return $str;
}

sub pmc_fold_blocks {
    my ($class, $source) = @_;
    $source = "use PHP::Block;\n".$source;
    $class->SUPER::pmc_fold_blocks($source);
}

sub make_begin {
    return q{
        use CGI;
        our %_REQUEST = %{CGI->new->Vars};
        our @_HEADER = ("Content-Type: text/html;");
        sub header {
            if (@_) {
                my $header = shift;
                $header =~ s{[\n\r]*$}{}g;
                push @_HEADER, $header;
            }
            else {
                print "$_\n" for @_HEADER;
                print "\n";
                @_HEADER = ();
            }
        };
    };
}

sub pmc_compile {
    my ( $class, $source, $extra ) = @_;
    $source =~ s{\?>\n?(.*?)<\?php}{conver_print($1)}egsm;
    $source =~ s{^(.*)<\?php}{conver_print($1)}egsm;
    $source =~ s{\?>\n?(.*)$}{conver_print($1)}egsm;
    return make_begin().$source;
}

1;
<html>
  <body>
<?php $name = "fbis" ?>
    僕の名前は<?php print $name; ?>です。
    年齢は<?php print $_REQUEST{'age'}; ?>歳です。
  </body>
</html>

そして実行時にPHP::Blockを指定します。

$ perl -MPHP::Block test.pl age=18
Content-Type: text/html;

<html>
  <body>
    僕の名前はfbisです。
    年齢は18歳です。
  </body>
</html>

はい、できました。ちゃんと動いてますね。もちろん閉じタグ省略しても動作するよ♪

Module::Compile使っているので初回のアクセス時のみコンパイルされるので実行時の負荷は殆ど無いと思ってもらって結構です。

ちなみにコンパイルされたコードは下記になります。

# Generated by PHP::Block 0 (Module::Compile 0.20) - do not edit!
################((( 32-bit Checksum Validator III )))################
#line 1
BEGIN { use 5.006; local (*F, $/); ($F = __FILE__) =~ s!c$!!; open(F)
or die "Cannot open $F: $!"; binmode(F, ':crlf'); if (unpack('%32N*',
$F=readline(*F)) != 0xD67E7A7B) { use Filter::Util::Call; my $f = $F;
filter_add(sub { filter_del(); 1 while &filter_read; $_ = $f; 1; })}}
#line 1

        use CGI;
        our %_REQUEST = %{CGI->new->Vars};
        our @_HEADER = ("Content-Type: text/html;");
        sub header {
            if (@_) {
                my $header = shift;
                $header =~ s{[\n\r]*$}{}g;
                push @_HEADER, $header;
            }
            else {
                print "$_\n" for @_HEADER;
                print "\n";
                @_HEADER = ();
            }
        };
    ;header() if @_HEADER;print '<html>
  <body>
'; $name = "fbis" ;header() if @_HEADER;print '    僕の名前は'; print $name; ;header() if @_HEADER;print 'です。
    年齢は'; print $_REQUEST{'age'}; ;header() if @_HEADER;print '歳です。
  </body>
</html>
';

ヘッダのところは正直テキトー実装なのでかなり微妙ですが、雰囲気だけでも味わって頂ければなと思って処理入れました。

という感じでソースフィルタを使うと何でもできちゃうのでソースフィルタはあんまり好きじゃないですというお話でした(表題と話変わってるじゃねーかというツッコミが聞こえてきそうです)

え?そんなこと言ったらPerlだってCの巨大なソースフィルタじゃんだって?





・・・。

















・・・・・・・・(ノ∀\*)。