web-dev-qa-db-fra.com

Utiliser `$ this` dans une fonction anonyme dans PHP pre 5.4.0

Les états du manuel PHP

Il n'est pas possible d'utiliser $this à partir d'une fonction anonyme avant PHP 5.4.0

sur la page des fonctions anonymes . Mais j'ai trouvé que je pouvais le faire fonctionner en affectant $this à une variable et en passant la variable à une instruction use à la définition de la fonction.

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

Est-ce une bonne pratique?
Existe-t-il un meilleur moyen d'accéder à $this à l'intérieur d'une fonction anonyme utilisant PHP 5.3?

85
steampowered

Il échouera lorsque vous tenterez d'appeler une méthode protégée ou privée dessus, car son utilisation de cette façon compte comme un appel de l'extérieur. Il n'y a aucun moyen de contourner cela dans 5.3 pour autant que je sache, mais venez PHP 5.4, cela fonctionnera comme prévu, hors de la boîte:

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"

Encore plus, vous pourrez changer ce à quoi cela pointe au moment de l'exécution, pour les fonctions anonymus (reliure de fermeture):

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"

En effet, les fonctions anonymus auront une méthode bindTo () , où le premier paramètre peut être utilisé pour spécifier vers quoi cela pointe, et le second paramètre contrôle ce qui devrait le niveau de visibilité soit . Si vous omettez le deuxième paramètre, la visibilité sera comme appeler de "l'extérieur", par exemple. seules les propriétés publiques sont accessibles. Notez également le fonctionnement de bindTo, il ne modifie pas la fonction d'origine, il en retourne une nouvelle .

65
K. Norbert

Ne comptez pas toujours sur PHP pour passer des objets par référence, lorsque vous assignez une référence elle-même, le comportement n'est pas le même que dans la plupart des langages OO où le pointeur d'origine est modifié.

votre exemple:

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

devrait être:

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

REMARQUE LA RÉFÉRENCE "&" et $ CI doivent être attribués après les derniers appels, sinon vous pourriez avoir une sortie imprévisible, en PHP accéder à une référence n'est pas toujours la même chose qu'accéder à la classe d'origine - si cela a du sens.

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

6
Christof Coetzee

C'est la façon normale de procéder.
b.t.w, essayez de supprimer le & cela devrait fonctionner sans cela, car les objets passent par ref de toute façon.

5

Cela semble correct si vous passez par référence, c'est la bonne façon de le faire. Si vous utilisez PHP 5, vous n'avez pas besoin du & symbole avant $this car il passera toujours par référence malgré tout.

1
fire

C'est bon. Je devrais penser que vous pourriez aussi faire ça:

$CI = $this;

... car les affectations impliquant des objets copient toujours les références, pas les objets entiers.

1
halfer