limonadeを試してみる第一歩

今ちょうどPHPでの開発案件があって、CakePHPなどのWAFを使うほどの規模の案件じゃないんだけど、生PHPでプログラムを作成して無秩序なプログラムができるのは問題ですよねということで、いわゆるPHP製の小規模WAFを探してみた際に見つけたのがlimonade

公式サイトによるとRuby製のSinatraCampingなどからインスパイアされたフレームワークらしい。

以下、学習テストを兼ねて簡単に触ってみます。

githubからv0.4.6のzip版をダウンロード。他にもtgz版があったり、gitで落としてきたりが可能です。

公式サイトでは以降、

  • libフォルダを自分のプロジェクトに入てね。
  • 自分のアプリケーションのメインとなるphpファイルにrequire_once vendors/limonade.php (or require_once lib/limonade.php)と書き加えてね。
  • READMEを読んだり、examplesを試してみるなりして楽しんでね!

とあるので、

mkdir ~/public_html/limonade
cp -pr ~/sofadesign-limonade-85e77b4/lib ~/public_html/limonade

とコピー。で、さっそくlimonadeディレクトリ下にindex.phpを作ってみます。とりあえずありがちに、「Hello, World.」を表示するだけのプログラム。

<?php
require_once dirname( __FILE__ ) .'/lib/limonade.php';

dispatch('/', 'hello_world');
    function hello_world() {
        return 'Hello, World.';
    }

run();

として、http://localhost/limonade/にアクセスしてみるとHello, World.と表示されるはずです。お、結構簡単。

次に、プログラムとHTMLテンプレートを分離してみます。テンプレート用のファイルを納めるディレクトリviewsをlimonade直下に作成して、その中にtoppage.html.phpというテンプレートファイルを作ります。内容はこんな感じに。

<html>
<head>
<title>limonade Test</title>
</head>
<body>
<h1><?= $title ?></h1>
</body>
</html>

ちなみにh1要素内を「Hello, World.」と置き換える想定です。

次にindex.phpにも手を加えます。テンプレートがどこにあるかを指定しておかないといけないので。

<?php
require_once dirname( __FILE__ ) .'/lib/limonade.php';

option( 'root_dir',   dirname( __FILE__ )              );
option( 'views_dir',  option( 'root_dir' ) .'/views/'  );

dispatch('/', 'hello_world');
    function hello_world() {
        set( 'title', 'Hello, World.' );
        return html('toppage.html.php');
    }

run();

強調部分が、先ほどのindex.phpから変更・追加した箇所になります。最初の強調部分がテンプレートを収めるディレクトリの指定をしてる箇所。後半のset()はテンプレートに値を挿入するための関数で、html()がテンプレートを出力するための関数です。

で、http://localhost/limonade/にアクセスしてみると、想定どおりh1要素でHello, World.と表示されるます。

せっかくなので、URLに付加したパラメータを名前として扱うものとして、その人に「Hello」と呼ばせてみましょう。http://localhost/limonade/?MATSUOKAにアクセスするとHello, MATSUOKA!と表示させてみます。

まずはテンプレート。

<html>
<head>
<title>limonade Test</title>
</head>
<body>
<h1><?= h($title) ?></h1>
<p>Hello, <?= h($name) ?>.</p>
</body>
</html>

p要素のh($name)の部分にパラメータで渡された名前が表示される想定です。ちなみに以前のサンプルにはなかったh()ですが、Limonade – Public API Documentationによるとhtmlspecialcharsのエイリアスです。パラメータから値を受け取る以上、XSSが怖いですからね。こういうクセを付けておかないと。

次にindex.phpに更に手を加えます。今度はパラメータが渡されてくることを教えないといけないので。

<?php
require_once dirname( __FILE__ ) .'/lib/limonade.php';

option( 'root_dir',   dirname( __FILE__ )              );
option( 'views_dir',  option( 'root_dir' ) .'/views/'  );

dispatch('/:name', 'hello_world');
    function hello_world() {
        set( 'title', 'Hello, World.' 
        set_or_default('name', params('name'),'everyone');
        return html('toppage.html.php');
    }

run();

強調部分が、前回に追加した部分です。最初の:nameはlimonadeのrootディレクトリ以降にパラメータが追加して、それはnameっていう変数の値だよ、という指定です。

後半のset_or_default()は、

set_or_default('テンプレート上の変数名', '値', '値がない場合にセットする内容' )

という書式で、値がない場合で初期値をテンプレートに挿入するときに使う関数です。

これでhttp://localhost/limonade/?MATSUOKAにアクセスすると、

Hello, World.
Hello, MATSUOKA.

おおー。なお、http://localhost/limonade/なら

Hello, World.
Hello, everyone.

と出てくれます(ちなみにHello, World.の部分は共にh1要素で表示されます)。

limonadeは日本ではまだマイナーなのか、ほとんど公式サイトのREADMEPublic API documentationだけが頼りなので(共に英語)、敷居が高いところもあるんだけど、

  • Ruby製マイクロフレームワークの分野で認知度を上げてきているSinatraに近い思想で設計されている
  • READMEの内容やexamplesのソースコードを見渡せば、それなりに使い方が分かる学習コストの低さ
  • 英語ではあるものの、Public API documentationで情報が一通り公開されている

という面があって、高いと感じた敷居が、触ってみるとそうでもない印象を受けます。まだとっても基本的なところしか触ってないってこともあるんだろうけど。

生PHPで作成したプログラムは相当気をつけても、改良を重ねるうちにスパゲティーなコードになりがちなので、それを抑制するための手段としても一つの選択肢にできるんじゃないかなって感じでした。