Bonjour,
J'ai décidé de passer d'un Cakephp à une structure beaucoup plus simple pour mon site via Slim.
J'ai donc regardé le tuto Slim de Grafikart, et j'ai voulu mettre en place une structure similaire à la sienne (avec le Router, Controller, ...) en utilisant les namespaces et l'autoloader de composer.
Je précise que j'ai encore du mal avec les namespaces (je découvre seulement).
Mon problème est que lorsque je tente d'accèder à mon site (en utilisant les namespaces et l'autoloader) j'ai cette erreur :
Fatal error: Class 'App\Core\Router' not found
Alors que tout se passe bien si je require mes classes à la main et que je ne les mets pas dans un namespace.
J'ai mis mon router et mes controller dans le namespace App\Core.
j'ai tenté en ajoutant :
"autoload": {
"psr-4": {"App\\Core\\": "app" }
}
et
"autoload": {
"psr-4": {"App\\": "app" }
}
à mon composer.js mais j'ai toujours une erreur. J'aimerais donc bien comprendre comment ça se fait.
Alors je ne pense pas que le "Core" soit justifié dans ton cas. Le namespace App\ donc dans ton composer tu fais
"autoload": {
"psr-4": {"App\\": "app/" }
}
Puis tu n'oublie pas de rechercher l'autoloader avec
composer dump-autoload
Et ta classe Router tu met
namespace App;
class Router{
}
C'est la première chose que j'ai tenté mais ça me retourne une erreur de syntaxte (détectée par phpstorm par ailleurs). Ce qui donne l'erreur php suivante :
Parse error: syntax error, unexpected '$controller_name' (T_VARIABLE), expecting identifier (T_STRING)
Du coup, j'ai été relire un peu la doc php, et j'ai trouvé comment préciser un namespace lors de l'appelle d'une class de cette façon là :
$controller_name = '\\App\\' . $action[0] . 'Controller';
Mais, maintenant il me dit qu'il ne trouve pas ma class :
Fatal error: Class '\App\IndexController' not found
Pour que ça fonctionne j'ai du ajouter à la main les require de mes classes. Comme si l'autoloader ne les avaient pas pris en compte lors de l'autoload. Du coup, est-ce qu'il y a une manipulation spéciale à faire pour dire à l'autoloader de charger aussi les fichiers de tous les sous dossier de app/ ?
EDIT : C'est bon j'ai trouvé la réponse à ma question dans la doc de composer. Je suis vraiment trop con, je suis passé 3-4 fois dans la doc, et je n'arrivais pas à trouver ma réponse xD
Au final j'ai fait comme ça :
"autoload": {
"psr-4": {
"App\\": ["app/", "app/Controller/"]
}
}
Si il y a une autre méthode, je suis tout ouïe :)
Un simple
$controller_name = '\\App\\Controller\\' . $action[0] . 'Controller';
Vu que tu lui dit que App est dans app il suffit de lui lui ajouter Controller au namespace pour qu'il cherche dedans.
En psr-4 les namespace suivent l'architectute des dossiers donc si tu lui dit que ton namespace App est dans le dossier app si tu veux IndexController qui est dans le dossier controller et faut mettre ce que j'ai mit plus haut sinon il cherche IndexController à la racine du dossier app
Ah oui, j'ai oublié de l'ajouter à mon post :D
app\
app\Controller
Controller.php
mes controllers
app\Router.php
Merci Graf' !
J'avais utilisé le App\Core pour différencier les classes propre au coeur de mon app et ceux de mes helpers (Que je comptais mettre dans App\helper par exemple).
J'ai encore une question, via l'autoloader, il inclus tout ce qui se trouve dans le namespace précisé. Du coup mes controllers qui se trouve aussi dans le namespace App\ sont inclus, mais, comment je dois faire pour les appeler ?
Un exemple plus concret, si je reprends ton tuto sur Slim, dans ton Router.php tu appelles tes controllers via :
$controller = new $controller_name($this->app);
call_user_func_array([$controller, $method], func_get_args());
Comment intégrer les namespaces dans ce genre de cas ?
Et tant que j'y suis, y a-t-il des bonnes pratiques pour les namespaces, les pièges à éviter ?