Appel privé de méthodes et de propriétés privées à partir de l'extérieur d'une classe en PHP
Je veux un accès privé à des méthodes et des variables à partir de l'extérieur de l'classes dans de très rares cas particuliers.
J'ai vu que ce n'est pas être possible, bien que l'introspection est utilisé.
Le cas spécifique est la suivante:
Je voudrais avoir quelque chose comme ceci:
class Console
{
final public static function run() {
while (TRUE != FALSE) {
echo "\n> ";
$command = trim(fgets(STDIN));
switch ($command) {
case 'exit':
case 'q':
case 'quit':
echo "OK+\n";
return;
default:
ob_start();
eval($command);
$out = ob_get_contents();
ob_end_clean();
print("Command: $command");
print("Output:\n$out");
break;
}
}
}
}
Cette méthode doit pouvoir être injecté dans le code comme ceci:
Class Demo
{
private $a;
final public function myMethod()
{
//some code
Console::run();
//some other code
}
final public function myPublicMethod()
{
return "I can run through eval()";
}
private function myPrivateMethod()
{
return "I cannot run through eval()";
}
}
(c'est juste une simplification. le réel passe par un support et mettre en œuvre un tas de choses...)
Donc...
Si vous instancier la classe Démo et que vous appelez $demo->myMethod(), vous aurez une console: la console peuvent accéder à la première méthode d'écriture d'une commande comme:
> $this->myPublicMethod();
Mais vous ne pouvez pas exécuter avec succès la seconde:
> $this->myPrivateMethod();
Faire l'un de vous à une idée, ou s'il existe une bibliothèque PHP qui vous permet de le faire?
Merci beaucoup!
Pour info
while(true)
ou for(;;)
sont légèrement plus succincte et des méthodes communes de la boucle jusqu'à ce qu'un explicite break
ou return
est rencontré.Comme je l'ai dit précédemment, j'ai fait ça plus comme un POC que d'un exemple réel. La Console réelle de classe a, plus ou moins environ 1k lignes et s'étend de quelques autres par la composition. La maintenabilité du code n'est pas un problème car il sera utilisé comme un composant isolé à l'extérieur du principal projet sur lequel nous travaillons, donc ce n'est pas seulement "une fonction forcé dans une classe", mais un extrait d'une classe qui ne sera pas posté ici, pour éviter que les gens s'énerve. 🙂 @meagar: héhé, j'ai fait le while(TRUE != FALSE) comme une blague, depuis PHP valide FALSE != 0 comme FAUX. merci quand même 😉
et, j'ai oublié de commenter, je n'ai jamais écrit un retour, ni de continuer à l'intérieur d'une fonction, sauf si un PoC. Je pense n'est pas une bonne pratique et des choses comme cela pourrait perturber la lisibilité du code.
OriginalL'auteur Pablo López Torres | 2010-04-29
Vous devez vous connecter pour publier un commentaire.
Juste faire de la méthode public. Mais si vous voulez obtenir difficile, vous pouvez essayer ceci (PHP 5.3):
Hm, j'ai aussi de finale de la classe LockedGate { private function __construct() {} ... } et il ne semble pas fonctionner. Je me demande si la "finale" empêche l'accessibilité d'être changé.
Ahh, je pense que mon problème peut avoir été que c'était une classe statique. Cela a fonctionné pour moi
$method = $reflector->getMethod('myStaticPrivate');
$method->setAccessible(true);
$method->invoke(NULL);
Avec PHP 5.3.22 sur la coque
$ php -a
échoue avec:PHP Fatal error: Call to private method LockedGate::open() from context '' in php shell code on line 1
PHP Stack trace:
PHP 1. {main}() php shell code:0
Fatal error: Call to private method LockedGate::open() from context '' in php shell code on line 1
Call Stack:
5.3208 641904 1. {main}() php shell code:0
Cela n'a jamais fonctionné, comme vous pouvez le voir ici: 3v4l.org/mhjAQ
OriginalL'auteur webbiedave
EDIT:
Mis à jour pour inclure des exemples de privé appels de fonction avec des paramètres.
De PHP 5.4, vous pouvez utiliser le prédéfinies
Closure
classe de lier une méthode/propriété d'une classe à un delta fonctions qui a accès aux membres privés.La Fermeture de classe
Par exemple, nous avons une classe avec une variable privée et nous voulons y accéder en dehors de la classe:
PHP 5.4+
De PHP 7, vous pouvez utiliser la nouvelle
Closure::call
méthode, de lier n'importe quelle méthode/propriété d'un obect à une fonction de rappel, même pour les membres privés:PHP 7+
merci. Je viens de réaliser que la réponse n'est donc pas un appel de fonction avec des paramètres, mais seulement des variables privées! Mise à jour et ajout d'exemples privé appels de fonctions pour PHP 5.4+ et PHP 7+.
Cela fonctionne, ce qui est génial! Mais vous pensez que c'est la meilleure pratique comme ils l'ont probablement fait privé pour une raison?
Bien sûr, il est PAS les meilleures pratiques. Ce qui doit être évité si possible, il peut être utilisé quand on veut avoir accès à des privés memeber, et 1) nous ne voulons pas modifier le source de la classe de fichiers (peut-être un prêt lib qui va casser après la mise à jour) et 2) si c'est un de vos projets;s classes, puis modifiez la propriété/fonction publique, ou de faire une autre fonction pour récupérer ce membre privé.
oui c'est la situation pour moi, je n'ai pas vraiment envie de modifier la bibliothèque car il va se casser sur la mise à jour, merci pour la réponse.
OriginalL'auteur Christos Lytras
La première question à vous poser est, si vous avez besoin d'y accéder à partir de l'extérieur de la classe, pourquoi avez-vous déclaré en privé? Si ce n'est pas votre code, l'auteur avait sans doute une bonne raison de le déclarer privé, et d'accéder directement est un très mauvais (et largement désuète).
MODIFIER: Comme Adam V. points dans les commentaires, vous avez besoin de faire la méthode privée accessible avant de l'appeler. Exemple de Code mis à jour pour inclure cette. Je n'ai pas testé, bien - juste en ajoutant ici pour garder la réponse de mise à jour.
Cela dit, vous pouvez utiliser La réflexion pour accomplir cette tâche. Instancier
ReflectionClass
, appelgetMethod
pour la méthode que vous souhaitez appeler, puis appelappeler
sur le revenuReflectionMethod
.Un exemple de code (bien que je n'ai pas testé, donc il peut y avoir des erreurs) pourrait ressembler à
Doh! Vous avez raison, mes excuses.
PHP API Reflection t le soutien à l'invocation des méthodes privées. Vous avez juste besoin d'un
$reflection_method->setAccessible(true)
après la$reflection_method = $reflection_class->getMethod("myPrivateMethod")
OriginalL'auteur Dathan
Voici une variante de l'autre des réponses qui peuvent être utilisés pour faire de tels appels sur une ligne:
OriginalL'auteur Mark McEver
J'ai ces problèmes trop parfois, mais j'ai autour de à travers mes normes de codage. Privés ou protégés fonctions sont identifiées par un préfixe de souligner ie
Puis-je simplement faire de la fonction publique.
Ainsi, bien que la fonction publique est la convention de nommage donne la notification que, alors que le public est privé et ne devrait pas vraiment être utilisé.
OriginalL'auteur buggedcom
Je suppose que le reflectionClass est la seule alternative si vous voulez vraiment accomplir certaines méthodes privées. De toute façon, si vous avez juste besoin d'un accès en lecture à privat ou des biens protégés, vous pouvez utiliser ce code:
OriginalL'auteur seorch.me
Si vous êtes en mesure d'ajouter une méthode dans la classe où la méthode est définie, vous pouvez ajouter une méthode qui utilise le call_user_method() en interne. Cela fonctionne également avec PHP 5.2.x
OriginalL'auteur Thomas Hunziker
Réponse est de mettre le public à la méthode. Tout ce truc que vous allez faire, ce ne serait pas compréhensible pour les autres développeurs. Par exemple, ils ne savent pas qu'à un autre code de cette fonction a été consulté en tant que public en regardant la Démo de classe.
Une chose de plus. de la console peuvent accéder à la première méthode d'écriture d'une commande comme:. Comment cela peut-il être possible? La Console ne peut pas accéder à la démo des fonctions de classe en utilisant $this.
OriginalL'auteur siva kiran
Pourquoi ne pas vous utiliser protégé? Et de l'étendre
OriginalL'auteur kobbycoder