web-dev-qa-db-ja.com

PHP pre 5.4.0の匿名関数で `$ this`を使用する

PHP手動状態

PHP 5.4.0の前に匿名関数から$thisを使用することはできません

匿名関数ページ で。しかし、$thisを変数に割り当て、関数定義でuseステートメントに変数を渡すことで、それを機能させることができることがわかりました。

$CI = $this;
$callback = function () use ($CI) {
    $CI->public_method();
};

これは良い習慣ですか?
PHP 5.3?を使用して、匿名関数内で$thisにアクセスするより良い方法はありますか?

85
steampowered

保護されたメソッドまたはプライベートメソッドを呼び出そうとすると失敗します。その方法で使用すると、外部からの呼び出しとしてカウントされるためです。私が知っている限り、5.3でこれを回避する方法はありませんが、PHP 5.4、それは箱から出して、期待どおりに動作します:

class Hello {

    private $message = "Hello world\n";

    public function createClosure() {
        return function() {
            echo $this->message;
        };
    }

}
$hello = new Hello();
$helloPrinter = $hello->createClosure();
$helloPrinter(); // outputs "Hello world"

さらに、匿名関数(クロージャの再バインド)のために、実行時に$ thisが指すものを変更できます。

class Hello {

    private $message = "Hello world\n";

    public function createClosure() {
        return function() {
            echo $this->message;
        };
    }

}

class Bye {

    private $message = "Bye world\n";

}

$hello = new Hello();
$helloPrinter = $hello->createClosure();

$bye = new Bye();
$byePrinter = $helloPrinter->bindTo($bye, $bye);
$byePrinter(); // outputs "Bye world"

事実上、anonymus関数には bindTo()メソッド があり、最初のパラメーターを使用して$ thisが指すものを指定し、2番目のパラメーターを使用して可視性レベルbe。 2番目のパラメーターを省略すると、可視性は「外部」からの呼び出しのようになります。アクセスできるのはパブリックプロパティのみです。また、bindToの動作方法に注意してください。元の関数は変更されません。新しい関数が返されます

65
K. Norbert

参照によってオブジェクトを渡す際に、常にPHPに依存しないでください。参照自体を割り当てる場合、動作はほとんどのOO言語と同じではありません元のポインターが変更される場所。

あなたの例:

$CI = $this;
$callback = function () use ($CI) {
$CI->public_method();
};

する必要があります:

$CI = $this;
$callback = function () use (&$CI) {
$CI->public_method();
};

参照 "&"と$ CIは、最後の呼び出しが行われた後に割り当てる必要があります。そうでない場合は、PHP参照へのアクセスは常にアクセスと同じではありません元のクラス-それが理にかなっている場合。

http://php.net/manual/en/language.references.pass.php

6

それが行われた通常の方法です。
b.t.w、&オブジェクトはrefで渡されるため、これがなくても動作するはずです。

参照渡しするのが正しい方法であれば、それは大丈夫のようです。 PHP 5を使用している場合、&記号の前に$thisに関係なく、常に参照渡しされます。

1
fire

これは大丈夫です。これもできると思うはずです:

$CI = $this;

...オブジェクトを含む割り当ては、オブジェクト全体ではなく、常に参照をコピーするためです。

1
halfer