update php's tp

master
Antoine PEREDERII 1 year ago
parent 985667699a
commit f272f48ca7

@ -0,0 +1,22 @@
<?php
namespace Classes;
class Personne {
private $nom;
private $prenom;
private $anneeNaissance;
private $email;
// Constructeur
public function __construct($nom, $prenom, $anneeNaissance, $email) {
$this->nom = $nom;
$this->prenom = $prenom;
$this->anneeNaissance = $anneeNaissance;
$this->email = $email;
}
// Méthode magique pour l'affichage
public function __toString() {
return "Nom: {$this->nom}, Prénom: {$this->prenom}, Année de Naissance: {$this->anneeNaissance}, Email: {$this->email}";
}
}

@ -0,0 +1,19 @@
<?php
class Validation {
// Méthode pour valider une adresse email
public static function validerEmail($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL);
}
public static function validerAge($age) {
return filter_var($age, FILTER_VALIDATE_INT);
}
// Méthode pour nettoyer une chaîne de caractères
public static function nettoyerChaine($chaine) {
return filter_var($chaine, FILTER_DEFAULT);
}
}
?>

@ -1,10 +0,0 @@
<html>
<body>
<?php
// foreach ($tab as $t)
// echo $t . "</br>";
echo "hello world";
?>
</body>
</html>

@ -0,0 +1,22 @@
<?php
// Initialise le tableau TMessage avec des messages d'erreur
//$TMessage = ['Division par zéro', 'Valeur invalide'];
//
//// Inclut la page fonction.php pour pouvoir apeler les fonctions
//require('fonction.php');
//
//// Exemples d'utilisation
//echo pourcentageAvis('favorable', 10, 40) . "<br>";
//echo pourcentageAvis('defavorable', 10, 40) . "<br>";
//
//echo pourcentageAvis2("defavorable", 5, 8, $TMessage) . "<br>";
//echo pourcentageAvis2("defavorable", 0, 0, $TMessage) . "<br>";
//
//// Inclut la page erreur.php pour afficher les messages d'erreur
//require('erreur.php');
require('testPersonne.php');
require('testPersonnes.php');
require('saisirPersonne.php');
?>

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Erreur</title>
</head>
<body>
<h1>Messages d'erreur :</h1>
<?php
// Vérifie si le tableau TMessage est défini
if (!empty($TMessage)) {
// Parcourir le tableau TMessage et afficher chaque message d'erreur
echo "<ul>";
foreach ($TMessage as $erreur) {
echo "<li>$erreur</li>";
}
echo "</ul>";
} else {
echo "<p>Aucun message d'erreur à afficher.</p>";
}
?>
</body>
</html>

@ -0,0 +1,50 @@
<?php
function pourcentageAvis(string $typeAvis, int $nbAvisFav, int $nbAvisDefav): string
{
// Vérifier que le type d'avis est soit "favorable" soit "defavorable"
if ($typeAvis !== 'favorable' && $typeAvis !== 'defavorable') {
return "Type d'avis non valide.";
}
// Calculer le pourcentage en fonction du type d'avis
$totalAvis = $nbAvisFav + $nbAvisDefav;
if ($totalAvis === 0) {
return "Aucun avis disponible.";
}
$pourcentage = ($typeAvis === 'favorable') ? ($nbAvisFav / $totalAvis) * 100 : ($nbAvisDefav / $totalAvis) * 100;
// Formater le résultat
return "Le pourcentage d'avis de type $typeAvis est de : " . number_format($pourcentage, 2) . "%";
}
function pourcentageAvis2(string $typeAvis, int $nbAvisFav, int $nbAvisDefav, array &$TMessage): string
{
// Vérifier que le type d'avis est soit "favorable" soit "defavorable"
if ($typeAvis !== 'favorable' && $typeAvis !== 'defavorable') {
return "Type d'avis non valide.";
}
try {
// Calculer le pourcentage en fonction du type d'avis
$totalAvis = $nbAvisFav + $nbAvisDefav;
if ($totalAvis === 0) {
throw new Exception("Division par zéro - Aucun avis disponible.");
}
$pourcentage = ($typeAvis === 'favorable') ? ($nbAvisFav / $totalAvis) * 100 : ($nbAvisDefav / $totalAvis) * 100;
// Formater le résultat
return "Le pourcentage d'avis de type $typeAvis est de : " . number_format($pourcentage, 2) . "%";
} catch (Exception $e) {
// En cas d'erreur, ajouter le message dans la table TMessage
$TMessage[] = $e->getMessage();
return "Attention : calcul du pourcentage impossible - division par zéro";
}
}
?>

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Saisie de Personne</title>
</head>
<body>
<h1>Saisie de Personne</h1>
<form action="verif.php" method="post">
<label for="nom">Nom :</label>
<input type="text" name="nom" id="nom" required>
<br>
<label for="prenom">Prénom :</label>
<input type="text" name="prenom" id="prenom" required>
<br>
<br>
<label for="age">Age :</label>
<input type="text" name="age" id="age" required>
<br>
<label for="email">Email :</label>
<input type="email" name="email" id="email" required>
<br>
<input type="submit" value="Valider">
</form>
</body>
</html>

@ -0,0 +1,12 @@
<?php
// Inclusion de la classe Personne
require_once('../classes/Personne.php');
use Classes\Personne;
// Instanciation de la classe Personne
$unePersonne = new Personne("Doe", "John", 1990, "john.doe@example.com");
// Affichage des propriétés à l'aide de la méthode magique __toString()
echo $unePersonne;

@ -0,0 +1,25 @@
<?php
// Inclure la classe Personne
require_once('../classes/Personne.php');
use Classes\Personne;
// Instancier plusieurs objets Personne
$personnes = [
new Personne("Doe", "John", 1990, "john.doe@example.com"),
new Personne("Smith", "Jane", 1985, "jane.smith@example.com"),
new Personne("DEoe", "Johqn", 1990, "john.doe@exdample.com"),
new Personne("Smsith", "Jaddne", 100, "jane.smithdd@example.com"),
new Personne("Dodsfe", "Johqzn", 1990, "john.doe@dexample.com"),
new Personne("Smitdfsh", "Jazne", 1985, "jane.smidsth@example.com"),
new Personne("Dcxvoe", "Johne", 1990, "john.doe@exdsample.com"),
new Personne("Smcxith", "Janee", 1985, "jane.smith@dsexample.com"),
// Ajoutez autant d'instances que nécessaire
];
// Appeler le script de vue
require('vuePersonnes.php');
?>

@ -0,0 +1,43 @@
<?php
require_once('../classes/Personne.php');
require_once('../classes/Validation.php');
use Classes\Personne;
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// Récupérer les données du formulaire
$nom = $_POST['nom'];
$prenom = $_POST['prenom'];
$age = $_POST['age'];
$email = $_POST['email'];
// Utiliser la classe Validation pour valider l'adresse email
if (!Validation::validerEmail($email)) {
die("Adresse email invalide");
}
// Utiliser la classe Validation pour valider l'age
if (!Validation::validerAge($age)) {
die("Age invalide");
}
// Utiliser la classe Validation pour nettoyer le nom et le prénom
$nom = Validation::nettoyerChaine($nom);
$prenom = Validation::nettoyerChaine($prenom);
// Créer une instance de la classe Personne
$personne = new Personne($nom, $prenom, $age, $email);
// Afficher les données saisies, filtrées et nettoyées
echo "Nom : " . $nom . "<br>";
echo "Prénom : " . $prenom . "<br>";
echo "Age : " . $age . "<br>";
echo "Email : " . $email . "<br>";
echo "<h2>Instance de Personne :</h2>";
echo "$personne";
} else {
// Rediriger vers la page de saisie si la requête n'est pas POST
header("Location: saisirPersonne.php");
}
?>

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue des Personnes</title>
</head>
<body>
<h1>Liste des Personnes</h1>
<ul>
<?php
// Parcourir le tableau de personnes et afficher les propriétés
foreach ($personnes as $personne) {
echo "<li>{$personne}</li>";
}
?>
</ul>
</body>
</html>

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/mvc_PSR4_twig/config" isTestSource="false" packagePrefix="config\" />
<sourceFolder url="file://$MODULE_DIR$/mvc_PSR4_twig/controleur" isTestSource="false" packagePrefix="controleur\" />
<sourceFolder url="file://$MODULE_DIR$/mvc_PSR4_twig/modeles" isTestSource="false" packagePrefix="modeles\" />
<excludeFolder url="file://$MODULE_DIR$/mvc_PSR4_twig/vendor/composer" />
<excludeFolder url="file://$MODULE_DIR$/mvc_PSR4_twig/vendor/symfony/polyfill-ctype" />
<excludeFolder url="file://$MODULE_DIR$/mvc_PSR4_twig/vendor/symfony/polyfill-mbstring" />
<excludeFolder url="file://$MODULE_DIR$/mvc_PSR4_twig/vendor/twig/twig" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/5_tp.iml" filepath="$PROJECT_DIR$/.idea/5_tp.iml" />
</modules>
</component>
</project>

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MessDetectorOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCSFixerOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCodeSnifferOptionsConfiguration">
<option name="highlightLevel" value="WARNING" />
<option name="transferred" value="true" />
</component>
<component name="PhpIncludePathManager">
<include_path>
<path value="$PROJECT_DIR$/mvc_PSR4_twig/vendor/symfony/polyfill-mbstring" />
<path value="$PROJECT_DIR$/mvc_PSR4_twig/vendor/symfony/polyfill-ctype" />
<path value="$PROJECT_DIR$/mvc_PSR4_twig/vendor/composer" />
<path value="$PROJECT_DIR$/mvc_PSR4_twig/vendor/twig/twig" />
</include_path>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="7.0">
<option name="suggestChangeDefaultLanguageLevel" value="false" />
</component>
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PsalmOptionsConfiguration">
<option name="transferred" value="true" />
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../../.." vcs="Git" />
</component>
</project>

@ -8,10 +8,6 @@
<body> <body>
<h1>ERREUR page !!!!!</h1> <h1>ERREUR page !!!!!</h1>
{% if dVueEreur is defined %}
{% for value in dVueEreur %}
<p>{{value}}</p> <p>{{value}}</p>
{% endfor %}
{% endif %}
</body> </body>
</html> </html>

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="a263194b-24d5-4f6d-967d-4d377d6e129f" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/../1_tp/scripts/Affichage.php" afterDir="false" />
<change afterPath="$PROJECT_DIR$/../1_tp/scripts/erreur.php" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../1_tp/erreur.php" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/../1_tp/final.php" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/../5_tp/mvc_PSR4_twig/templates/erreur.html" beforeDir="false" afterPath="$PROJECT_DIR$/../5_tp/mvc_PSR4_twig/templates/erreur.html" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ComposerSettings" synchronizationState="SYNCHRONIZE">
<pharConfigPath>$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/composer.json</pharConfigPath>
<execution>
<executable path="composer" />
</execution>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/../../.." />
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="PhpWorkspaceProjectConfiguration" interpreter_name="/opt/homebrew/bin/php">
<include_path>
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/myclabs/deep-copy" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/squizlabs/php_codesniffer" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/phpunit/php-timer" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/phpunit/phpunit" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/phpunit/php-text-template" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/phpunit/php-invoker" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/phpunit/php-file-iterator" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/phpunit/php-code-coverage" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/sebastian/type" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/sebastian/diff" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/sebastian/lines-of-code" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/sebastian/object-enumerator" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/sebastian/comparator" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/sebastian/code-unit" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/sebastian/cli-parser" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/sebastian/exporter" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/sebastian/version" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/sebastian/complexity" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/sebastian/recursion-context" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/sebastian/resource-operations" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/sebastian/code-unit-reverse-lookup" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/sebastian/global-state" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/sebastian/environment" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/sebastian/object-reflector" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/theseer/tokenizer" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/nikic/php-parser" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/phar-io/version" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/phar-io/manifest" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/composer" />
<path value="$PROJECT_DIR$/dannyvankooten-AltoRouter-ac028a7/vendor/doctrine/instantiator" />
</include_path>
</component>
<component name="ProjectColorInfo"><![CDATA[{
"associatedIndex": 1
}]]></component>
<component name="ProjectId" id="2Y9lWVsZE3aFjiLhWo3KQuOPX8d" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"WebServerToolWindowFactoryState": "false",
"git-widget-placeholder": "master",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"vue.rearranger.settings.migration": "true"
}
}]]></component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="a263194b-24d5-4f6d-967d-4d377d6e129f" name="Changes" comment="" />
<created>1699945708174</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1699945708174</updated>
<workItem from="1699945709450" duration="4785000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
</project>

@ -0,0 +1,3 @@
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]

@ -0,0 +1,302 @@
<?php
/*
MIT License
Copyright (c) 2012 Danny van Kooten <hi@dannyvankooten.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
class AltoRouter
{
/**
* @var array Array of all routes (incl. named routes).
*/
protected $routes = [];
/**
* @var array Array of all named routes.
*/
protected $namedRoutes = [];
/**
* @var string Can be used to ignore leading part of the Request URL (if main file lives in subdirectory of host)
*/
protected $basePath = '';
/**
* @var array Array of default match types (regex helpers)
*/
protected $matchTypes = [
'i' => '[0-9]++',
'a' => '[0-9A-Za-z]++',
'h' => '[0-9A-Fa-f]++',
'*' => '.+?',
'**' => '.++',
'' => '[^/\.]++'
];
/**
* Create router in one call from config.
*
* @param array $routes
* @param string $basePath
* @param array $matchTypes
* @throws Exception
*/
public function __construct(array $routes = [], $basePath = '', array $matchTypes = [])
{
$this->addRoutes($routes);
$this->setBasePath($basePath);
$this->addMatchTypes($matchTypes);
}
/**
* Retrieves all routes.
* Useful if you want to process or display routes.
* @return array All routes.
*/
public function getRoutes()
{
return $this->routes;
}
/**
* Add multiple routes at once from array in the following format:
*
* $routes = [
* [$method, $route, $target, $name]
* ];
*
* @param array $routes
* @return void
* @author Koen Punt
* @throws Exception
*/
public function addRoutes($routes)
{
if (!is_array($routes) && !$routes instanceof Traversable) {
throw new RuntimeException('Routes should be an array or an instance of Traversable');
}
foreach ($routes as $route) {
call_user_func_array([$this, 'map'], $route);
}
}
/**
* Set the base path.
* Useful if you are running your application from a subdirectory.
* @param string $basePath
*/
public function setBasePath($basePath)
{
$this->basePath = $basePath;
}
/**
* Add named match types. It uses array_merge so keys can be overwritten.
*
* @param array $matchTypes The key is the name and the value is the regex.
*/
public function addMatchTypes(array $matchTypes)
{
$this->matchTypes = array_merge($this->matchTypes, $matchTypes);
}
/**
* Map a route to a target
*
* @param string $method One of 5 HTTP Methods, or a pipe-separated list of multiple HTTP Methods (GET|POST|PATCH|PUT|DELETE)
* @param string $route The route regex, custom regex must start with an @. You can use multiple pre-set regex filters, like [i:id]
* @param mixed $target The target where this route should point to. Can be anything.
* @param string $name Optional name of this route. Supply if you want to reverse route this url in your application.
* @throws Exception
*/
public function map($method, $route, $target, $name = null)
{
$this->routes[] = [$method, $route, $target, $name];
if ($name) {
if (isset($this->namedRoutes[$name])) {
throw new RuntimeException("Can not redeclare route '{$name}'");
}
$this->namedRoutes[$name] = $route;
}
return;
}
/**
* Reversed routing
*
* Generate the URL for a named route. Replace regexes with supplied parameters
*
* @param string $routeName The name of the route.
* @param array @params Associative array of parameters to replace placeholders with.
* @return string The URL of the route with named parameters in place.
* @throws Exception
*/
public function generate($routeName, array $params = [])
{
// Check if named route exists
if (!isset($this->namedRoutes[$routeName])) {
throw new RuntimeException("Route '{$routeName}' does not exist.");
}
// Replace named parameters
$route = $this->namedRoutes[$routeName];
// prepend base path to route url again
$url = $this->basePath . $route;
if (preg_match_all('`(/|\.|)\[([^:\]]*+)(?::([^:\]]*+))?\](\?|)`', $route, $matches, PREG_SET_ORDER)) {
foreach ($matches as $index => $match) {
list($block, $pre, $type, $param, $optional) = $match;
if ($pre) {
$block = substr($block, 1);
}
if (isset($params[$param])) {
// Part is found, replace for param value
$url = str_replace($block, $params[$param], $url);
} elseif ($optional && $index !== 0) {
// Only strip preceding slash if it's not at the base
$url = str_replace($pre . $block, '', $url);
} else {
// Strip match block
$url = str_replace($block, '', $url);
}
}
}
return $url;
}
/**
* Match a given Request Url against stored routes
* @param string $requestUrl
* @param string $requestMethod
* @return array|boolean Array with route information on success, false on failure (no match).
*/
public function match($requestUrl = null, $requestMethod = null)
{
$params = [];
// set Request Url if it isn't passed as parameter
if ($requestUrl === null) {
$requestUrl = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/';
}
// strip base path from request url
$requestUrl = substr($requestUrl, strlen($this->basePath));
// Strip query string (?a=b) from Request Url
if (($strpos = strpos($requestUrl, '?')) !== false) {
$requestUrl = substr($requestUrl, 0, $strpos);
}
$lastRequestUrlChar = $requestUrl ? $requestUrl[strlen($requestUrl)-1] : '';
// set Request Method if it isn't passed as a parameter
if ($requestMethod === null) {
$requestMethod = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET';
}
foreach ($this->routes as $handler) {
list($methods, $route, $target, $name) = $handler;
$method_match = (stripos($methods, $requestMethod) !== false);
// Method did not match, continue to next route.
if (!$method_match) {
continue;
}
if ($route === '*') {
// * wildcard (matches all)
$match = true;
} elseif (isset($route[0]) && $route[0] === '@') {
// @ regex delimiter
$pattern = '`' . substr($route, 1) . '`u';
$match = preg_match($pattern, $requestUrl, $params) === 1;
} elseif (($position = strpos($route, '[')) === false) {
// No params in url, do string comparison
$match = strcmp($requestUrl, $route) === 0;
} else {
// Compare longest non-param string with url before moving on to regex
// Check if last character before param is a slash, because it could be optional if param is optional too (see https://github.com/dannyvankooten/AltoRouter/issues/241)
if (strncmp($requestUrl, $route, $position) !== 0 && ($lastRequestUrlChar === '/' || $route[$position-1] !== '/')) {
continue;
}
$regex = $this->compileRoute($route);
$match = preg_match($regex, $requestUrl, $params) === 1;
}
if ($match) {
if ($params) {
foreach ($params as $key => $value) {
if (is_numeric($key)) {
unset($params[$key]);
}
}
}
return [
'target' => $target,
'params' => $params,
'name' => $name
];
}
}
return false;
}
/**
* Compile the regex for a given route (EXPENSIVE)
* @param $route
* @return string
*/
protected function compileRoute($route)
{
if (preg_match_all('`(/|\.|)\[([^:\]]*+)(?::([^:\]]*+))?\](\?|)`', $route, $matches, PREG_SET_ORDER)) {
$matchTypes = $this->matchTypes;
foreach ($matches as $match) {
list($block, $pre, $type, $param, $optional) = $match;
if (isset($matchTypes[$type])) {
$type = $matchTypes[$type];
}
if ($pre === '.') {
$pre = '\.';
}
$optional = $optional !== '' ? '?' : null;
//Older versions of PCRE require the 'P' in (?P<named>)
$pattern = '(?:'
. ($pre !== '' ? $pre : null)
. '('
. ($param !== '' ? "?P<$param>" : null)
. $type
. ')'
. $optional
. ')'
. $optional;
$route = str_replace($block, $pattern, $route);
}
}
return "`^$route$`u";
}
}

@ -0,0 +1,26 @@
<?php
namespace Controller;
Class UserController
{
public function __construct()
{
print 'I am a controller<br>';
}
public function add(array $params): void
{
$id = $params['id'] ?? -1;
print 'using add action ; id:' . $id;
}
public function page(array $params): void
{
$page = $params['page'] ?? -1;
print 'using page action ; page : ' . $page;
}
}
?>

@ -0,0 +1,39 @@
name: PHP
on: [ push, pull_request ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: [ '7.3', '7.4', '8.0', '8.1' ]
steps:
- uses: actions/checkout@v2
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
tools: composer
- name: Validate composer.json and composer.lock
run: composer validate
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install dependencies
if: steps.composer-cache.outputs.cache-hit != 'true'
run: composer install --prefer-dist --no-progress
- name: Run test suite
run: composer run-script test

@ -0,0 +1,302 @@
<?php
/*
MIT License
Copyright (c) 2012 Danny van Kooten <hi@dannyvankooten.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
class AltoRouter
{
/**
* @var array Array of all routes (incl. named routes).
*/
protected $routes = [];
/**
* @var array Array of all named routes.
*/
protected $namedRoutes = [];
/**
* @var string Can be used to ignore leading part of the Request URL (if main file lives in subdirectory of host)
*/
protected $basePath = '';
/**
* @var array Array of default match types (regex helpers)
*/
protected $matchTypes = [
'i' => '[0-9]++',
'a' => '[0-9A-Za-z]++',
'h' => '[0-9A-Fa-f]++',
'*' => '.+?',
'**' => '.++',
'' => '[^/\.]++'
];
/**
* Create router in one call from config.
*
* @param array $routes
* @param string $basePath
* @param array $matchTypes
* @throws Exception
*/
public function __construct(array $routes = [], $basePath = '', array $matchTypes = [])
{
$this->addRoutes($routes);
$this->setBasePath($basePath);
$this->addMatchTypes($matchTypes);
}
/**
* Retrieves all routes.
* Useful if you want to process or display routes.
* @return array All routes.
*/
public function getRoutes()
{
return $this->routes;
}
/**
* Add multiple routes at once from array in the following format:
*
* $routes = [
* [$method, $route, $target, $name]
* ];
*
* @param array $routes
* @return void
* @author Koen Punt
* @throws Exception
*/
public function addRoutes($routes)
{
if (!is_array($routes) && !$routes instanceof Traversable) {
throw new RuntimeException('Routes should be an array or an instance of Traversable');
}
foreach ($routes as $route) {
call_user_func_array([$this, 'map'], $route);
}
}
/**
* Set the base path.
* Useful if you are running your application from a subdirectory.
* @param string $basePath
*/
public function setBasePath($basePath)
{
$this->basePath = $basePath;
}
/**
* Add named match types. It uses array_merge so keys can be overwritten.
*
* @param array $matchTypes The key is the name and the value is the regex.
*/
public function addMatchTypes(array $matchTypes)
{
$this->matchTypes = array_merge($this->matchTypes, $matchTypes);
}
/**
* Map a route to a target
*
* @param string $method One of 5 HTTP Methods, or a pipe-separated list of multiple HTTP Methods (GET|POST|PATCH|PUT|DELETE)
* @param string $route The route regex, custom regex must start with an @. You can use multiple pre-set regex filters, like [i:id]
* @param mixed $target The target where this route should point to. Can be anything.
* @param string $name Optional name of this route. Supply if you want to reverse route this url in your application.
* @throws Exception
*/
public function map($method, $route, $target, $name = null)
{
$this->routes[] = [$method, $route, $target, $name];
if ($name) {
if (isset($this->namedRoutes[$name])) {
throw new RuntimeException("Can not redeclare route '{$name}'");
}
$this->namedRoutes[$name] = $route;
}
return;
}
/**
* Reversed routing
*
* Generate the URL for a named route. Replace regexes with supplied parameters
*
* @param string $routeName The name of the route.
* @param array @params Associative array of parameters to replace placeholders with.
* @return string The URL of the route with named parameters in place.
* @throws Exception
*/
public function generate($routeName, array $params = [])
{
// Check if named route exists
if (!isset($this->namedRoutes[$routeName])) {
throw new RuntimeException("Route '{$routeName}' does not exist.");
}
// Replace named parameters
$route = $this->namedRoutes[$routeName];
// prepend base path to route url again
$url = $this->basePath . $route;
if (preg_match_all('`(/|\.|)\[([^:\]]*+)(?::([^:\]]*+))?\](\?|)`', $route, $matches, PREG_SET_ORDER)) {
foreach ($matches as $index => $match) {
list($block, $pre, $type, $param, $optional) = $match;
if ($pre) {
$block = substr($block, 1);
}
if (isset($params[$param])) {
// Part is found, replace for param value
$url = str_replace($block, $params[$param], $url);
} elseif ($optional && $index !== 0) {
// Only strip preceding slash if it's not at the base
$url = str_replace($pre . $block, '', $url);
} else {
// Strip match block
$url = str_replace($block, '', $url);
}
}
}
return $url;
}
/**
* Match a given Request Url against stored routes
* @param string $requestUrl
* @param string $requestMethod
* @return array|boolean Array with route information on success, false on failure (no match).
*/
public function match($requestUrl = null, $requestMethod = null)
{
$params = [];
// set Request Url if it isn't passed as parameter
if ($requestUrl === null) {
$requestUrl = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/';
}
// strip base path from request url
$requestUrl = substr($requestUrl, strlen($this->basePath));
// Strip query string (?a=b) from Request Url
if (($strpos = strpos($requestUrl, '?')) !== false) {
$requestUrl = substr($requestUrl, 0, $strpos);
}
$lastRequestUrlChar = $requestUrl ? $requestUrl[strlen($requestUrl)-1] : '';
// set Request Method if it isn't passed as a parameter
if ($requestMethod === null) {
$requestMethod = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET';
}
foreach ($this->routes as $handler) {
list($methods, $route, $target, $name) = $handler;
$method_match = (stripos($methods, $requestMethod) !== false);
// Method did not match, continue to next route.
if (!$method_match) {
continue;
}
if ($route === '*') {
// * wildcard (matches all)
$match = true;
} elseif (isset($route[0]) && $route[0] === '@') {
// @ regex delimiter
$pattern = '`' . substr($route, 1) . '`u';
$match = preg_match($pattern, $requestUrl, $params) === 1;
} elseif (($position = strpos($route, '[')) === false) {
// No params in url, do string comparison
$match = strcmp($requestUrl, $route) === 0;
} else {
// Compare longest non-param string with url before moving on to regex
// Check if last character before param is a slash, because it could be optional if param is optional too (see https://github.com/dannyvankooten/AltoRouter/issues/241)
if (strncmp($requestUrl, $route, $position) !== 0 && ($lastRequestUrlChar === '/' || $route[$position-1] !== '/')) {
continue;
}
$regex = $this->compileRoute($route);
$match = preg_match($regex, $requestUrl, $params) === 1;
}
if ($match) {
if ($params) {
foreach ($params as $key => $value) {
if (is_numeric($key)) {
unset($params[$key]);
}
}
}
return [
'target' => $target,
'params' => $params,
'name' => $name
];
}
}
return false;
}
/**
* Compile the regex for a given route (EXPENSIVE)
* @param $route
* @return string
*/
protected function compileRoute($route)
{
if (preg_match_all('`(/|\.|)\[([^:\]]*+)(?::([^:\]]*+))?\](\?|)`', $route, $matches, PREG_SET_ORDER)) {
$matchTypes = $this->matchTypes;
foreach ($matches as $match) {
list($block, $pre, $type, $param, $optional) = $match;
if (isset($matchTypes[$type])) {
$type = $matchTypes[$type];
}
if ($pre === '.') {
$pre = '\.';
}
$optional = $optional !== '' ? '?' : null;
//Older versions of PCRE require the 'P' in (?P<named>)
$pattern = '(?:'
. ($pre !== '' ? $pre : null)
. '('
. ($param !== '' ? "?P<$param>" : null)
. $type
. ')'
. $optional
. ')'
. $optional;
$route = str_replace($block, $pattern, $route);
}
}
return "`^$route$`u";
}
}

@ -0,0 +1,9 @@
MIT License
Copyright (c) 2012 Danny van Kooten <hi@dannyvankooten.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

@ -0,0 +1,57 @@
# AltoRouter ![PHP status](https://github.com/dannyvankooten/AltoRouter/workflows/PHP/badge.svg) [![Latest Stable Version](https://poser.pugx.org/altorouter/altorouter/v/stable.svg)](https://packagist.org/packages/altorouter/altorouter) [![License](https://poser.pugx.org/altorouter/altorouter/license.svg)](https://packagist.org/packages/altorouter/altorouter)
AltoRouter is a small but powerful routing class, heavily inspired by [klein.php](https://github.com/chriso/klein.php/).
```php
$router = new AltoRouter();
// map homepage
$router->map('GET', '/', function() {
require __DIR__ . '/views/home.php';
});
// dynamic named route
$router->map('GET|POST', '/users/[i:id]/', function($id) {
$user = .....
require __DIR__ . '/views/user/details.php';
}, 'user-details');
// echo URL to user-details page for ID 5
echo $router->generate('user-details', ['id' => 5]); // Output: "/users/5"
```
## Features
* Can be used with all HTTP Methods
* Dynamic routing with named route parameters
* Reversed routing
* Flexible regular expression routing (inspired by [Sinatra](http://www.sinatrarb.com/))
* Custom regexes
## Getting started
You need PHP >= 5.6 to use AltoRouter, although we highly recommend you [use an officially supported PHP version](https://secure.php.net/supported-versions.php) that is not EOL.
- [Install AltoRouter](http://altorouter.com/usage/install.html)
- [Rewrite all requests to AltoRouter](http://altorouter.com/usage/rewrite-requests.html)
- [Map your routes](http://altorouter.com/usage/mapping-routes.html)
- [Match requests](http://altorouter.com/usage/matching-requests.html)
- [Process the request your preferred way](http://altorouter.com/usage/processing-requests.html)
## Contributors
- [Danny van Kooten](https://github.com/dannyvankooten)
- [Koen Punt](https://github.com/koenpunt)
- [John Long](https://github.com/adduc)
- [Niahoo Osef](https://github.com/niahoo)
## License
MIT License
Copyright (c) 2012 Danny van Kooten <hi@dannyvankooten.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

@ -0,0 +1,35 @@
{
"name": "altorouter/altorouter",
"description": "A lightning fast router for PHP",
"keywords": ["router", "routing", "lightweight"],
"homepage": "https://github.com/dannyvankooten/AltoRouter",
"license": "MIT",
"authors": [
{
"name": "Danny van Kooten",
"email": "dannyvankooten@gmail.com",
"homepage": "http://dannyvankooten.com/"
},
{
"name": "Koen Punt",
"homepage": "https://github.com/koenpunt"
},
{
"name": "niahoo",
"homepage": "https://github.com/niahoo"
}
],
"require": {
"php": ">=5.6.0"
},
"require-dev": {
"phpunit/phpunit": "9.5.*",
"squizlabs/php_codesniffer": "3.6.2"
},
"autoload": {
"classmap": ["AltoRouter.php"]
},
"scripts": {
"test": "vendor/bin/phpunit"
}
}

@ -0,0 +1,10 @@
<?xml version="1.0"?>
<ruleset name="rules">
<description>rules</description>
<rule ref="PSR2"/>
<rule ref="Generic.Arrays.DisallowLongArraySyntax"/>
<file>tests</file>
<file>AltoRouter.php</file>
<file>examples/</file>
<arg name="colors"/>
</ruleset>

@ -0,0 +1,43 @@
<?php
require 'AltoRouter.php';
require 'Controller/UserController.php';
$router = new AltoRouter();
$router->setBasePath('/routeur');
//$router->map('GET', '/', 'AppController#create');
$router->map('GET', '/', 'AppController');
$router->map( 'GET|POST', '/user/[i:id]/[a:action]?', 'UserController');
$router->map( 'GET|POST', '/[a:action]/[i:page]/[i:id]?', 'UserController');
$page = 0;
$id =0;
$match = $router->match();
//var_dump($match);
$action = array();
$id=array();
if (!$match) { echo "404"; die; }
if ($match) {
//list($controller, $action) = explode('#', $match['target'] );
$controller=$match['target'] ?? null;
$action=$match['params']['action'] ?? null;
$id=$match['params']['id'] ?? null;
$page=$match['params']['page'] ?? null;
print 'user Id received '.$id.'<br>';
print 'controleur appelé '.$controller .'<br>';
print $action .'<br>';
print $id .'<br>';
print 'vous avez demandé la page '.$page.'<br>';
try {
$controller = '\\Controller\\' . $controller;
$controller = new $controller;
if (is_callable(array($controller, $action))) {
call_user_func_array(array($controller, $action),
array($match['params']));
}
}
catch (Error $error){print 'pas de controller';}
}
?>
Loading…
Cancel
Save