LoginSignup
12

More than 5 years have passed since last update.

pharでWebアプリを作ってみた

Last updated at Posted at 2013-10-11

pharを使ってみる / pharアーカイブを作成 / pharでWebアプリを作ってみた

前回はpharアーカイブをライブラリとして使用しましたが、実はpharアーカイブだけで完全な動作をするPHPプログラムを作成可能です。
この利用法、Phar::webPhar()あたりをよく読めば書いてあるのですが、物凄く便利っぽい機能にもかかわらず何故か何処にもこれを使ってみたという人が見あたらない不思議。

まあとりあえずでっちあげてみたのがこちら

中身は大昔に作った超適当なフォームなのでソースは絶対に参考にしてはいけませんが、以下の3ファイルが入っています。

input.php

<?php
    //初期化
        header("Content-Type: text/html; charset=UTF-8");
        error_reporting(E_ALL ^ E_NOTICE);
        $shimei = '';
        $mail   = '';
        $sex    = '';

    //引数を確認
    if($_REQUEST['comp']){
        //引数があれば入力チェック
            $shimei = $_REQUEST['shimei'];
            $mail   = $_REQUEST['mail'];
            $sex    = $_REQUEST['sex'];
            $error_message = '';
            if(empty($shimei)){    $error_message.= "氏名が入力されていません<br />";}
            if(empty($mail)){      $error_message.= "メアドが入力されていません<br />";}
            if($sex!=1 && $sex!=2){$error_message.= "性別が入力されていません<br />";}
            if($error_message){
                //エラーがあれば戻る
                require_once('phar://index.phar/input.tpl');
                exit();
            }else{
                //エラーがなければ保存して終了
                file_put_contents('form.txt', $_REQUEST, FILE_APPEND);
                require_once('phar://index.phar/comp.tpl');
                exit();
            }
    }else{
        //引数が無ければ入力画面
        require_once('phar://index.phar/input.tpl');
        exit();
    }

input.tpl

    <?php if($error_message){print('<div style="color:red;">'.$error_message.'</div>');} ?>
    <form method="POST" action="<?php print(htmlspecialchars($_SERVER['PHP_SELF'])); ?>">
       氏名:<input type="text" name="shimei" maxlength="64" value="<?php print(htmlspecialchars($shimei)); ?>"><br />
       メアド:<input type="text" name="mail" maxlength="64" value="<?php print(htmlspecialchars($mail)); ?>"><br />
       性別:
       <input type="radio" name="sex" value="1"<?php if($sex==1){print(" checked");} ?>>男 
       <input type="radio" name="sex" value="2"<?php if($sex==2){print(" checked");} ?>><br />
       <input type="submit" name="comp" value=" 登録 ">
    </form>

comp.tpl

    投稿を受け付けました<br />
    ご協力ありがとうございました

適当にサーバに置いてブラウザからindex.pharを呼び出すと、普通にフォームが動作します。
ファイルをひとつぽんとサーバ上に置くだけでフォームが完成という、配布などに非常に便利な機能となっています。
まあ、この例で作ったフォーム程度なら手動で1ファイルにした方が早いんですが、というかわざわざpharにする必要全くないんですが、たとえばファイルが2200個あるMantisがなんと今ならたった1ファイル、とかになったらずいぶん利用のハードルが下がったりするかもしれません。

ちなみにこのpharファイルの作成方法は以下のようになっています。

<?php
    $phar = new Phar('index.phar', 0);

    $phar->addFile('input.php');
    $phar->addFile('input.tpl');
    $phar->addFile('comp.tpl');
    $phar->setStub('<?php
         Phar::webPhar("index.phar", "input.php" );
         __HALT_COMPILER(); ?>');

Phar::webPhar()が、pharファイルを直接呼び出しで動作できるようにしてくれるフロントコントローラです。
このメソッドを呼んでおくと$_REQUESTとかの処理を適切に割り振って、pharアーカイブ内でそのまま使用できるようにしてくれます。
第二引数の'input.php'を指定すると、index.pharが呼ばれたときにアーカイブ内の'input.php'が実行されるようになります。

このPhar::webPhar()をセットしているPhar::setStub()はローダスタブをpharアーカイブにセットするメソッドです。
で、そのローダスタブって何なのかというと、今回のようにpharファイルを直接呼び出した、あるいはrequire_once('index.phar')と直接pharアーカイブがインクルードされた際に自動的に実行される部分です。
'phar://index.phar/input.tpl'とpharアーカイブ内の一部ファイルだけを呼び出した際には実行されません。
デフォルトだと、phar未対応のPHPでpharをエミュレートする機能を追加し、その後自動的にアーカイブ内の'index.php'を実行してくれるようです。

なおpharが入っていれば、zipやtarのままPHPとして動作させるなんてこともできてしまうようです。
そこらへんは調べてないのでよくわかりません。

__HALT_COMPILER()なんて初めて使ったよ。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12