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 :

Autochargement des classes et espaces de nom


Sujet :

Langage PHP

  1. #1
    Membre éclairé Avatar de metagoto
    Profil pro
    Hobbyist programmateur
    Inscrit en
    Juin 2009
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Hobbyist programmateur

    Informations forums :
    Inscription : Juin 2009
    Messages : 646
    Points : 845
    Points
    845
    Par défaut Autochargement des classes et espaces de nom
    Je ne sais pas si vous vous êtes penchés sur le problème, à savoir gérer les namespaces dans php 5.3 en ce qui concerne l'usage d'autoload.

    Pour un projet perso, j'en suis arrivé à cette solution:
    Comme à la PEAR, Zend etc, le nom complet des classes reflète la structure des répertoires dans lesquels elles sont situées.

    Donc disons que j'ai une classe complètement qualifiée comme ceci:

    \framework\sub\ns\Controller

    Le fichier de la classe sera dans:

    framework/sub/ns/Controller.php

    Ce qu'il y a "avant" le répertoir framework/ n'importe pas (voir plus bas)

    Comme dans mon projet il y a plusieurs namespaces indépendants (qui n'ont pas la même racine), j'utilise spl_autoload_register().

    Voici à quoi je suis arrivé pour l'autoloading des classes du framework.
    L'include path est vide car je ne travaille qu'avec des path absolus (plus rapide).
    L'autoloading pour la partie userland est en fait exactement la même:


    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
    // fichier de la classe \framework\Autoloader
     
    namespace framework;
     
    class Autoloader
    {
        private static $NS_LEN = 0; // pourrait être codé en dur, mais bon...
     
        public static function register()
        {
            // store le strlen du namespace courant (framework\)
            self::$NS_LEN = strlen(__NAMESPACE__) + 1;
            // register l'autoload
            spl_autoload_register(array(__CLASS__, 'autoload'));
        }
     
        public static function autoload($class)
        {
            // check si la classe est bien une classe controllée par le framework
            // donc que "framework\" est bien le prefix
            if (strpos($class, __NAMESPACE__.'\\') === 0) {
                // ok, on envoie
                // on virre le prefix "framework\" et on mappe le reste sur la structure du directory
                include __DIR__.DIRECTORY_SEPARATOR
                       .str_replace('\\', DIRECTORY_SEPARATOR, substr($class, self::$NS_LEN))
                       .'.php';
            }   
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // userland:
     
    namespace userland;
    use framework;
     
    include '/path/to/framework/Autoloader.php';
    framework\Autoloader::register();
     
    $c = new framework\sub\ns\Controller; 
    $blah = new custom\ns\Blah; // \userland\custom\ns\Blah
    Avez-vous pensez à une autre solution ? A l'usage, cette technique m'est pleinement satisfaisante.

  2. #2
    Membre confirmé Avatar de gtraxx
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2006
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 1 043
    Points : 570
    Points
    570
    Par défaut
    Je relance ce thread :
    J'ai une question concernant à l'appel des classes, tu m'avais aidé pour un autoload compatible php 5.2 sur base de celui-ci (il fonctionne nikel )
    Mais je me demandais si je pouvais ajouté un petit quelque chose pour réduire l'appel à une fonction.
    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    \framework\sub\ns\Controller
    $appel = new framework_sub_ns_Controller();
    $appel->ma_fonction();
    .....
    Bref est il possible de passer framework automatiquement dans l'autoload et faire une semi auto instance.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    \framework\sub\ns\Controller
    $appel = new sub_ns_Controller();
    $appel->ma_fonction();
    .....
    Désolé du mal à exprimer ce que je souhaite
    En espérant que je n'altèrerais en rien le chargement sachant que je dois garder la possibilité d'utiliser une instance complète.
    Au petit déjeuner, je prend du PHP et au souper du jQuery.
    AFUP 2009 : Bien optimiser son code pour le référencement
    Mon projet open source de librairie PHP 5: magix cjquery

  3. #3
    Membre éclairé Avatar de metagoto
    Profil pro
    Hobbyist programmateur
    Inscrit en
    Juin 2009
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Hobbyist programmateur

    Informations forums :
    Inscription : Juin 2009
    Messages : 646
    Points : 845
    Points
    845
    Par défaut
    Tu es dans le cas de php < 5.3 ?
    Pour php 5.3, avec les namespaces, ton soucis de raccourcir les noms lors des appels ne serait plus un problème puisqu'il suffit d'importer une portion de namespace. Genre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    use framework\sub\ns;
    $appel = new ns\Controller; // \framework\sub\ns\Controller
    Dans le cas de php 5.2 et inférieur, il va y avoir un problème puisque pour toute instanciation, php s'attend à trouver la classe qui porte le nom exact.

    On ne peut pas substituer une classe de nom "A_B_C" (par exemple) à la place de "B_C" qui est attendue par php.
    Un autoloader peut bidouiller comme il veut pour charger le fichier de la classe, la seule chose obligatoire est que dans ce fichier, une classe doit porter le nom exact "B_C" et non pas "A_B_C". Pour php, il s'agit d'une autre classe et il va alors générer une erreur fatale.

    Les namespaces sont venus palier à ce genre de problème, le fait de devoir se trimbaler des noms_a_rallonge_etc. Il n'y a pas de solution à ton problème pour php < 5.3

  4. #4
    Membre confirmé Avatar de gtraxx
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2006
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 1 043
    Points : 570
    Points
    570
    Par défaut
    Merci pour ta réponse metagoto, je suis bien conscient que le nom de la classe doit obligatoirement être complète.
    Ma question c'est plutot au niveau de l'appel d'une classe ou instance.
    Disons que je fais un petit site internet je souhaite appeller une classe spécifique mais elle porte un nom à rallonge.
    framework_sub_ns_Controller_subcontroller_truc();
    Etant donnée que je dois toujours appelé framework_....., je me demande si je ne peux pas faire en sorte que dans l'autoload je passe directement cette partie de l'instance afin de réduire la chaine.
    Donc je pourrai l'appeler dans mon site de cette manière sub_ns_Controller_subcontroller_truc(); sachant que framework_ est pré instanciée automatiquement.
    Je ne sais pas si tu me suis
    Je tente désespérement de reduire l'appel à une classe car mes utilisateurs râle un peux
    On ne peux tout connaitre c'est certain
    Au petit déjeuner, je prend du PHP et au souper du jQuery.
    AFUP 2009 : Bien optimiser son code pour le référencement
    Mon projet open source de librairie PHP 5: magix cjquery

  5. #5
    Membre éclairé Avatar de metagoto
    Profil pro
    Hobbyist programmateur
    Inscrit en
    Juin 2009
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Hobbyist programmateur

    Informations forums :
    Inscription : Juin 2009
    Messages : 646
    Points : 845
    Points
    845
    Par défaut
    Citation Envoyé par gtraxx Voir le message
    Etant donnée que je dois toujours appelé framework_....., je me demande si je ne peux pas faire en sorte que dans l'autoload je passe directement cette partie de l'instance afin de réduire la chaine.
    Donc je pourrai l'appeler dans mon site de cette manière sub_ns_Controller_subcontroller_truc(); sachant que framework_ est pré instanciée automatiquement.
    Je ne sais pas si tu me suis
    Je pense comprendre ton problème et je t'ai répondu plus haut: ça ne va pas fonctionner.

    Si ta "vraie" classe porte le nom de framework_sub_ns_Controller_subcontroller_truc, alors on ne peut pas y faire référence avec un nom plus court du point de vue de php:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $a = new sub_ns_Controller_subcontroller_truc; // pas bon
    En interne php maintient une symbols table et si "sub_ns_Controller_subcontroller_truc" n'est pas déjà une classe connue à un instant t, le mécanisme d'autoloading entre en jeu et ce dernier est prié de lui fournir une classe qui porte ce nom exact ou sinon il y a une erreur.

    Donc là je me place dans le cadre d'un autoloading avec une convention à la PEAR/Zend: Des classes du genre Zend_Machin_Bidule_Abstract. On doit se trimbaler le prefixe "Zend_". Les symboles doivent être en corrélation.

    Cependant, il y aurait une alternative: quelque chose proche d'un Factory. Là on ne va plus utiliser des expressions du style "$a = new Symbole" mais plutôt "$a = getSymbole()". getSymbole() serait une fonction (ou une méthode, peu importe) et c'est à elle qu'incombe la tache d'utiliser l'opérateur new avec le bon nom de classe. Cette indirection serait une solution pour les noms à rallonge, mais personnellement, je trouve que ce serait complètement inapproprié. Pour comprendre, un exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    // partie librairie
    function getTruc() {
      // trigger l'autoloading si besoin. pas de prob, tout baigne
      return new famework_sub_ns_Controller_subcontroller_truc;
    }
     
    // partie userland
    $t = getTruc();
    getTruc() (ou createTruc(), newTruc() etc) s'extirpe complètement de la convention des prefixes sensée apporter un peu de cohérence et d'ordre dans les libraires et les usages. Alors ok, à la place de getTruc(), on pourrait mettre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    function sub_ns_Controller_subcontroller_truc() {
      return new famework_sub_ns_Controller_subcontroller_truc;
    }
    Mais ça me parait encore pire...

  6. #6
    Membre confirmé Avatar de gtraxx
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2006
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 1 043
    Points : 570
    Points
    570
    Par défaut
    C'est bien ce que je pensais, j'ai certaine personne qui râle à devoir taper magixcjquery_.... mais bon je n'y peux rien je me suis basé justement sur zend afin de bien comprendre le système.
    Je pense tout de même améliorer pas mal de chose, notamment côté gestion des erreurs , je dois trouvé les améliorations à faire dans la lib avant de continuer mon chemin pour les fonctionnalités avec jquery.
    Je pense que l'autoload peut être améliorer afin de diminuer le nombre d'erreurs, probléme.
    Pas mal de travail encore du côté de magixdb pour améliorer les fonctionnalités et ainsi avoir quelque chose de plus rapide, plus simple surtout (pour mes users).
    Mes recherches vont bien finir par aboutir dans une optimisation optimal avec une bonne simplicité
    Au petit déjeuner, je prend du PHP et au souper du jQuery.
    AFUP 2009 : Bien optimiser son code pour le référencement
    Mon projet open source de librairie PHP 5: magix cjquery

  7. #7
    Membre éclairé Avatar de metagoto
    Profil pro
    Hobbyist programmateur
    Inscrit en
    Juin 2009
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Hobbyist programmateur

    Informations forums :
    Inscription : Juin 2009
    Messages : 646
    Points : 845
    Points
    845
    Par défaut
    Sans un support natif des namespaces, il faut préfixer les symboles. Il est donc important de bien choisir le prefixe! "Zend" pour Zend, "sf" pour symfony... autant éviter les longs préfixes!! Et là tu ne peux t'en vouloir qu'à toi même
    On préfixe aussi à mort dans le langage C par exemple. Pareil, les préfixes sont judicieusement choisis...

  8. #8
    Membre confirmé Avatar de gtraxx
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2006
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 1 043
    Points : 570
    Points
    570
    Par défaut
    mmm tu as raison, je dois alors faire en sorte que le préfixe sois par exemple
    mc_...
    Au lieux de magixcjquery_...
    Je vais voir comment faire
    Si tu as d'autres conseils je suis preneur
    Au petit déjeuner, je prend du PHP et au souper du jQuery.
    AFUP 2009 : Bien optimiser son code pour le référencement
    Mon projet open source de librairie PHP 5: magix cjquery

Discussions similaires

  1. Autochargement des classes dans une tâche CRON
    Par sebastien.bordat dans le forum Langage
    Réponses: 1
    Dernier message: 13/06/2013, 23h22
  2. Réponses: 6
    Dernier message: 24/04/2012, 13h53
  3. Génération de $ dans le nom des .class générées
    Par mrfirefunk dans le forum Eclipse Java
    Réponses: 6
    Dernier message: 05/12/2007, 16h44
  4. Récupérer les noms des classes parents
    Par see++ dans le forum Général Python
    Réponses: 2
    Dernier message: 12/03/2007, 17h35
  5. package ambiguïté pour des classes de même nom
    Par soad dans le forum Langage
    Réponses: 2
    Dernier message: 10/06/2004, 19h25

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