Bonsoir. Je continue à apprendre le développement d'application grâce au cour: Mise en pratique de la POO en PHP. Je fais fasse à une difficulté de chargement de classe lorsque je crée les différentes routes. En effet, j'ai entrepris de modéliser la partie de la définition des "routes" de mon routeur. Ainsi, le path, le callable ainsi que le nom de la route proviennent directement de la base de données.
Ce que j'ai fais est le suivant:
<?php
namespace App\Unit\Administrative;
use App\Core\Entity\Route;
use App\Core\Table\ModuleTable;
use App\Core\Table\RouteTable;
use App\Core\Table\RouteTypeTable;
use App\Unit\Administrative\Action\BoroughCrudAction;
use App\Unit\Administrative\Action\CantonCrudAction;
use App\Unit\Administrative\Action\ContinentCrudAction;
use App\Unit\Administrative\Action\CountryCrudAction;
use App\Unit\Administrative\Action\DepartmentCrudAction;
use App\Unit\Administrative\Action\LocalityCrudAction;
use App\Unit\Administrative\Action\RegionCrudAction;
use Framework\Database\QueryResult;
use Framework\Module;
use Framework\Renderer\RendererInterface;
use Framework\Router;
use PDO;
use Psr\Container\ContainerInterface;
class AdministrativeUnitModule extends Module
{
public const DEFINITIONS = __DIR__.'/config.php';
public const MIGRATIONS = __DIR__.'/db/migrations';
public const SEEDS = __DIR__.'/db/seeds';
public function __construct(ContainerInterface $container)
{
// Ajoute le chemin racine pour les vues
$container->get(RendererInterface::class)->addPath('unit',__DIR__.'/views');
/** @var Router $router */
$router = $container->get(Router::class);
// Récupère le prefix prévu pour l'administration
$adminPrefix = $container->get('admin.prefix');
// Récupère le prefix pour l'espace de développeur
$unitPrefix = $container->get('unit.prefix');
/** @var PDO $pdo */
$pdo = $container->get(PDO::class);
/** @var RouteTable $routeTable */
$routeTable = new RouteTable($pdo);
/** @var RouteTypeTable $routeTypeTable */
$routeTypeTable = new RouteTypeTable($pdo);
/** @var ModuleTable $moduleTable */
$moduleTable = new ModuleTable($pdo);
/** @var QueryResult $routes */
$routes = $routeTable->makeQuery()
->select('r.*', 'm.id', 'rT.route_type_name as routeTypeName')
->join($routeTypeTable->getTable().' as rT', 'rT.id = r.route_type_id', 'inner')
->join($moduleTable->getTable().' as m', 'm.id = r.module_id', 'inner')
->where('m.id = 1')
->fetchAll();
foreach ($routes as $route) {
/** @var Route $xRoute */
$xRoute = $route;
switch ($xRoute->getRouteTypeName())
{
case 'CRUD':
$router->crud($adminPrefix.$unitPrefix.'/'.$xRoute->getPath(), $xRoute->getCallable(), $xRoute->getName());
break;
case 'POST':
$router->post($unitPrefix.'/'.$xRoute->getPath(), $xRoute->getCallable());
break;
case 'GET':
$router->get($unitPrefix.'/'.$xRoute->getPath(), $xRoute->getCallable(), $xRoute->getName());
break;
case 'DELETE':
$router->delete($unitPrefix.'/'.$xRoute->getPath(), $xRoute->getCallable());
break;
case 'PUT':
break;
}
}
}
}
Ci-dessous, le contenu de ma table en base de données:
********************************************************************************************
* path * callable * name * Description *
********************************************************************************************
1 * departments * Department::class * unit.admin.departments * Gestion des départements *
2 * boroughs * BoroughCrudAction::class * unit.admin.boroughs * Gestion des arrondissements *
3 * cantons * CantonCrudAction::class * unit.admin.cantons * Groupements ou cantons *
4 * localities * LocalityCrudAction::class * unit.admin.localities * Gestion des localités *
5 * regions * RegionCrudAction::class * unit.admin.regions * Gestion des régions *
6 * countries * CountryCrudAction::class * unit.admin.countries * Gestion des pays *
7 * continents * ContinentCrudAction::class * unit.admin.continents * Gestion des continents *
*********************************************************************************************
Ce que je souhaite, c'est de pouvoir inscrire mes routes, un peu comme dans le Blog:
public function __construct(ContainerInterface $container)
{
// On décrit les différentes routes (liens) et les fonctions à appeler
$router = $container->get(Router::class);
$prefix = $container->get('blog.prefix');
$router->get($prefix, PostIndexAction::class, 'blog.index');
$router->get($prefix . '/{slug:[a-z\-0-9]+}-{id:[0-9]+}', PostShowAction::class, 'blog.show');
$router->get($prefix . '/categories/{slug:[a-z\-0-9]+}', CategoryShowAction::class, 'blog.category');
//On ajoute le namespace pour charger les vues du module
$container->get(RendererInterface::class)->addPath('blog', __DIR__ . '/views');
//On Cherche à savoir si la page d'administration (blog.prefix) a été charger dans le container
if ($container->has('admin.prefix')) {
$prefixAdmin = $container->get('admin.prefix');
$router->crud("$prefixAdmin" . "/posts", PostCrudAction::class, 'blog.admin');
$router->crud("$prefixAdmin" . "/categories", CategoryCrudAction::class, 'blog.category.admin');
}
}
Ce qui marche très bien tant que les paramètres ne viennent pas pas de la base de données.
Lorsque je veux par exemple accéder à l'url mondomaine.com/admin/unit/localities, j'ai l'erreur suivante:
DI \ NotFoundException
No entry or class found for 'LocalityCrudAction::class'
Il en est de même pour les URL que je fabrique dynamiquement. Pour ce cas, le serveur interprète le contenu de la variable xRoute->getCallable() comme une simple chaîne de caractères, qui en réalité est le nom d'une classe (Exemple : LocalityCrudAction::class) qui devrait automatiquement appelé la méthode __invoke().
Je suis coincé.
J'ai trouvé moi-même la réponse. En effet, les différents use:
use App\Unit\Administrative\Action\BoroughCrudAction;
use App\Unit\Administrative\Action\CantonCrudAction;
use App\Unit\Administrative\Action\ContinentCrudAction;
use App\Unit\Administrative\Action\CountryCrudAction;
use App\Unit\Administrative\Action\DepartmentCrudAction;
use App\Unit\Administrative\Action\LocalityCrudAction;
use App\Unit\Administrative\Action\RegionCrudAction;
que j'ai mis en haut de ma classe ne sont pas injecter automatiquement dans le routeur dans le routeur. En plus, le suffix ::class a la fin de chaque class tel qu'indiqué de manière classique n'est pas necéssaire au moment d'injecter dynamiquement les callabe dans le routeur.
Pour résourdre le problème, il faut remarquer que mes callables sont dans un seul dossier (Action). Donc, j'ai crée un prefix :
$loaderPrefix = 'App\\Unit\\Administrative\\Action\\';
Puis, je le concatène à la chaine qui permet de renseigner le callable
$router->crud($adminPrefix.$unitPrefix.'/'.$xRoute->getPath(), $loaderPrefix.$xRoute->getCallable(), $xRoute->getName());
Ainsi, le reste a marché tout simplement.