Page 1 sur 1

Hooks et objets avec des propriétés privées

Posté : 19 nov. 2010, 15:53
par Genova
Hello :)

Je base une grosse partie du projet sur lequel je suis actuellement en train de travailler sur la présence de hooks à des points clefs. Et je me suis heurté a un petit problème de logique ...

Admettons une classe basique :
class MVC
{
   protected $rules = array();

   public function process()
   {
      // Ici je place un hook, que des plugins pourront utiliser
      trigger_hook('mvc:process', $this);

      // Ici du code, que la méthode process() fera
      foreach ($this->rules) { ... }
   }
}
Maintenant dans un plugin, je vais faire en sorte d'utiliser ce hook (vive PHP 5.3 et les fonctions anonymes :p)
// Mon plugin qui veut ajouter un truc dans le MVC
register_hook('mvc:process', function(MVC $mvc)
{
   $mvc->rules[] = 'une nouvelle règle';
}
Sauf que le soucis ... C'est que MVC->rules est protégée, donc impossible d'y accéder dans mon plugin :)

Pour ce cas de figure vous me direz que je peux créer des setter et des getters pour y accéder, sauf que pour une classe avec 30 propriétés, ça devient vite un peu chiant ... Et de plus ça ne résoudrait pas le soucis pour les méthodes protégées, là j'ai simplement mentionné les propriétés, mais il peut arriver que j'ai besoin d'utiliser des méthodes protégées.

En gros j'aimerai pouvoir transporter le "contexte" du $this dans mon Hook. La seule solution que je vois actuellement c'est de ... tout passer en public :s Au moins ça marchera, mais je trouve dommage de ne pas pouvoir bénéficier de ces fonctionnalités de PHP, surtout qu'il s'agit d'un Framework sur lequel je bosse et ça ferait moyennement sérieux ...

Vous auriez des idées ? J'ai peut être pris le problème dans le mauvais sens ?

Re: Hooks et objets avec des propriétés privées

Posté : 19 nov. 2010, 16:02
par stealth35
hellon, tu peux regarde du coté de __set et de debug_backtrace, debug_backtrace va te renvoyé la fonction qui a été appelée en stack donc register_hook, l'autre je sais pas trop se que ca va donnée

EDIT : il va te mettre {closure} :? , mais t'as quand même le register_hook :wink:

Re: Hooks et objets avec des propriétés privées

Posté : 19 nov. 2010, 16:07
par Genova
Salut,
j'avoue que je ne vois pas trop où tu veux en venir, tu pourrais développer un peu ton idée ?

Merci ^^

Re: Hooks et objets avec des propriétés privées

Posté : 19 nov. 2010, 16:20
par stealth35
Salut,
j'avoue que je ne vois pas trop où tu veux en venir, tu pourrais développer un peu ton idée ?

Merci ^^
quand tu fais un surcharge avec __set, pour accéder a une variable et la remplir, tout le monde peux y accède c'est comme si ca la rendais public, mais comme c'est une méthode on peu lui donner des conditions, dans ton cas, seul la fonction register_hook a le droit de modifié un classe, c'est la qu'intervient debug_backtrace, qui lui va te renvoyer le stack d'appelle et tu va pouvoir controller les autorisations

exemple
class Test
{
    private $rules = array('old');
    
    public function __set($name, $value)
    {
        $stack = debug_backtrace();
        
        if(!empty($stack[2]) && $stack[2]['function'] === 'hook')
        {
            $this->rules = $value;
        }            
    }
}
function hook()
{
	$test = function()
	{
		$test = new Test();
		$test->rules = array('new');
		return $test;
	};
    return $test();
}

function hack()
{
    $test = function()
	{
		$test = new Test();
		$test->rules = array('new');
		return $test;
	};
    return $test();
}

var_dump(hook());
var_dump(hack());
/*
object(Test)#2 (1) {
  ["rules":"Test":private]=>
  array(1) {
    [0]=>
    string(3) "new"
  }
}
object(Test)#1 (1) {
  ["rules":"Test":private]=>
  array(1) {
    [0]=>
    string(3) "old"
  }
}
*/

Re: Hooks et objets avec des propriétés privées

Posté : 19 nov. 2010, 17:23
par popy
Si tes "hooks" étaient des paires objet/methodes, tu pourrais implémenter une sorte de "friend classes", en stockant l'objet hook en cours dans une propriété (pour comparaison), et avec une methode getprotected($name, $caller). Du coup tu peux comparer $caller a la propriété précédemment citée pour "authentifier" ton hook. (avec === bien entendu)

Re: Hooks et objets avec des propriétés privées

Posté : 19 nov. 2010, 17:45
par Genova
@stealth35 : jolie solution, seulement cela implique que toutes les classes qui auront des hooks devront avoir __set(), __get() et __call() ... Sachant qu'il y a potentiellement des centaines de classes, c'est difficilement envisageable. Je pourrai faire en sorte que toutes les classes en étendent une commune, mais là c'est encore difficilement envisageable, surtout que certaines classes utilisent déjà ces méthodes magiques à d'autre fins :/

@popy : le problème avec ça c'est que pour l'utilisateur final qui développera des plugins ou travaillera sur le projet, ça sera assez galère. J'aurai aimé que ce soit aussi simple que dans mon exemple :/

Re: Hooks et objets avec des propriétés privées

Posté : 19 nov. 2010, 18:05
par Genova
Bon j'ai trouvé une solution, que j'espère temporaire, mais qui permet de faire ce que je veux.

Je me suis basé sur ça : http://www.php.net/manual/en/functions. ... .php#98384

Dans trigger_hook(), je ferai un test sur les arguments, et s'il s'agit d'un objet j'appliquerai la classe donnée dans le lien (qui utilise Reflection) sur l'objet avant de le transmettre au callback. Ca me dérange un peu en terme de performance (faudra que je fasse des tests poussés pour voir) d'avoir à appliquer ça sur les objets, sachant que les hooks seront très utilisés, mais au moins c'est transparent pour l'utilisateur :)

Re: Hooks et objets avec des propriétés privées

Posté : 19 nov. 2010, 18:19
par stealth35
après ca dépend surtout de la possibilité du hook, si il doit avoir accès a tout et tout faire ou si son utilisation est spécifique

Re: Hooks et objets avec des propriétés privées

Posté : 19 nov. 2010, 18:33
par Genova
Les hooks seront très présent, donc il peut arriver dans de très nombreux cas de devoir accéder à des données protégées. Mais je vais limiter ce que fait la classe indiquée, en ne donnant accès qu'aux propriétés "protected" et non "private", histoire de garder un petit peu de cohérence avec les déclarations des classes.