Upload
masahiko-sakamoto
View
2.980
Download
6
Embed Size (px)
DESCRIPTION
Citation preview
eval() と create_function() のミニレシピ
自己紹介
● PHP, Java プログラマー● 404 Blog Not Found の影響で Perl に浮気中。● はてなダイアリ:● http://d.hatena.ne.jp/msakamoto-sf/● PukiWiki :● http://www.glamenv-septzen.net/pukiwiki/inde
x.php
eval() って?
● 文字列を PHP コードとして評価する● http://jp.php.net/manual/ja/function.eval.php● サンプルは後で。● フレームワークなどで、動的な処理を行わせた
い場合に使われているらしい。●
● 但し、著者は現場では一度も使ったことがない。・・・ ( ; ´Д ` ) ウウッ…
create_function() って?
● 匿名関数 ( ラムダ形式 ) を作成する● http://jp.php.net/manual/ja/function.create-fun
ction.php● array_map などで callback に使う関数を、一々定
義するのが面倒なときに使ったりするらしい。●
● 但し、これも著者は現場での使用経験は無し。・・・ ( ; ´Д ` ) ウウッ…
eval() の例
eval01.php:<?php$a = “xyz”;eval('$b = “abc”; $c = \'123\'; $result = $a . $b . $c;');echo $result;?>
> php eval01.phpxyzabc123
>
create_function() の例
create_function01.php:<?php$lambda = create_function('$a, $b', 'static $c; $c++; return $a + $b + $c;');echo $lambda(1, 2) . PHP_EOL;echo $lambda(3, 4) . PHP_EOL;?>
> php create_function01.php4 // 1 + 2 + 1 ($c)9 // 3 + 4 + 2 ($c)
>
イケテナイ。
エスケープが面倒くさい。
Perl なら・・・ !! (eval の場合 )
#!/usr/bin/perluse strict;use warnings;
my $a = “xyz”;my $result;eval { my $b = “abc”; my $c = '123'; $result = $a . $b . $c;};print $result;
Perl なら・・・ !! ( 匿名関数の場合 )
#!/usr/bin/perluse strict;use warnings;
my $c = 0;my $lambda = sub() {
my ($a, $b) = @_;$c++;return $a + $b + $c;
};print $lambda->(1, 2), “\n”;print $lambda->(3, 4), “\n”;
PHP でこうできれば・・・!!
<?php...eval { $a = ...}
$lambda = function($a, $b) {...return ...;
}
$result = $lambda(1, 2);...?>
匿名関数については、挑戦者がいた。パッチも作成され、 ML でも議論された。
[PHP-DEV] PATCH: anonymous functions in PHP
http://marc.info/?l=php-internals&m=117426121911550&w=2
忘れ去られたっぽい。
Σ (゚ д ゚ lll )
↓ML のスレッドも 2007 年 3 月一杯で終了。
↓PHP 5.3 Suggested Feature List にも無し。
(http://d.hatena.ne.jp/shimooka/20070910/1189359199)
が・・・。
駄目元で PHP のソースを見る。
訳わかんねぇ
。゚ ( ゚ ´Д `゚ ) ゚。
yacc? lex? ZTS ってなーに?
“ 小泉守義の PHP ソースコードウォッチ”https://www.codeblog.org/blog/moriyoshi/
“ZeroMemory”http://ido.nu/kuma/
でも読んで勉強してみようか知らん・・・。
手っ取り早く PHP の現状の文法の範囲内で、何とか抜け道を見つけ、エスケープメントの縛りから
逃れる方法は無いのか・・・。
(ヒアドキュメントも目的を達し得ない)
以上が前置き。
とにかく、
PHP のコードが「そのまま」べた書きできればイイ!!
それが最優先!!
とにかくエスケープメントから逃げたい!!!
あった。
電波受信成功!!!
キタ─wwヘ√レvv~ ( ゚∀゚ )─wwヘ√レvv~─ !!
出力バッファリングを使え!!
● PHP では” <?php” - “?>” の「外」はそのまま出力される。 (HTML埋め込み型言語だから )
● つまり、「外」では何を書こうがエスケープの心配は要らない。
● →わざと「外」に PHP のコードを書き、それを ob_*() で取得すればどうにかできるのでは?
Proof of Concept
hoge1.php : <?php$i = 0;ob_start();?>global $i;$i++;return "Hello, World! + [$i]";<?php$_code = ob_get_contents();ob_end_clean();
echo eval($_code)."\n"; // out : Hello, World! + [1]echo eval($_code)."\n"; // out : Hello, World! + [2]echo eval($_code)."\n"; // out : Hello, World! + [3]?>
普通なら HTML が入る箇所に、わざと PHP コードを入れる。→エスケープの必要が無くなる。
Pseudo_Block
「疑似」コードブロックをサポート
http://xhwlay.sourceforge.net/Pseudo_Block/
・ Apache Software License 2・ PHP4/5
・ PEARパッケージ
Usage 1 : Pseudo_Eval
<?phprequire_once('Pseudo/Eval.php');$pe =& new Pseudo_Eval();$pe->start(); // start pseudo block?>$a = "ABC.";$b = 'xyz.';return $a . $b . $c;<?php$pe->end(); // end pseudo block $val = 30;$pe->bind('c', $val); // eval() された時のコードブロックに、変数をコピーする。
$result = $pe->act();echo $result . PHP_EOL;// out : "ABC.xyz.30" ?>
ここが疑似ブロック
Usage 2 : Pseudo_Lambda
<?phprequire_once('Pseudo/Lambda.php');$pl =& new Pseudo_Lambda('$a, $b');$pl->start(); // start pseudo block?>static $c = 0; $c++;return $a + $b + $c + $d;<?php$pl->end(); // end pseudo block
$val = 30;$pl->bind('d', $val); // 匿名関数のスコープに外部変数をコピーする。
$func = $pl->create();echo $func(1, 2) . PHP_EOL; // out : 34 (1 + 2 + 1($c) + 30($d))echo $func(3, 4) . PHP_EOL; // out : 39 (3 + 4 + 2($c) + 30($d))?>
ここが疑似ブロック
Usage 3 : Pseudo_Block
<?phprequire_once('Pseudo/Block.php');$pb =& new Pseudo_Block();$pb->start(); // start pseudo block?>Name|Age|HobbiesMasahiko|26|ProgrammingSakamoto|62|CookingFengJing|-|Walking<?php$pb->end(); // end pseudo block
$text = $pb->getText(); // 疑似ブロック内のテキストを取得
$rows = array_map('trim', explode("\n", $text));foreach($rows as $row) { echo strtr($row, "|", ",") . PHP_EOL;}?>
ここが疑似ブロック
ご意見募集中。
● http://sourceforge.net/projects/xhwlay/–↑の Tracker 、あるいは msakamoto-sf のはて
なダイアリへ。● コードブロック中でクラスや関数を定義したり、外部と参照をやりとりし始めるとヤバイかも・・・。– →tokenizer を通して conflict なコードは除去す
る?● あまりいぢめないで下さい。 (*´д ` *)
–泣いちゃいます。– PHP の文法としてサポートする議論のとば口
になれば・・・。
で。
・・・使うのか?
↓
「別に、 eval() とか匿名関数とか使わなくても Webは作れるよね。」
「何でもかんでも {Perl|Ruby|JavaScript|Python}マンセーっておかしくね?」
・・・ビミョー・・・。
おしまい。
( ゚ Д ゚ )y─┛~~
ウマー。
おまけ:無責任な Proposal
C のソースを埋め込み、 PHP の Extension として実行時にコンパイル ,dl() しちゃうとかどうだろう?
(CPAN の Inlineモジュールみたく )
埋め込まれたテキストのハッシュ値を取っておいて上手く cache, expire の仕掛けを作れば・・・?
Pseudo_{C|Java|Ruby|Perl|Python|Lisp|e.t.c}