O küresellerle kullanmayan PHP 5.2.x 'te kapakları taklit etmek mümkün mü?

4 Cevap php

O küresellerle kullanmayan PHP 5.2.x 'te kapakları taklit etmek mümkün mü? Ben kapatılması için ekstra parametre olarak istenen değişkenleri geçerdi ama bu sadece iyi uygulama gibi gelmiyor bir şekilde düşünebilirim.

Herhangi bir fikir?

4 Cevap

İlginç bir soru. I it's not possible at all söylüyorlar, ama bakalım istiyorum

Alıntı IBM - What's new in PHP5.3, Part 2

Bir kapatma birini veya fonksiyon çağrıldığında ulaşılabilir daha bağlı değişkenleri kendi ortamında, değerlendirildiğinde bir işlevdir.

ve ayrıca (vurgu benim)

Variables to be imported dış çevreden kapanma işlevi tanımının kullanılması fıkrasında belirtilmiştir. Varsayılan olarak, are passed by value, biz kapanma işlevi tanımı içinde geçti değerini güncelleştirmek olsaydı, bu dış değerini güncelleme olmaz yani.

O & use fıkrasında kullanarak bir kapatma ile referans değişkenleri bağlamak mümkün olsa kullanma global referans geçmek ve olurdu zaten bir sapma 5.3 varsayılan davranış.

$var = 'yes';
$fn  = create_function('', 'global $var; $var = "no";');
$fn();
echo $var; // outputs no

Siz örneğin, olsa değer bunu kullanmak için küresel değişkeni kopya olabilir

$var = 'yes';
$fn  = create_function('', 'global $var; $tmp = $var; $tmp = "no";');
$fn();
echo $var; // outputs yes

Fonksiyonu oluşturulduğunda (bağlı) değerlendirilir ama olmayacak (create_function kullanırken) ek olarak, küresel değişkenin değeri fonksiyon çalıştırıldığında

$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

Ayrıca önemli olan

Bir nesnenin içinde tanımlanmış zaman, kullanışlı bir şey kapatma bunu açıkça ithal etmek gerek kalmadan, $ bu değişken üzerinden nesneye tam erişim olmasıdır. *Though I think this was dropped in final PHP5.3

Bu global anahtar kelime ile imkansızdır ve ayrıca sadece kullanamazsınız $this. create_function ile fonksiyon gövdesini tanımlarken bir sınıftan bir özellik başvurmak için hiçbir yolu yoktur.

class A {

    protected $prop = 'it works';

    public function test()
    {
        $fn = create_function('', 'echo $this->prop;');
        return $fn;
    }
}

$a = new A;
$fn = $a->test();
$fn();

neden olur

Fatal error: Using $this when not in object context

To sum this up
While you can create a function importing a variable from the global scope, you cannot cannot create one using variables from another scope. And because you are technically not binding when using create_function but importing when the created function is executed, I'd like to argue this limitation makes the closure a lambda.


EDIT: Aşağıda Onno Marsman tarafından sunulan çözüm olsa oldukça iyi. Tamamen Kapaklar taklit etmez ama uygulama oldukça yakındır.

Benim çözüm: http://techblog.triptic.nl/simulating-closures-in-php-versions-prior-to-php-5-3/

Ancak ilk argüman olarak kapatılması için bir nesne içindeki değişkenler geçmek yok.

Bunu bazı özel durumlar vardır.

Eğer (referans değil) değerine göre bir değişken yakalamak gerekir ve değeri daha sonra yukarıda bir dizi, dize veya dizi (nesneler ve kaynaklar ve fonksiyonları gibi türleri başvuramaz) gibi basit bir değer türü, sadece can ise kullanarak fonksiyon tanımı içine yerleştirin var_export():

$var = array(1, 3);
$f = create_function('',
    '$var=' . var_export($var,true) . '; return $var;');

Eğer, fonksiyonun çağrıları karşısında kesilebilir durumunu korumak amacıyla referans değişkeni yakalamak için, ancak bir akümülatör oluşturmayı yarattığı orijinal kapsamında yansıyan değişiklikleri (örneğin olması gerekmez gerekiyor ama eğer değişiklikler toplamı) oluştururken kapsamında toplam değişkeni değiştirmek gerekmez, o zaman aynı şekilde yerleştirin, ancak statik bir değişken olarak yapabilirsiniz:

function make_accumulator($sum) {
    $f = create_function('$x',
        'static $var=' . var_export($var,true) . '; return $var += $x;');
    return $f;
}