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 :

Problème de singleton abstrait [PHP 5.2]


Sujet :

Langage PHP

  1. #1
    Membre confirmé Avatar de alejandro
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2004
    Messages
    167
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2004
    Messages : 167
    Par défaut Problème de singleton abstrait
    Bonjour,

    J'ai créé un singleton abstrait qui fonctionne très bien jusqu'ici :

    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
    if( ! class_exists( 'Singleton_Abstract' ) )
    {
        abstract class Singleton_Abstract
        implements Singleton_Interface
        {
            protected static $i_Counter = 0;
            protected static $s_Fline = null;
     
            final private function __clone(){}
            protected function __construct(){}
     
            final public static function GetInstance()
            {
                static $h_Instances = array();
     
                $s_Class = self::GetChild();
     
                if( ! isset( $h_Instances[ $s_Class ] ) )
                    $h_Instances[ $s_Class ] = new $s_Class;
     
                return $h_Instances[ $s_Class ];
            }
     
            final protected static function GetChild()
            {
                $h_Backtrace = debug_backtrace();
     
                $i_Line = $h_Backtrace[1]['line'];
                $s_File = $h_Backtrace[1]['file'];
                $s_Function = $h_Backtrace[1]['function'];
     
                self::$i_Counter = ( self::$s_Fline == $s_File . $i_Line )
                                 ? self::$i_Counter++ : 0;
     
                $s_Search = "/([a-zA-Z0-9\_]+)::$s_Function/";
     
                $a_Lines = file( $s_File );
                $s_Line = $a_Lines[ --$i_Line ];
     
                preg_match_all( $s_Search, $s_Line, $a_Matches );
     
                return $a_Matches[1][self::$i_Counter];
            }
     
        }
    }
    Sauf que j'ai un bug lorsque je réclame une instance de mon singleton via eval() comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    eval( "$s_Class::GetInstance();" );
    J'obtiens plusieurs messages d'erreur :

    Warning: file(C:\Documents and Settings\alejandro\Mes documents\Company\Programmes\Mairies\Framework\Default\Bootstrap.php(56) : eval()'d code) [function.file]: failed to open stream: No such file or directory in C:\Documents and Settings\alejandro\Mes documents\Company\Programmes\Mairies\Framework\Singleton\Abstract.php on line 47

    Notice: Undefined offset: 0 in C:\Documents and Settings\alejandro\Mes documents\Company\Programmes\Mairies\Framework\Singleton\Abstract.php on line 52

    Fatal error: Class name must be a valid object or a string in C:\Documents and Settings\alejandro\Mes documents\Company\Programmes\Mairies\Framework\Singleton\Abstract.php on line 29
    Les deux messages d'erreur suivants découlent de la première erreur.

    Quelqu'un saurait-il comment modifier mon singleton abstrait afin qu'il puisse également fonctionner lors d'une instanciation via la fonction eval() ???

  2. #2
    Membre éprouvé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2007
    Messages
    121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Avril 2007
    Messages : 121
    Par défaut
    Je suppose que tu sais que l'utilisation de eval() est fortement déconseillé et qu'elle est peut toujours être remplacé par quelque chose de correct.

    Pour revenir à ton problème, eval() semble vouloir inclure quelque chose au fichier ou il sert à inclure un fichier qui n'est pas trouvé.
    Que contient $s_Class ?
    Que contiennent les lignes citées par l'erreur ?

  3. #3
    Membre confirmé Avatar de alejandro
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2004
    Messages
    167
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2004
    Messages : 167
    Par défaut
    Bonsoir,

    Je sais que l'utilisation d'eval n'est pas conseillée mais je n'ai pour l'instant pas trouvé de solution de remplacement. Mon eval se trouve dans un bootstrap :

    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
    if( ! class_exists( 'Default_Bootstrap' ) )
    {
        if( ! defined( 'APPLICATION_CONTROLLERS_DIRECTORY' ) )
            define( 'APPLICATION_CONTROLLERS_DIRECTORY', 'Controller' );
     
        if( ! defined( 'APPLICATION_DEFAULT_CONTROLLER' ) )
            define( 'APPLICATION_DEFAULT_CONTROLLER', 'Default' );
     
        final class Default_Bootstrap
        extends Strategy_Singleton_Abstract
        implements Factory_Interface
        {        
            protected function __construct()
            {
                $i_Segment = 1;
                $s_Path = APPLICATION_CONTROLLERS_DIRECTORY;
                $o_Uri = Default_Uri::GetInstance();
     
                while( $s_Segment = $o_Uri->GetSegment( $i_Segment ) )
                {                
                    $s_Segment = strtoupper( substr( $s_Segment, 0, 1 ) ) 
                               . strtolower( substr( $s_Segment, 1, strlen( $s_Segment ) ) );
     
                    $s_Path .= "/$s_Segment";
     
                    $i_Segment++;
                }
     
                $s_FrameworkPath = dirname( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR;
     
                if( $s_Path === APPLICATION_CONTROLLERS_DIRECTORY
                  OR is_dir( APPLICATION_PATH . str_replace( '/', DIRECTORY_SEPARATOR, $s_Path ) ) )
                    $s_Path .= '/' . APPLICATION_DEFAULT_CONTROLLER;
     
                $this->o_Strategy = $this->Factory( $s_Path );
            }
     
            public function Factory( $s_Path )
            {
                $s_FrameworkPath = dirname( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR;
                $s_Path = str_replace( '/', DIRECTORY_SEPARATOR, $s_Path );
                $s_Class = str_replace( DIRECTORY_SEPARATOR, '_', $s_Path );
     
                if( file_exists( APPLICATION_PATH . "$s_Path.php" )
                  OR file_exists( $s_FrameworkPath . "$s_Path.php" ) )
                    return eval( "$s_Class::GetInstance();" );
     
                throw new Exception( "PAGE_NOT_FOUND", 404 );
            }
        }
    }
    Je dois instancier de manière dynamique un singleton et je n'ai pas trouvé d'autre solution que d'utiliser eval. $s_Class est une string contenant le nom de la classe à instancier, par exemple "Default_Controller_404".

    Lorsque la classe contrôleur est appelée pour la première fois, une fonction _autoload() se charge d'inclure le fichier correspondant au chemin Default/Controller/404.php.

    Cette variable $s_Class est donc générée de manière dynamique en fonction de l'URI saisie par le client et utilisée pour appeler l'instance unique du contrôleur correspondant.

    Concernant le contenu des deux fichiers donnés dans les warnings, le bootstrap est ci-dessus et le singleton abstrait dans mon premier post.

  4. #4
    Membre éprouvé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2007
    Messages
    121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Avril 2007
    Messages : 121
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ${$s_Class}::GetInstance();
    ne fonctionne pas ??

    L'erreur vient tel de ton GetInstance() ??

  5. #5
    Membre confirmé Avatar de alejandro
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2004
    Messages
    167
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2004
    Messages : 167
    Par défaut
    Bonjour et merci pour ta réponse, mais cela ne fonctionne pas ... Ma variable $s_Class contient un nom de classe de type "Controller_404" par exemple.

    J'essaye de caster de manière dynamique cette classe qui est un singleton :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Controller_404::GetInstance();
    Sauf que puisque "Controller_404" est généré de manière dynamique par mon script j'ai essayé de faire comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $s_Class::GetInstance();
    et j'obtiens le message d'erreur suivant :

    Parse error: parse error, unexpected T_PAAMAYIM_NEKUDOTAYIM in C:\Documents and Settings\alejandro\Mes documents\Company\Programmes\Mairies\Framework\Default\Bootstrap.php on line 57
    Si j'essaye comme ceci cela ne marche pas non plus :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    {$s_Class}::GetInstance();
    J'obtiens le message d'erreur suivant :

    Parse error: parse error, unexpected '{' in C:\Documents and Settings\alejandro\Mes documents\Company\Programmes\Mairies\Framework\Default\Bootstrap.php on line 57
    et enfin mettre un dollar devant je ne comprends pas pourquoi car je ne cherche pas à faire $Controller_404::GetInstance(); mais Controller_404::GetInstance();

    En fait il faudrait que je puisse instancier un singleton de manière dynamique sans passer par eval... si vous avez une idée ...

  6. #6
    Membre éprouvé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2007
    Messages
    121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Avril 2007
    Messages : 121
    Par défaut
    la solution a ton problème est dans la doc... et ca doit fonctionner (si la doc le dit...)

  7. #7
    Membre confirmé Avatar de alejandro
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2004
    Messages
    167
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2004
    Messages : 167
    Par défaut
    Depuis PHP 5.3.0, il est possible de référencer une classe en utilisant une variable. La valeur de la variable ne peut être un mot clé (e.g. self, parent et static).
    Problème je suis sur PHP 5.2 et je ne peux pas passer en 5.3, d'où ma solution avec eval. Problème, cela ne semble pas fonctionner avec mon singleton abstrait car lors de l'appel à la fonction GetChild(), j'ai une erreur :

    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
    final protected static function GetChild()
            {
                $h_Backtrace = debug_backtrace();
     
                $i_Line = $h_Backtrace[1]['line'];
                $s_File = $h_Backtrace[1]['file'];
                $s_Function = $h_Backtrace[1]['function'];
     
                self::$i_Counter = ( self::$s_Fline == $s_File . $i_Line )
                                 ? self::$i_Counter++ : 0;
     
                $s_Search = "/([a-zA-Z0-9\_]+)::$s_Function/";
     
                $a_Lines = file( $s_File );
                $s_Line = $a_Lines[ --$i_Line ];
     
                preg_match_all( $s_Search, $s_Line, $a_Matches );
     
                return $a_Matches[1][self::$i_Counter];
            }
    Warning: file(C:\Documents and Settings\alejandro\Mes documents\Company\Programmes\Mairies\Framework\Default\Bootstrap.php(56) : eval()'d code) [function.file]: failed to open stream: No such file or directory in C:\Documents and Settings\alejandro\Mes documents\Company\Programmes\Mairies\Framework\Singleton\Abstract.php on line 47
    et cette erreur vient du fait que dans mon backtrace, $Backtrace[1]['file'] contient (56) : eval()'d code à la fin du chemin d'accès au fichier.

    Soit je remplace return eval( "$s_Class::GetInstance();" ); par une autre façon d'instancier mon singleton, sachant que je suis en php 5.2 et que je ne peux pas faire $s_Class::GetInstance();.

    Soit je modifie ma fonction GetChild() dans mon singleton abstrait de manière à ne garder que l'adresse du fichier et à supprimer tout ce qui suit... je vais regarder avec une expression régulière mais je ne suis pas sûr que ce soit la façon la plus élégante de régler mon problème...

  8. #8
    Membre confirmé Avatar de alejandro
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2004
    Messages
    167
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2004
    Messages : 167
    Par défaut
    Bon c'est bon j'ai compris d'où venait le problème, je vais réouvrir un autre post pour voir si on peut trouver une solution au problème :

    Dans mon singleton abstrait j'ai besoin de connaitre le nom de la classe enfant qui hérite de Singleton_Abstract. En PHP 5.3 il est possible d'utiliser la fonction get_called_class() qui renvoie donc ce nom.

    Par contre pour les versions antérieures à PHP 5.3 ( et je suis en 5.2 ) il existe différents bricolages permettant de retranscrire cette fonctionnalité. Tous utilisent la fonction debug_backtrace() pour récupérer le nom de la classe enfant. Problème : Ces bricolages ne fonctionnent pas si l'on utilise la fonction eval ou call_user_func().

    Je peux considérer mon problème comme partiellement résolu

  9. #9
    Membre éprouvé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2007
    Messages
    121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Avril 2007
    Messages : 121
    Par défaut
    Si tu veux faire dans le bricolage, tu peux passer par une fonction avec une série de IF ou un SWITCH afin d'appeler chaque instance des "Controller".
    C'est pas super mais c'est du bricolage...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 26/08/2011, 14h44
  2. [PHP 5.3] Problème de Singleton
    Par adc15 dans le forum Langage
    Réponses: 23
    Dernier message: 30/04/2011, 15h27
  3. Problème avec classe abstraite
    Par Antoniom dans le forum Débuter avec Java
    Réponses: 4
    Dernier message: 29/01/2011, 14h03
  4. Problème de singleton
    Par Monstros Velu dans le forum Général Dotnet
    Réponses: 0
    Dernier message: 19/02/2009, 16h27
  5. [GOF] Fabrique abstraite peut-elle être un Singleton ?
    Par manel007 dans le forum Design Patterns
    Réponses: 7
    Dernier message: 06/01/2005, 11h02

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