IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Séparation de modules et __php_incomplete_class


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Juin 2008
    Messages
    125
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 125
    Par défaut Séparation de modules et __php_incomplete_class
    Bonjour,

    Je suis en train de peiner depuis un beau bout de temps pour résoudre un problème (qui me semble celui de l'oeuf et la poule) ...

    Je développe un site sous prestashop (on me dira peut être que je suis pas au bon endroit !) qui fonctionne sur la base de modules.
    J'ai donc 3 modules : porte-monnaie contenant les classes PorteMonnaie et PorteMonnaieService, gestionnaire-cle contenant les classes GestionnaireCle et GestionnaireCleService et abonnement contenant la classe Abonnement.

    Les trois modules sont et doivent être indépendants les uns des autres dans le sens où aucun fichier de l'un ne doit être inclus dans l'autre. Pour cela, je suis passer par une classe ServiceLocator qui perment de stocker les services dans $SESSION et de me fournir l'instance voulue au moment voulu.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
     
    class ServiceLocator
    {
        private static $SERVICE_ATTR = 'service';
        private static $PATH_ATTR = 'path';
     
        public function getService ($pServiceName)
        {
        	$serviceInstance = null;
        	$path = null;
        	$serviceName = strtolower($pServiceName);
     
    	if (isset($_SESSION[$serviceName]))
           	{
           		$serviceInstance = $_SESSION[$serviceName][self::$SERVICE_ATTR];
               	$path = $_SESSION[$serviceName][self::$PATH_ATTR];
           	}
     
           	return $serviceInstance;
        }
     
        public function servicePath($pServiceName)
        {
        	$serviceName = strtolower($pServiceName);
           	if (isset($_SESSION[$serviceName]))
           	{
               	return $_SESSION[$serviceName][self::$PATH_ATTR];
           	}
     
           	return null;
        }
     
        public function setService ($pServiceName, $path, $pService)
        {
        	$serviceName = strtolower($pServiceName);
     
    	if (file_exists($path))
    	{
           	      include_once($path); // Ce code n'a été que par la suite pour tenter de solutionner le problème mais n'a vraisemblablement pas d'effet ...
    	}
        	//if (!isset($_SESSION[$serviceName])) 
        	{
    	        $_SESSION[$serviceName] = array(self::$SERVICE_ATTR => $pService, self::$PATH_ATTR => $path);
        	}
     
            return $this;
        }
     
        public function unsetService($pServiceName)
        {
        	unset($_SESSION[strtolower($pServiceName)]);
        }
     
        public function __call ($pName, $pParameters)
        {
            if (strpos(strtolower($pName), 'get') === 0) {
                return $this->getService(substr($pName, 3));
            }else{
                echo $pName;
            }
        }
    }
     
    class StaticServiceLocator
    {
        private static $_serviceLocator = false;
     
        public static function setService($pServiceName, $path, $pService)
        {
            return self::_serviceLocatorInstance()->setService($pServiceName, $path, $pService);
        }
     
        public static function unsetService($pServiceName)
        {
            return self::_serviceLocatorInstance()->unsetService($pServiceName);
        }    
     
        public static function getService($pServiceName)
        {
            return self::_serviceLocatorInstance()->getService($pServiceName);
        }
     
        public static function servicePath($pServiceName)
        {
        	return self::_serviceLocatorInstance()->servicePath($pServiceName);
        }
     
        public static function __callStatic($pName, $pParameters)
        {
            return self::_serviceLocatorInstance()->$pName($pParameters);
        }
     
        private static function _serviceLocatorInstance()
        {
            if (self::$_serviceLocator === false) {
                self::$_serviceLocator = new ServiceLocator();
            }
            return self::$_serviceLocator;
        }
    }
    La classe PorteMonnaieService s'enregistre auprès de mon ServiceLocator comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
     
    // Classe du module PorteMonnaie
    class PorteMonnaie
    {
         public function __construct() {
               StaticServiceLocator::setService('PorteMonnaie', _PS_MODULE_DIR_.'porte-monnaie/PorteMonnaieService.php', new PorteMonnaieService);
         }
    }
     
    // Classe service PorteMonnaie
    class PorteMonnaieService
    {
         public function methodeA()
         {}
    }
    La classe GestionnaireCleService s'enregistre auprès de mon ServiceLocator comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
     
    // Classe du module GestionnaireCle
    class GestionnaireCle
    {
         public function __construct() {
               StaticServiceLocator::setService('GestionnaireCle', _PS_MODULE_DIR_.'gestionnaire-cle/GestionnaireCleService.php', new GestionnaireCleService);
         }
    }
     
    // Classe GestionnaireCle service
    class GestionnaireCleService
    {
         public function methodeB()
         {}
    }
    La classe Abonnement a besoin des deux classes PorteMonnaieService et GestionnaireCleService.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     
    include_once(dirname(__FILE__).'/../classes/StaticServiceLocator.php'); // Le chemin est correct
     
    class Abonnement
    {
         public function __construct() {
                // Instance vers le porte-monnaie
                $porteMonnaieInstance = StaticServiceLocator::getPorteMonnaie(); // Cela est possible grâce à l'appel ServiceLocator::__call()
                // Appel d'une méthode de la classe PorteMonnaie
               $porteMonnaieInstance->methodeA(); // Là j'ai l'erreur de php incomplete class
         } 
    }
    Alors sur les forums, la cause était que l'inclusion du fichier de la classe instanciée doit apparaitre AVANT le session_start(). C'est ce que j'ai tenté de faire mais malheureusement cela n'est pas applicable à mon cas car j'ai besoin de récupérer dans la session le $path de la classe pour l'inclure => session_start() avant inclusion de fichier et inclusion de fichier avant session_start() !!

    Les modules sont systématiquement chargés dans l'index pourvu que leur attribut need_instance soit égal à 1 (ce qui est le cas).


    Comment contourner ce blocage ?

    EDIT : Parties soulignées et définition des classes PorteMonnaieService et GestionnaireCleService ajoutées.

    Merci

  2. #2
    Expert confirmé
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Billets dans le blog
    12
    Par défaut
    Salut,

    je ne connais pas particulièrement Prestashop mais y a quand même un truc qui coince. D'après tes exemples class PorteMonnaie { } et class GestionnaireCle { } tu es obligé d'instancier MANUELLEMENT au moins une fois ta classe pour qu'elle s'auto-déclare via (public function __construct(){ }) auprès du ServiceLocator !
    C'est un non-sens.
    Quelle est l'utilité de cette aprroche ? De fait, tu dois tout instancier manuellement vu que tu ne peut être jamais absolument sûr et certain que la classe appellée l'a déjà été au moins une fois et en conséquence, l'appel au StaticServiceLocator{ } relèvera du p'tit bonheur la chance.
    T'es sûr de tes codes ?

  3. #3
    Membre confirmé
    Inscrit en
    Juin 2008
    Messages
    125
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 125
    Par défaut
    Citation Envoyé par rawsrc Voir le message
    Salut,

    je ne connais pas particulièrement Prestashop mais y a quand même un truc qui coince. D'après tes exemples class PorteMonnaie { } et class GestionnaireCle { } tu es obligé d'instancier MANUELLEMENT au moins une fois ta classe pour qu'elle s'auto-déclare via (public function __construct(){ }) auprès du ServiceLocator !
    C'est un non-sens.
    Quelle est l'utilité de cette aprroche ? De fait, tu dois tout instancier manuellement vu que tu ne peut être jamais absolument sûr et certain que la classe appellée l'a déjà été au moins une fois et en conséquence, l'appel au StaticServiceLocator{ } relèvera du p'tit bonheur la chance.
    T'es sûr de tes codes ?
    Merci pour ta réaction.

    Effectivement, il y a un soucis avec le code que j'ai posté : j'ai tenté de réduire au strict minimum mon code mais ai commis une erreur. En réalité, il y a deux classes que je n'ai pas citées : celles des deux modules PorteMonnaie et GestionnaireCle. C'est dans ces classes que se font les enregistrements de services auprès du ServiceLocator.
    Je modifie en conséquence le code précédemment posté. Oups je ne vois pas le bouton me le permettant => je poste à nouveau alors !
    Désolé de cette inattention ...

Discussions similaires

  1. Module FTP.pm ?
    Par MSP dans le forum Modules
    Réponses: 4
    Dernier message: 04/08/2003, 15h49
  2. module Find
    Par martijan dans le forum Modules
    Réponses: 8
    Dernier message: 09/07/2003, 11h07
  3. cherche module ou langage pour récupérer des données audio..
    Par Ry_Yo dans le forum Langages de programmation
    Réponses: 5
    Dernier message: 12/05/2003, 17h44
  4. PerlDoc sur une fonction d'un module
    Par lesouriciergris dans le forum Modules
    Réponses: 2
    Dernier message: 13/03/2003, 20h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo