5.4.0より前のPHPの無名関数で `$ this`を使用する


86

PHPマニュアルには

使用できません $thisPHP5.4.0より前の無名関数

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

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

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


1
ちょっとしたフォーラムの慣習です。通常は、質問を編集して好みの回答を反映するよりも、回答を受け入れる方がよいでしょう。これは主に、応答が永続的に意味をなすようにするためですが、もちろん正解を評価するためでもあります。
2011

4
それに注意してください、$CI = $this;そして実際には同一で$CI =& $this; はありません。たぶんあなたの目的のためですが、それらは同じではありません。$CI = 'bla'; var_dump($this);両方のバージョンで試して、違いを確認してください。
ルディ2011

1
@Rudieコメントのドキュメントを追加します
Steampowered

@steampoweredこれについての良い例/記事がオンラインのどこかにありますが、見つかりませんでした=)申し訳ありません。違いがわからない場合は、試してみてください。その時は明らかです。
ルディ2011

回答:


67

保護されたメソッドまたはプライベートメソッドを呼び出そうとすると失敗します。そのように使用すると、外部からの呼び出しとしてカウントされるためです。私の知る限り、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"

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


1
正解をマークしますが、他の読者のために明確にするためです。質問で使用されている規則は、参照しているオブジェクトを使用するパブリックメソッドで機能します$this
2011

5
非公開メソッドには、リフレクションを使用してアクセスできます。非効率的で少し邪悪ですが、それは機能します。
outis 2012

7

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

あなたの例:

$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

それはそれが行われた通常の方法です。
ところで、&オブジェクトはrefを通過するので、これがなくても機能するはずです。


1

参照による通過がそれを行う正しい方法である場合、それは問題ないようです。PHP 5を使用している場合は、&シンボル$thisは常に参照によって渡されるため、以前はシンボルは必要ありません。


2
4.xは無名関数をサポートしていなかったため、OPは5.3以降を使用している必要があります:-)
2011

1

これで結構です。私はあなたがこれもできると思うべきです:

$CI = $this;

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.