pseudo block

27
eval() と create_function() の ミニレシピ 坂本昌彦 [email protected]

Upload: masahiko-sakamoto

Post on 02-Dec-2014

2.980 views

Category:

Technology


6 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Pseudo Block

eval() と create_function() のミニレシピ

坂本昌彦[email protected]

Page 2: Pseudo Block

自己紹介

● PHP, Java プログラマー● 404 Blog Not Found の影響で Perl に浮気中。● はてなダイアリ:● http://d.hatena.ne.jp/msakamoto-sf/● PukiWiki :● http://www.glamenv-septzen.net/pukiwiki/inde

x.php

Page 3: Pseudo Block

eval() って?

● 文字列を PHP コードとして評価する● http://jp.php.net/manual/ja/function.eval.php● サンプルは後で。● フレームワークなどで、動的な処理を行わせた

い場合に使われているらしい。●

● 但し、著者は現場では一度も使ったことがない。・・・ ( ; ´Д ` ) ウウッ…

Page 4: Pseudo Block

create_function() って?

● 匿名関数 ( ラムダ形式 ) を作成する● http://jp.php.net/manual/ja/function.create-fun

ction.php● array_map などで callback に使う関数を、一々定

義するのが面倒なときに使ったりするらしい。●

● 但し、これも著者は現場での使用経験は無し。・・・ ( ; ´Д ` ) ウウッ…

Page 5: Pseudo Block

eval() の例

eval01.php:<?php$a = “xyz”;eval('$b = “abc”; $c = \'123\'; $result = $a . $b . $c;');echo $result;?>

> php eval01.phpxyzabc123

>

Page 6: Pseudo Block

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)

>

Page 7: Pseudo Block

イケテナイ。

Page 8: Pseudo Block

エスケープが面倒くさい。

Page 9: Pseudo Block

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;

Page 10: Pseudo Block

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”;

Page 11: Pseudo Block

PHP でこうできれば・・・!!

<?php...eval { $a = ...}

$lambda = function($a, $b) {...return ...;

}

$result = $lambda(1, 2);...?>

Page 12: Pseudo Block

匿名関数については、挑戦者がいた。パッチも作成され、 ML でも議論された。

[PHP-DEV] PATCH: anonymous functions in PHP

http://marc.info/?l=php-internals&m=117426121911550&w=2

Page 13: Pseudo Block

忘れ去られたっぽい。

Σ (゚ д ゚ lll )

↓ML のスレッドも 2007 年 3 月一杯で終了。

↓PHP 5.3 Suggested Feature List にも無し。

(http://d.hatena.ne.jp/shimooka/20070910/1189359199)

が・・・。

Page 14: Pseudo Block

駄目元で PHP のソースを見る。

訳わかんねぇ

。゚ ( ゚ ´Д `゚ ) ゚。

yacc? lex? ZTS ってなーに?

“ 小泉守義の PHP ソースコードウォッチ”https://www.codeblog.org/blog/moriyoshi/

“ZeroMemory”http://ido.nu/kuma/

でも読んで勉強してみようか知らん・・・。

Page 15: Pseudo Block

手っ取り早く PHP の現状の文法の範囲内で、何とか抜け道を見つけ、エスケープメントの縛りから

逃れる方法は無いのか・・・。

(ヒアドキュメントも目的を達し得ない)

以上が前置き。

Page 16: Pseudo Block

とにかく、

PHP のコードが「そのまま」べた書きできればイイ!!

それが最優先!!

とにかくエスケープメントから逃げたい!!!

Page 17: Pseudo Block

あった。

電波受信成功!!!

キタ─wwヘ√レvv~ ( ゚∀゚ )─wwヘ√レvv~─ !!  

Page 18: Pseudo Block

出力バッファリングを使え!!

● PHP では” <?php” - “?>” の「外」はそのまま出力される。 (HTML埋め込み型言語だから )

● つまり、「外」では何を書こうがエスケープの心配は要らない。

● →わざと「外」に PHP のコードを書き、それを ob_*() で取得すればどうにかできるのでは?

Page 19: Pseudo Block

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 コードを入れる。→エスケープの必要が無くなる。

Page 20: Pseudo Block

Pseudo_Block

「疑似」コードブロックをサポート

http://xhwlay.sourceforge.net/Pseudo_Block/

・ Apache Software License 2・ PHP4/5

・ PEARパッケージ

Page 21: Pseudo Block

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" ?>

ここが疑似ブロック

Page 22: Pseudo Block

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))?>

ここが疑似ブロック

Page 23: Pseudo Block

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;}?>

ここが疑似ブロック

Page 24: Pseudo Block

ご意見募集中。

● http://sourceforge.net/projects/xhwlay/–↑の Tracker 、あるいは msakamoto-sf のはて

なダイアリへ。● コードブロック中でクラスや関数を定義したり、外部と参照をやりとりし始めるとヤバイかも・・・。– →tokenizer を通して conflict なコードは除去す

る?● あまりいぢめないで下さい。 (*´д ` *)

–泣いちゃいます。– PHP の文法としてサポートする議論のとば口

になれば・・・。

Page 25: Pseudo Block

で。

・・・使うのか?

「別に、 eval() とか匿名関数とか使わなくても Webは作れるよね。」

「何でもかんでも {Perl|Ruby|JavaScript|Python}マンセーっておかしくね?」

・・・ビミョー・・・。

Page 26: Pseudo Block

おしまい。

( ゚ Д ゚ )y─┛~~

ウマー。

Page 27: Pseudo Block

おまけ:無責任な Proposal

C のソースを埋め込み、 PHP の Extension として実行時にコンパイル ,dl() しちゃうとかどうだろう?

(CPAN の Inlineモジュールみたく )

埋め込まれたテキストのハッシュ値を取っておいて上手く cache, expire の仕掛けを作れば・・・?

Pseudo_{C|Java|Ruby|Perl|Python|Lisp|e.t.c}