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