Utiliser `$ this` dans une fonction anonyme dans PHP antérieur à 5.4.0

86

Le manuel PHP indique

Il n'est pas possible d'utiliser $thisune fonction anonyme avant PHP 5.4.0

sur la page des fonctions anonymes . Mais j'ai trouvé que je peux le faire fonctionner en attribuant $thisà une variable et en passant la variable à une useinstruction à 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 à l' $thisintérieur d'une fonction anonyme en utilisant PHP 5.3?

à vapeur
la source
1
Juste une convention de forum mineure - il est généralement préférable d'accepter une réponse que de modifier une question pour refléter votre réponse préférée. C'est principalement pour que les réponses aient toujours un sens à perpétuité, mais aussi bien sûr pour donner le crédit d'une réponse correcte.
halfer
4
Méfiez-vous de cela $CI = $this;et $CI =& $this; ne sont pas réellement identiques. Peut-être pour vos besoins, mais ce n'est pas la même chose. Essayez $CI = 'bla'; var_dump($this);avec les deux versions pour voir la différence.
Rudie
1
@Rudie J'ajoute la documentation pour votre commentaire
Steampowered
@steampowered Il y a un bon exemple / article en ligne quelque part à ce sujet, mais je ne l'ai pas trouvé =) Désolé. Essayez-le si vous ne voyez pas la différence. C'est évident alors.
Rudie

Réponses:

67

Il échouera lorsque vous essayez d'appeler une méthode protégée ou privée dessus, car l'utiliser de cette façon compte comme un appel de l'extérieur. Il n'y a aucun moyen de contourner ce problème dans 5.3 pour autant que je sache, mais avec 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"

De plus, vous pourrez changer ce à quoi $ this 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 $ this pointe, et le second paramètre contrôle quel devrait être le niveau de visibilité . Si vous omettez le deuxième paramètre, la visibilité sera comme un appel 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 renvoie une nouvelle .

K. Norbert
la source
1
Marquer votre réponse correcte, mais juste pour clarifier pour les autres lecteurs: la convention utilisée dans la question fonctionnera pour les méthodes publiques utilisant l'objet qui fait référence $this.
vapeur
5
Les méthodes non publiques sont accessibles à l'aide de la réflexion. Inefficace et un peu mauvais, mais ça marche.
sortie le
7

Ne comptez pas toujours sur PHP pour passer des objets par référence, lorsque vous attribuez 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();
};

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

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

Christof Coetzee
la source
6

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

Itay Moav -Malimovka
la source
1

Cela semble correct si votre passage par référence est la bonne façon de le faire. Si vous utilisez PHP 5, vous n'avez pas besoin du &symbole auparavant $thiscar il passera toujours par référence de toute façon.

Feu
la source
2
L'OP doit utiliser 5.3 ou supérieur, car 4.x ne supportait pas les fonctions anonymes :-)
halfer
1

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

$CI = $this;

... puisque les affectations impliquant des objets copieront toujours des références, pas des objets entiers.

licol
la source