Globalsを使用しないPHP 5.2.xで閉鎖をシミュレートすることは可能ですか?
-
18-09-2019 - |
質問
Globalsを使用しないPHP 5.2.xで閉鎖をシミュレートすることは可能ですか?目的の変数をクロージャーの追加パラメーターとして渡す方法を考えることができましたが、それはベストプラクティスのようには感じられません。
何か案は?
解決
興味深い質問。私は言います まったく不可能です, 、でも見てみましょう
閉鎖とは、独自の環境で評価される関数であり、関数が呼び出されたときにアクセスできる1つ以上のバウンド変数があります。
そしてさらに(私の強調)
インポートする変数 外部から環境は、閉鎖関数定義の使用節で指定されています。デフォルトでは、彼ら 価値によって渡されます, 、つまり、閉鎖関数定義内で渡された値を更新する場合、外部値は更新されません。
使用 global
参照によって通過しますが、使用して閉鎖とともに参照によって変数をバインドすることは可能ですが &
の中に use
句、それはすでに5.3デフォルトの動作からの逸脱です。
$var = 'yes';
$fn = create_function('', 'global $var; $var = "no";');
$fn();
echo $var; // outputs no
グローバル変数をコピーして、値で使用することができます。
$var = 'yes';
$fn = create_function('', 'global $var; $tmp = $var; $tmp = "no";');
$fn();
echo $var; // outputs yes
さらに、グローバル変数の値(使用する場合 create_function
)関数が作成されたときと機能が実行されたときに評価されません(バウンド)
$var = 'yes';
$fn = create_function('', 'global $var; $tmp = $var; return $tmp;');
$var = 'maybe';
echo $fn(); // outputs maybe
$var = 'yes';
$fn = function() use ($var) { return $var; };
$var = 'maybe';
echo $fn(); // outputs yes
また、重要です
オブジェクト内で定義されている場合、1つの便利なことは、閉鎖がこの変数を介してオブジェクトに完全にアクセスできることです。明示的にインポートする必要はありません。 *これは最終的なphp5.3で削除されたと思いますが
これは不可能です global
キーワードと使用することもできません $this
. 。関数本文をで定義するときにクラスからプロパティを参照する方法はありません create_function
.
class A {
protected $prop = 'it works';
public function test()
{
$fn = create_function('', 'echo $this->prop;');
return $fn;
}
}
$a = new A;
$fn = $a->test();
$fn();
結果として生じます
Fatal error: Using $this when not in object context
これを要約します
グローバルスコープから変数をインポートする関数を作成できますが、別のスコープから変数を使用して作成することはできません。そして、あなたは技術的には使用するときに拘束されていないからです create_function
しかし、作成された関数が実行されたときにインポートすると、私は議論したいと思います この制限により、閉鎖がラムダになります.
編集:以下のOnno Marsmanが提供するソリューションはかなりまともです。閉鎖を完全にシミュレートするわけではありませんが、実装はかなり近いです。
他のヒント
私の解決策: http://techblog.triptic.nl/simulating-closures-in-php-versions-php-5-3/
ただし、オブジェクト内の変数を最初の引数として閉鎖に渡します。
カリーのようなことを意味しますか http://en.wikipedia.org/wiki/currying
それで http://zaemis.blogspot.com/2009/06/currying-in-php.html
そうでない場合は、気にしないでください。 :-)
あなたがそれをすることができるいくつかの特別なケースがあります。
値(参照ではない)で変数をキャプチャする必要がある場合、値は上記の数字、文字列、または配列のような単純な値タイプ(オブジェクトやリソースや関数などの参照タイプではありません)である場合、単純にできます。使用して関数定義に挿入します var_export()
:
$var = array(1, 3);
$f = create_function('',
'$var=' . var_export($var,true) . '; return $var;');
関数の呼び出し全体で可変状態を維持するために参照によって変数をキャプチャする必要がありますが、作成された元のスコープに変更を反映する必要はありません(例えば、アキュムレータを作成するが、の変更は合計は、作成スコープの合計変数を変更する必要はありません)、同様に挿入できますが、静的変数として挿入できます。
function make_accumulator($sum) {
$f = create_function('$x',
'static $var=' . var_export($var,true) . '; return $var += $x;');
return $f;
}