Start project PHP Back.
50% routes.
This commit is contained in:
37
src/Domain/Controller.php
Normal file
37
src/Domain/Controller.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domain;
|
||||
|
||||
use App\Http\Route;
|
||||
|
||||
abstract class Controller {
|
||||
|
||||
/**
|
||||
* Va permettre de créer une route en préremplissant certains arguments.
|
||||
* Pour les paramètres, veuillez voir le constructeur d'une Route.
|
||||
*
|
||||
* @param mixed ...$args
|
||||
* @return Route
|
||||
*
|
||||
* @see Route::__construct()
|
||||
*/
|
||||
public static function Route( ...$args ): Route {
|
||||
$defaults = [
|
||||
'routeController' => static::class,
|
||||
'routeMethods' => [ 'GET' ],
|
||||
];
|
||||
|
||||
$args = array_merge($defaults, $args);
|
||||
return new Route( ...$args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet de définir les routes du controller sous le format d'une liste d'objets Route.
|
||||
* Vous pouvez utiliser la method self::Route() pour préremplir des champs.
|
||||
*
|
||||
* @return Route[]
|
||||
* @see self::Route()
|
||||
*/
|
||||
abstract public static function defineRoutes(): array;
|
||||
|
||||
}
|
||||
34
src/Domain/Pages/PagesController.php
Normal file
34
src/Domain/Pages/PagesController.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domain\Pages;
|
||||
|
||||
use App\Domain\Controller;
|
||||
|
||||
/**
|
||||
* Controller pour les pages sans lien avec un contenu spécifique.
|
||||
* Exemple : Page d'accueil.
|
||||
*/
|
||||
class PagesController extends Controller {
|
||||
|
||||
public static function defineRoutes(): array
|
||||
{
|
||||
return [
|
||||
self::Route( routeUrl: '/', routeName: 'Homepage', routeAction: 'index' ),
|
||||
self::ROute( routeUrl: '/test/{int}', routeName: 'test', routeAction: 'test' ),
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Route de la page d'accueil.
|
||||
* @return void
|
||||
*/
|
||||
public function index(): void {
|
||||
echo "Coucou";
|
||||
}
|
||||
|
||||
public function test( int $id ): void {
|
||||
echo "Coucou" . $id;
|
||||
}
|
||||
|
||||
}
|
||||
28
src/Exceptions/ConfigFailedLoadingException.php
Normal file
28
src/Exceptions/ConfigFailedLoadingException.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
/**
|
||||
* Exception qui se déclenche lorsqu'un fichier de configuration n'a pas pu être chargé.
|
||||
*
|
||||
* - Peut se déclencher si un fichier de configuration non voulu.
|
||||
*/
|
||||
class ConfigFailedLoadingException extends \Exception {
|
||||
|
||||
/**
|
||||
* Chemin vers le fichier de configuration manquant.
|
||||
* @var string
|
||||
*/
|
||||
public private(set) string $configFilePath;
|
||||
|
||||
/**
|
||||
* Constructeur.
|
||||
* @param string $configFilePath Le fichier de configuration manquant.
|
||||
*/
|
||||
public function __construct( string $configFilePath ) {
|
||||
$this->configFilePath = $configFilePath;
|
||||
$this->message = "Failed to load configuration file '{$configFilePath}'.";
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
}
|
||||
15
src/Exceptions/InvalidRouteException.php
Normal file
15
src/Exceptions/InvalidRouteException.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
class InvalidRouteException extends \Exception {
|
||||
|
||||
private string $clientRoute;
|
||||
|
||||
public function __construct(string $clientRoute)
|
||||
{
|
||||
$this->clientRoute = $clientRoute;
|
||||
$message = "{$clientRoute} doesn't exist";
|
||||
parent::__construct($message, 404);
|
||||
}
|
||||
|
||||
}
|
||||
38
src/Helpers/AutoLoader.php
Normal file
38
src/Helpers/AutoLoader.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
namespace App\Helpers;
|
||||
|
||||
/**
|
||||
* Classe utilitaire contenant des méthodes pour charger automatiquement les classes.
|
||||
*/
|
||||
class AutoLoader {
|
||||
|
||||
/**
|
||||
* Namespace principal de l'application.
|
||||
*/
|
||||
public const string PRIMARY_NAMESPACE = 'App\\';
|
||||
|
||||
/**
|
||||
* Permet d'enregistrer la méthode _autoload_ en tant que méthode pour charger des classes.
|
||||
* @return void
|
||||
*/
|
||||
public static function register(): void {
|
||||
spl_autoload_register( [ self::class, '_autoload_' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet de charger une classe.
|
||||
*
|
||||
* @param string $className
|
||||
* @return void
|
||||
*/
|
||||
public static function _autoload_( string $className ): void {
|
||||
if( !str_starts_with( $className, self::PRIMARY_NAMESPACE ) ) // Ne s'occupe que des classes à charger de cette application.
|
||||
return;
|
||||
|
||||
$className = str_replace( self::PRIMARY_NAMESPACE, '', $className );
|
||||
$className = str_replace( '\\', '/', $className );
|
||||
|
||||
require APP_ROOT . 'src/' . $className . '.php';
|
||||
}
|
||||
|
||||
}
|
||||
1
src/Helpers/CacheManager.php
Normal file
1
src/Helpers/CacheManager.php
Normal file
@@ -0,0 +1 @@
|
||||
<?php
|
||||
42
src/Helpers/ConfigFactory.php
Normal file
42
src/Helpers/ConfigFactory.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Exceptions\ConfigFailedLoadingException;
|
||||
|
||||
/**
|
||||
* Classe outillage qui permet de charger les fichiers de configuration.
|
||||
*/
|
||||
class ConfigFactory {
|
||||
|
||||
/**
|
||||
* Chemin relatif à partir de APP_ROOT du dossier contenant les fichiers de configuration.
|
||||
*
|
||||
* @see APP_ROOT
|
||||
*/
|
||||
const string CONFIG_RELATIVE_FOLDER = "config/";
|
||||
|
||||
/**
|
||||
* Permet de charger un fichier de configuration.
|
||||
*
|
||||
* @param string $fileName Le nom du fichier de configuration, avec ou sans l'extension .php.
|
||||
* @return array
|
||||
*
|
||||
* @throws ConfigFailedLoadingException
|
||||
*/
|
||||
public static function loadConfigFile( string $fileName ): array {
|
||||
if( !str_ends_with( $fileName, ".php" ) ) {
|
||||
$fileName .= ".php";
|
||||
}
|
||||
|
||||
$filePath = APP_ROOT . self::CONFIG_RELATIVE_FOLDER . $fileName;
|
||||
|
||||
if( !file_exists( $filePath ) ){
|
||||
throw new ConfigFailedLoadingException( "Config file '$fileName' does not exist" );
|
||||
}
|
||||
|
||||
$configArray = require $filePath;
|
||||
return $configArray;
|
||||
}
|
||||
|
||||
}
|
||||
31
src/Http/Route.php
Normal file
31
src/Http/Route.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http;
|
||||
|
||||
/**
|
||||
* Permet de définir une route précise.
|
||||
*/
|
||||
final class Route {
|
||||
|
||||
|
||||
public private(set) string $routeUrl;
|
||||
public private(set) string $routeName;
|
||||
public private(set) string $routeController;
|
||||
public private(set) string $routeAction;
|
||||
public private(set) array $routeMethods;
|
||||
|
||||
public function __construct(
|
||||
string $routeUrl,
|
||||
string $routeName,
|
||||
string $routeController,
|
||||
string $routeAction,
|
||||
array $routeMethods
|
||||
){
|
||||
$this->routeUrl = $routeUrl;
|
||||
$this->routeName = $routeName;
|
||||
$this->routeController = $routeController;
|
||||
$this->routeAction = $routeAction;
|
||||
$this->routeMethods = $routeMethods;
|
||||
}
|
||||
|
||||
}
|
||||
158
src/Http/Router.php
Normal file
158
src/Http/Router.php
Normal file
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http;
|
||||
|
||||
use App\Domain\Controller;
|
||||
use App\Exceptions\InvalidRouteException;
|
||||
use App\Helpers\AutoLoader;
|
||||
use FilesystemIterator;
|
||||
|
||||
final class Router {
|
||||
|
||||
/**
|
||||
* Route voulue par le client.
|
||||
* @var string
|
||||
*/
|
||||
public private(set) static string $clientRouteString;
|
||||
|
||||
/**
|
||||
* Informations de la route du client.
|
||||
* @var Route
|
||||
*/
|
||||
public private(set) static Route $clientRoute;
|
||||
|
||||
/**
|
||||
* Liste des controllers sorti du cache ou récupéré via fetchControllers.
|
||||
* @var array
|
||||
*/
|
||||
private static array $controllers;
|
||||
|
||||
/**
|
||||
* Liste des routes tirées des controllers. Rempli par la méthode fetchRoutes.
|
||||
* @var Route[]
|
||||
*/
|
||||
private static array $routes;
|
||||
|
||||
/**
|
||||
* Fonction principale qui va router le contenu vers la bonne méthode du bon Controlleur.
|
||||
* @return void
|
||||
*
|
||||
* @throws InvalidRouteException Si la route voulue n'existe pas ou n'est pas bien formaté.
|
||||
*/
|
||||
public static function routeTo(): void {
|
||||
|
||||
self::$clientRouteString = $_SERVER['REQUEST_URI'];
|
||||
|
||||
self::$controllers = self::fetchControllers();
|
||||
self::$routes = self::fetchRoutes();
|
||||
|
||||
$clientRoute = self::clientRouteExist();
|
||||
if( !$clientRoute ){
|
||||
throw new InvalidRouteException( self::$clientRouteString );
|
||||
}
|
||||
self::$clientRoute = $clientRoute;
|
||||
|
||||
if( !in_array( $_SERVER['REQUEST_METHOD'], self::$clientRoute->routeMethods ) ){
|
||||
throw new InvalidRouteException( self::$clientRouteString );
|
||||
} else {
|
||||
self::executeRouteAction();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet de récupérer tous les controllers du dossier Domain.
|
||||
* @return class-string[]
|
||||
*/
|
||||
private static function fetchControllers(): array {
|
||||
|
||||
$classes = [];
|
||||
|
||||
$iterator = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator( APP_ROOT . 'src/Domain', FilesystemIterator::SKIP_DOTS ),
|
||||
);
|
||||
|
||||
foreach( $iterator as $file ){
|
||||
|
||||
if( $file->isFile() && $file->getExtension() === 'php' ){
|
||||
|
||||
$fileName = $file->getPathname();
|
||||
|
||||
// Transformation du chemin du fichier vers le nom complet de la classe.
|
||||
$fileName = str_replace( APP_ROOT . 'src/', AutoLoader::PRIMARY_NAMESPACE, $fileName );
|
||||
$fileName = str_replace( '.php', '', $fileName );
|
||||
$fileName = str_replace( '/', '\\', $fileName );
|
||||
|
||||
|
||||
/*
|
||||
* Vérifie que l'on est bien sur un Controller.
|
||||
* Ignore Controller car Controller n'est pas une sous-classe de Controller.
|
||||
*/
|
||||
if( is_subclass_of( $fileName, Controller::class ) ){
|
||||
$classes[] = $fileName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $classes;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupérer toutes les routes des controllers récupéré avant.
|
||||
* @return Route[]
|
||||
*/
|
||||
private static function fetchRoutes(): array {
|
||||
|
||||
$routes = [];
|
||||
|
||||
foreach( self::$controllers as $controllerClassString ){
|
||||
$routes = array_merge( $routes, $controllerClassString::defineRoutes() );
|
||||
}
|
||||
|
||||
return $routes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet de savoir si la route que le client veut existe.
|
||||
* @return Route|bool Retourne la route de l'utilisateur ou false si inexistante.
|
||||
*/
|
||||
private static function clientRouteExist(): Route|bool {
|
||||
|
||||
foreach( self::$routes as $route ){
|
||||
/*
|
||||
if( preg_match( self::getRegexRoute( $route), self::$clientRouteString, $matches ) ){
|
||||
var_dump( $matches );
|
||||
}
|
||||
*/
|
||||
/*
|
||||
if( $route->routeUrl === self::$clientRouteString ){
|
||||
return $route;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
private static function getRegexRoute( Route $route ): string {
|
||||
$routeUrl = $route->routeUrl;
|
||||
$routeUrl = str_replace( "{int}", "([0-9]+)", $routeUrl );
|
||||
return $routeUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Va permettre d'exécuter la méthode du Controller->action() en parsant les arguments si existants.
|
||||
* @return void
|
||||
*/
|
||||
private static function executeRouteAction(): void {
|
||||
$controller = self::$clientRoute->routeController;
|
||||
$method = self::$clientRoute->routeAction;
|
||||
|
||||
new $controller()->$method();
|
||||
}
|
||||
|
||||
}
|
||||
93
src/Kernel.php
Normal file
93
src/Kernel.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
use App\Exceptions\ConfigFailedLoadingException;
|
||||
use App\Exceptions\InvalidRouteException;
|
||||
use App\Helpers\AutoLoader;
|
||||
use App\Helpers\ConfigFactory;
|
||||
use App\Http\Router;
|
||||
|
||||
/**
|
||||
* Classe primaire du site.
|
||||
* Permet de lancer l'application.
|
||||
*/
|
||||
final class Kernel {
|
||||
|
||||
/**
|
||||
* Liste des fichiers de configuration sous le format suivant :
|
||||
* [ 'nom_de_la_config' -> [ 'cle" → valeur ] ]
|
||||
*
|
||||
* @var array<string,array>
|
||||
*/
|
||||
public private(set) static array $configs = [];
|
||||
|
||||
/**
|
||||
* Instance actuelle de l'application.
|
||||
* @var Kernel|null
|
||||
*/
|
||||
private static ?self $instance = null;
|
||||
|
||||
/**
|
||||
* Méthode qui permet de démarrer le site.
|
||||
* @return self
|
||||
*/
|
||||
public static function start(): self {
|
||||
self::$instance = new self();
|
||||
self::$instance->init();
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet d'obtenir l'instance actuelle du site.
|
||||
* @return self
|
||||
*/
|
||||
public static function getInstance(): self {
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur.
|
||||
*/
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet de préparer le démarrage du site.
|
||||
* Lancé automatiquement par start().
|
||||
*
|
||||
* @return void
|
||||
* @see self::start()
|
||||
*/
|
||||
public function init(): void {
|
||||
$this->buildAutoloader();
|
||||
$this->loadConfig();
|
||||
|
||||
try {
|
||||
Router::routeTo();
|
||||
} catch ( InvalidRouteException $e ){
|
||||
die( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet de mettre en place l'Autoloader.
|
||||
* @return void
|
||||
*/
|
||||
private function buildAutoloader(): void {
|
||||
require_once 'Helpers/AutoLoader.php';
|
||||
AutoLoader::register();
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet de charger tous les fichiers de configuration du site.
|
||||
* @return void
|
||||
*/
|
||||
private function loadConfig(): void {
|
||||
try {
|
||||
self::$configs['general'] = ConfigFactory::loadConfigFile('general');
|
||||
} catch( ConfigFailedLoadingException $e ){
|
||||
die( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user