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 :

POO : Namespace et class not found [PHP 7]


Sujet :

Langage PHP

  1. #1
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut POO : Namespace et class not found
    Bonjour,

    J'essaie de me mettre sérieusement à la POO en m'inspirant du tutoriel de Baptiste Pesquet mais ça coince.

    index.php à la racine du site :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    use Application\Controller\Routeur;
    $routeur = new Routeur();
    Le fichier Routeur.php est bien situé dans Application/Controller. Eclipse m'a proposé lui-même ce use pour résoudre le new Routeur()La classe Routeur dans Routeur.php commence ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    namespace Application\Controller;
     
    use Application\View\Vue;
    use Exception;
     
    /**
     * @abstract Classe de routage de la requête HTTP
     */
    class Routeur
    {
    Et error.log de Apache me donne ceci :
    PHP Fatal error: Class 'Application\\Controller\\Routeur' not found
    Qu'est-ce que j'ai oublié ?
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  2. #2
    Membre expert
    Avatar de Spartacusply
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2011
    Messages
    1 723
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Mai 2011
    Messages : 1 723
    Points : 3 274
    Points
    3 274
    Par défaut
    Salut,

    la mise en place des espaces de noms n'est pas compris dans le tuto.

    Les espaces de noms sont définis ici dans la doc PHP : http://php.net/manual/fr/language.namespaces.php

    Ce qu'il faut bien comprendre c'est que la résolution d'un espace de nom n'est en aucun cas "magique", ce n'est pas parce que router est placé dans Application/Router qu'il sera automatiquement résolu.

    Il faut toujours définir un include du fichier en question pour que ce fichier soit utilisable dans ton code. Heureusement, étant donné que ce serait très vite pénible de réaliser cet include à chaque fois que l'on requière un fichier d'un namespace, php propose la fonction "__autoload" (http://php.net/manual/fr/language.oop5.autoload.php) qui va tenter d'inclure de manière dynamique le fichier. Mais comme écrit dans la doc, il est recommandé d'utiliser la fonction spl_autoload_register() qui propose le même résultat tout en étant plus flexible.

    Pour aller plus loin et plus vite, il y a encore deux choses à savoir :
    - Il existe une norme sur la manière d'autoload ses fichiers : la norme PSR-4 et dans une logique de conformité, il est fortement recommandé d'appliquer cette norme (d'où la logique de placer "Router" dans "Application/Router" dans ton cas par exemple).
    - L'outil composer qui est un gestionnaire de dépendance implémente directement la fonction spl_register_autoload en respectant la norme PSR-4, et dans cette optique, une fois que tu as compris comment ça fonctionne, je te recommande fortement de l'utiliser car tu ne feras jamais mieux que cet outil pour autoloader tes fichiers!
    Un message utile vous a aidé ? N'oubliez pas le

    www.simplifions.fr - Simplifier vos comptes entre amis !

  3. #3
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    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
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Salut,

    Passer à la POO c'est tip-top, si cela fait partie de tes résolutions 2018, bonne chance

    Ton problème est simple : le moteur PHP ne sait pas comment trouver le fichier qui contient le code source de ta classe.

    On va reprendre les explications pour que tu y vois plus clair :

    Les espaces de nom (namespace) te permettent de ranger logiquement ton code et éviter ainsi un véritable bordel quand la quantité de scripts augmente ainsi que les fonctionnalités de ton site web.
    Le découpage que cela induit offre une propriété intéressante qui te permet également dans les cas courants de trouver physiquement l'emplacement d'un fichier.
    Ce que je veux dire c'est que si ta classe Router est sur l'espace de nom : Application\Controller, il y a de très fortes chances que le fichier Router.php avec le code source se trouve dans une arborescence physique du disque du genre :
    src
     |--- Controller
     |        |--- Router.php
     |--- View
     |--- ...
    Comme tu peux le voir, il y a juste à dire au moteur PHP que quand tu appelles des classe avec use sur l'espace de nom Application il doive aller chercher physiquement les fichiers dans le dossier racine src et que pour la suite, il descende tout simplement l'arborescence des répertoires.

    Donc, cette logique d'organisation fournit directement pour la classe use Application\Controller\Router; l'emplacement physique du fichier à charger : src/Controller/Router.php.
    D'où la raison vitale de n'avoir toujours qu'une classe par fichier, que le nom du fichier corresponde exactement au nom de la classe et que l'arborescence des répertoires soit raccord avec les sous espaces de nom, cela simplifie grandement la vie.

    Allez je vais te faire voir le code source d'un petit autoloader répondant très simplement à cette problématique (l'autoloader doit être déclaré le plus tôt possible (au démarrage) du traitement d'une requête) :
    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
    // ici lors de l'appel : use Application\Controller\Router;     $full_class_name sera égal à Application\Controller\Router
     
    $autoloader = function($full_class_name) {
        // on prépare le terrain : on remplace le séparteur d'espace de nom par le séparateur de répertoires du système
        $name = str_replace('\\', DIRECTORY_SEPARATOR, $full_class_name);
        // on sépare en parties le nom complet de manière à isoler Application
        $parts = explode('Application', $name, 2);
     
        // on remplace Application par le nom du répertoire racine qui contient tous les fichiers
        $parts[0] = 'src';
     
        // on construit le chemin complet du fichier à inclure :
        // il faut que l'autoloader soit toujours à la racine du site : tout part de là avec __DIR__
        $path = __DIR__.DIRECTORY_SEPARATOR.implode('', $parts).'.php';    // $path = répertoire racine du site web/src/Controller/Router.php
     
        // on vérfie qu'il existe bien et on l'inclut
        // sinon on passe la main à une autre autoloader (return false)
        // tu peux empiler les autoloader sans problèmes jusqu'à tomber sur celui qui sera capable de localiser physiquement sur ton disque le fichier recherché
        if (is_file($path)) {
            include $path;
            return true;
        } else {
            return false;
        }
    };
     
    spl_autoload_register($autoloader);
    J'espère avoir été clair.

    Pour la suite, c'est simple : tout cela est maintenant normé : normes PSR-0/4 et effectivement composer est un bon outil pour gérer l'autoloading.
    Maintenant, personnellement pour ce qui est de composer, pour installer les dépendances, je dois avouer qu'il n'y a pas mieux mais pour un simple autoloader, c'est sortir un bazooka pour tuer une mouche.

  4. #4
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Je n'ai pas compris vraiment vos explications ni la doc de PHP sur ces histoires d'autoload.

    J'envisage une arborescence de ce type pour tout ce qui est commun au site :
    /
    |--Application
        |--Controller
        |--Model
        |--View
    |--Public
        |--css
        |--images
        |--js
    |--.htaccess
    |--index.php
    Ensuite, sous Application, j'envisage ceci :
    |--Application
        |--Module1
            |--Controller
            |--Model
            |--View
        |--Module2
    ...
    Dans le .htaccess, j'ai une réécriture d'URL qui va transformer monsite/fr/module1/action1/parametres-optionnels en index.php?langue=fr&module=module1&action=action1&params=parametres-optionnels et c'est cette URL qui doit être traitée par mon routeur pour appeler le bon contrôleur :
    - Par défaut le controller du module Accueil si appel du site à sa racine ;
    - Ou le contrôleur du module appelé par l'url qui va lui même déclencher l'action demandée avec les paramètres éventuels.

    J'ai commencé mon projet avec une méthode qui fonctionne mais qui est encore trop procédurale à mon goût, même si j'avais quand même déjà notamment des classes modèles pour les relations avec la BDD.
    Comme je ne suis pas encore trop avancé, je veux essayer de faire ça bien tout en objet, sauf bien sûr la partie index.php qui doit lancer la suite.

    Il y a quelques années, j'avais fait une application avec Zend Framework 1 mais j'ai voulu récemment essayer Zend Framework 3 et je l'ai trouvé beaucoup plus compliqué pour mon vieux cerveau. D'ailleurs, j'ai essayé le tuto et ça n'a pas fonctionné.
    C'est pour ça que j'ai cherché un autre tutoriel MVC POO.

    Donc tout ça pour dire que je n'ai pas bien compris où je dois mettre cet autoloader. Est-ce que ça doit être la première classe appelée par index.php ou est-ce une fonction dans index.php (donc un bout de procédural) ? Je pensais que c'était justement le boulot du routeur de s'occuper de ça : trouver la bonne classe à instancier et la bonne action à exécuter.

    Considérez-moi comme un noob en la matière et expliquez-moi ça par A+B SVP.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  5. #5
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    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
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Salut,

    Y a un truc je pense que tu n'as pas remarqué : est-ce que tu vois quelque part dans ton code un include ?
    Les espaces de nom, classes et le mécanisme d'autoloading t'évitent d'avoir à gérer manuellement tes inclusions. Le système se débrouille tout seul pour trouver tes fichiers sources.

    La seule obligation pour toi c'est d'indiquer au moteur PHP via spl_autoload_register comment transformer un nom de classe pleinement qualifié (espace de nom\sous-espace de nom...\Classe) en chemin de fichier.

    Si dans ton architecture, tout est redirigé vers index.php, j'ai déjà répondu à ta question concernant l'emplacement de déclaration de l'autoloading :
    Citation Envoyé par rawsrc
    l'autoloader doit être déclaré le plus tôt possible (au démarrage) du traitement d'une requête
    Donc le code de l'autoloader doit être au début de index.php avant les use.

    Enfin, il ne faut pas confondre : l'autoloading et le routage.
    L'autoloading est un mécanisme interne au code alors que le routage est un mécanisme à peu près équivalent dans la logique sauf qu'il s'agit de trouver le bon fichier en charge du traitement d'une requête externe.

  6. #6
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    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
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Pour en revenir à ton organisation :
    /
    |--Application
        |--Controller
        |--Model
        |--View
    |--Public
        |--css
        |--images
        |--js
    |--.htaccess
    |--index.php
    et
    |--Application
        |--Module1
            |--Controller
            |--Model
            |--View
        |--Module2
    Cela devra se traduire par des espaces de noms comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    namespace Application\Controller;
    namespace Application\Model;
    namespace Application\View;
    // --- //
    namespace Application\Module1\Controller;
    namespace Application\Module1\Model;
    namespace Application\Module1\View;
    Ensuite pour l'autloader c'est très simple, tu peux reprendre le mien (basique mais fonctionnel)
    Tu colles ce bout de code au démarrage de index.php
    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
    $autoloader = function($full_class_name) {
        // on prépare le terrain : on remplace le séparteur d'espace de nom par le séparateur de répertoires du système
        $name = str_replace('\\', DIRECTORY_SEPARATOR, $full_class_name);
        // on construit le chemin complet du fichier à inclure :
        // il faut que l'autoloader soit toujours à la racine du site : tout part de là avec __DIR__
        $path = __DIR__.DIRECTORY_SEPARATOR.$name.'.php';
     
        // on vérfie que le fichier existe et on l'inclut
        // sinon on passe la main à une autre autoloader (return false)
        if (is_file($path)) {
            include $path;
        } else {
            return false;
        }
    };
     
    spl_autoload_register($autoloader);
    Voilà le tour est joué, tu peux maintenant utiliser des use Application\Module1\Model\UneClasseModele comme tu le sens, PHP est maintenant capable de localiser physiquement tes fichiers source.

    Ce n'est ni plus ni moins que l'application directe des explications que je t'ai données

  7. #7
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    J'ai encore du mal à comprendre comment ça fonctionne...

    ici lors de l'appel : use Application\Controller\Router; $full_class_name sera égal à Application\Controller\Router
    Comment le use qui est situé n'importe où dans les programmes peut appeler $autoloader donc la fonction ayant pour paramètre $full_class_name ?
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  8. #8
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    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
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Je ne comprends pas ce que tu ne comprends pas.

    Cette fonction fait partie de la SPL (Standard PHP Library) qui regroupe un ensemble de classes et de fonctions qui pour certaines te permettent d'interagir directement sur le comportement du moteur PHP.
    Le mécanisme d'autoloading est présent depuis PHP 5.1.2 (12/01/2006), depuis il a été amélioré et a facilité la vie de millions de développeurs.
    C'est clair que sans s'être frotté à la POO, la connaissance de ce mécanisme peut être superflue mais une bonne compréhension de la logique sous-jacente est primordiale dans la mesure où cette problématique est commune à tous les langages gérant l'objet.

    Un conseil, vu tes réponses, m'est d'avis que tu attaques d'emblée trop haut pour ce qui est niveau de difficulté.
    Si tu te mets dans l'idée de modéliser en POO une architecture d'un site web à des fin d'auto-apprentissage tout en étant débutant, c'est tout bonnement mission impossible.
    Le risque que tu rejoigne les 15% des développeurs qui sont incapables de basculer en POO est grand ; sans compter que ta motivation va en prendre un sacré coup à cause d'une trop grande difficulté au démarrage et la courbe d'apprentissage va s'étirer s'étirer jusqu'à rompre.

    Démarre par du simple, le meilleur conseil que je puisse te donner c'est de prendre un bout d'un de tes programmes existants qui regroupe un ensemble de fonctions répondant à un petit besoin et prendre le temps re-modéliser le tout sous forme objet. Déjà qu'à la base, tu va devoir appréhender un sacré paquet de concepts assez abstraits, il vaut d'autant mieux que le support de cet apprentissage te soit des plus familier.

    Bon courage

  9. #9
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Bon les histoires de namespace et de use, ça va, ça fonctionne et j'arrive à peu près à ce que je veux.
    J'ouvre une autre discussion pour un autre souci au niveau de mon routeur.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

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

Discussions similaires

  1. [JDBC][MYSQL] class not found.
    Par hellboy dans le forum JDBC
    Réponses: 2
    Dernier message: 09/10/2006, 21h22
  2. Class not found
    Par khamed dans le forum Tomcat et TomEE
    Réponses: 5
    Dernier message: 24/07/2006, 09h22
  3. [HIBERNATE] Conf et classe not found
    Par djodjo dans le forum Hibernate
    Réponses: 2
    Dernier message: 10/05/2006, 16h37
  4. [JSF] JspServlet class not found
    Par anitshka dans le forum Servlets/JSP
    Réponses: 5
    Dernier message: 22/07/2005, 10h44
  5. [EJB Session] class not found exception ?
    Par champion dans le forum Wildfly/JBoss
    Réponses: 4
    Dernier message: 11/02/2005, 23h46

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