class: center, middle, inverse, title-slide # PHP & Web ## Introduction vers Symfony ### F. Hémery ### 2018 --- # Le protocole HTTP --- ## Utilisation du protocole HTTP * Le protocole **HTTP**(_HyperText Transfer Protocol_) de la couche application en réseaux est utilisé pour faire dialoguer * Le client : votre navigateur, et * Le serveur : un processus qui s'exécute sur une machine distante en attente de requêtes (apache, nginx) et qui dispatche la requête vers une application web. ![][id1] --- ## Les commandes du protocole HTTP | Nom de la commande | Description | |----------------------------|-----------------------------------------------------------------------| | GET | Demande d'accès à la ressource située à l'URL spécifiée | | HEAD | Demande d'accès à l'en-tête de la ressource située à l'URL spécifiée | | POST | Envoi de données au programme situé à l'URL spécifiée | | PUT | Envoi de données à l'URL spécifiée | | UPDATE | Envoi de données pour modification d'un enregistrement à l'URL spécifiée | | DELETE | Suppression de la ressource située à l'URL spécifiée | Par exemple : ``` bash GET http://www.iut-lens.univ-artois.fr HTTP/1.0 ``` --- ## Suite de l'en-tête A la suite de la commande, dans l'en-tête de la requête, on trouve des mots clès qui donnent des informations complémentaires au serveur, par exemple : | Mot clé | Description | |----------------------------|-----------------------------------------------------------------------| | Accept | Type de contenu accepté par le browser (par exemple text/html) | | Accept-Charset | Jeu de caractères attendu par le browser | | Accept-Language | Langage attendu par le browser (anglais par défaut) | | Date | Date de début de transfert des données | | User-Agent | Informations sur le client: nom et la version du navigateur, du système d'exploitation | --- ## Le corps de la requête La corps de la requête est le plus souvent vide, sauf quand on transmet des données saisies dans un formulaire ou encore quand on transmet un fichier vers le serveur. Voici un exemple de requête avec un corps vide ```bash GET http://www.iut-lens.univ-artois.fr HTTP/1.0 Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language fr-fr,fr;q=0.8,en-us;q=0.5,en;q=0.3 Host www.iut-lens.univ-artois.fr Referer http://www.iut-lens.univ-artois.fr/search/?query=server&page=1 User-Agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:30.0) Gecko/20100101 Firefox/30.0 ``` --- ## La réponse .smaller[ | Code | Message | Description | |----------------------------|------------------|-----------------------------------------------------| | **10x** | **Message d'information** | Ces codes ne sont pas utilisés avec HTTP 1.0 | | **20x** | **Réussite** | Ces codes indiquent le bon déroulement de la transaction | | 200 | OK | La requête a été accomplie correctement | | 204 | NO RESPONSE | Le serveur a reçu la requête mais il n'y a pas d'information à renvoyer | | **30x** | **Redirection** | Ces codes indiquent que la ressource a été déplacée | | 301 | MOVED | Les données demandées ont été transférées à une nouvelle adresse | | **40x** | **Erreur côté client** | Ces codes indiquent que la requête est incorrecte | | 400 | BAD REQUEST | La syntaxe de la requête est mal formulée ou est impossible à satisfaire | | 403 | FORBIDDEN | L'accès à la ressource est tout simplement interdit | | **50x** | **Erreur côté serveur** | Ces codes indiquent qu'il y a eu une erreur interne du serveur | | 500 | INTERNAL ERROR | Le serveur a rencontré une condition inattendue | | 503 | SERVICE UNAVAILABLE | Le serveur ne peut pas vous répondre à l'instant présent | ] --- # Les formulaires --- ## La création d'un formulaire Un formulaire permet à l'utilisateur de saisir des données. .red[Il faut toujours vérifier les données saisies (risque de corruption de votre application).] Dans une balise HTML `<form></form>`, on trouve une ou plusieurs balises `<input>`, `<textarea>`, `<select>`. ``` php <form action="traitFormulaire.php" method="post"> <input type="text" name="nom" /> <input type="text" name="prenom" /> <input type="text" name="tel" /> <input type="submit" /> </form> ``` * l'attribut `action` indique le script PHP qui traitera la saisie du formulaire. `POST` est la commande HTTP pour transmettre la requête vers le serveur. * l'attibut `type` indique le type de données accepté (on peut avoir date, email, number, ...), * l'attribut `name` associe un nom au champ du formulaire. C'est ce nom qu'il faudra utiliser comme clé pour récupérer la valeur saisie dans le tableau associatif `$_REQUEST`, `$_POST` ou `$_GET`. --- ## Traitement du formulaire Les données d'un formulaire sont récupérées dans la requête reçue sur le serveur et stockées par l'interpréteur PHP dans un tableau associatif `$_POST` si la méthode HTTP utilisée était POST, dans `$_GET` pour la méthode GET (la valeur des champs saisis dans le formulaire sont visibles dans l'URL). * `$_REQUEST['nom']`, `$_POST['nom']`, `$_GET['nom']` contient la valeur saisie dans le formulaire pour le champ avec l'attribut `name="nom"`. --- ## Traitement du formulaire : cas particulier * la balise `<select></select>` peut valider plusieurs valeurs. Le champ réponse dans ce cas est un tableau de valeurs. ``` php <form action="/traiteFormulaire.php" method="post"> <select name="fruits[]" multiple> <option value="Orange">Orange</option> <option value="Banane">Banane</option> <option value="Pomme">Pomme</option> </select> <br> <input type="submit" name="valide" value="Valide"> </form> ``` -- * Traitement du formulaire ``` php <ul> <?php foreach ($_REQUEST['fruits'] as $item) { ?> <li><?= $item ?></li> <?php } ?> </ul> ``` --- ## Traitement du formulaire : cas particulier * la balise `<input type="checkbox">` peut valider plusieurs valeurs. Le champ réponse dans ce cas est un tableau de valeurs. ``` php <form action="/traiteFormulaire.php" method="post"> <p>Votre boisson préférée : </p> <input type="checkbox" value="Bière" name="boissons[]">Bière <input type="checkbox" value="Coca cola" name="boissons[]">Coca cola <input type="checkbox" value="Perrier" name="boissons[]">Perrier <input type="submit" name="valide" value="Valide"> </form> ``` -- * Traitement du formulaire ``` php Boissons: <ul> <?php foreach ($_REQUEST['boissons'] as $item) { ?> <li><?= $item ?></li> <?php } ?> </ul> ``` --- ## Traitement du formulaire : cas particulier * la balise `<input type="file">` permet de téléverser (d'uploader) un fichier du client vers le serveur. * Il faut ajouter l'attribut `enctype` dans la balise `<form>` et lui donner la valeur `multipart/form-data`. ``` html <form action="/traiteFormulaire.php" method="post" enctype="multipart/form-data"> <p>Votre image préférée : </p> Nom de fichier : <input type="file" name="fichier"> <br> <input type="submit" name="valide" value="Valide"> </form> ``` --- ## Traitement du formulaire : cas particulier * Traitement du formulaire qui contient une balise `input` avec un type `file` * Les informations sont stockées dans un le tableau associatif `$_FILES`. * Pour chaque fichier on a les informations suivantes : .smaller[ | Nom (clé) | Description | |----------------------------|-----------------------------------------------------| | nam | Nom du fichier chargé | | tmp_name | Chemin temporaire de stockage | | type | Contenu type du fichier | | size | taille en octets | | error | Code erreur | ] ``` php $dest = '/data/'.basename($_FILES['fichier']['name']); $fichier = $_FILES['fichier']['tmp_name']; $err = $_FILES['fichier']['error']; if($err == 0 && move_uploaded_file($fichier, $dest)) echo 'Fichier chargé avec succès'; ``` La fonction [`move_uploaded_file`<svg style="height:0.8em;top:.04em;position:relative;fill:steelblue;" viewBox="0 0 512 512"><path d="M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"/></svg>](http://php.net/manual/fr/function.move-uploaded-file.php) déplace le fichier. --- # Les cookies ![][id2] --- # Manipulation des cookies * Le serveur ajoute des cookies dans la réponse avant de la transmettre au client en utilisant la fonction [`setcookie`<svg style="height:0.8em;top:.04em;position:relative;fill:steelblue;" viewBox="0 0 512 512"><path d="M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"/></svg>](http://php.net/manual/fr/function.setcookie.php) .smaller[ ``` php // nom du cookie, // valeur, // durée de vie, // le chemin sur le serveur, // le domaine du serveur, par défaut uniquement le serveur qui a crée le cookie // si vrai alors transmis si protocole sécurisé (HTTPS) setcookie("user","Robert Duchmol",0,"", ".exemple.com", false ); ``` ] * Le serveur récupère les cookies dans les requêtes suivantes, dans le tableau associatif `$_COOKIE` .smaller[ ``` php if (isset($_COOKIE['user'])) { echo "<h3>Bienvenue {$_COOKIE['user']}.</h3>"; } foreach ($_COOKIE as $cookie_name => $cookie_value) { print "$cookie_name = $cookie_value"; } ``` ] * Pour supprimer un cookie, il faut mettre à zéro la durée de vie .smaller[ ``` php setcookie("user","Robert Duchmol",0); ``` ] --- ## Modification de l'en-tête de la requête * La fonction [`header()`<svg style="height:0.8em;top:.04em;position:relative;fill:steelblue;" viewBox="0 0 512 512"><path d="M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"/></svg>](http://php.net/manual/fr/function.header.php) permet de modifier l'en-tête de la réponse vers le client. * Ajoute ou modifie un couple `(cle: valeur)` : `header('Content-Type: application/pdf');` * Dans l'exemple qui suit on l'utilise pour faire de la redirection en fin de traitement d'un formulaire. .smaller[ ``` php if (isset($_POST["valide_edit"])) { // Traitement des données du formulaire header('location:confirmationSaisie.php'); } else { // affiche le formulaire <form action="edit.php" method="post"> Nom : <input type="text" name="nom" value="<?=$etd->nom ?>" ><br /> // ... <input type="submit" name="valide_edit" value="Modification"></br> </form> } ``` ] * l'instruction `header('location:confirmationSaisie.php');` provoque une redirection (code 301). Le navigateur va recevoir la réponse et renvoyer une requête vers la nouvelle destination. --- # Notion de session --- ## Le protocole HTTP sans état * Le protocole HTTP est sans état : chaque requête est indépendante des autres. * Mise en place d'une session (persistence d'un état entre plusieurs requêtes) avec PHP * la fonction [`session_start()`<svg style="height:0.8em;top:.04em;position:relative;fill:steelblue;" viewBox="0 0 512 512"><path d="M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"/></svg>](http://php.net/manual/fr/function.session-start.php) ouvre une session * Les données de la session partagées entre les requêtes sont stockées dans un tableau associatif `$_SESSION` ``` php session_start(); if (! isset($_SESSION['visites'])) { $_SESSION['visites'] = 0; } $_SESSION['visits']++; print 'Vous avez visité la page '.$_SESSION['visites'].' fois.'; ``` * La fonction [`session_destroy()`<svg style="height:0.8em;top:.04em;position:relative;fill:steelblue;" viewBox="0 0 512 512"><path d="M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"/></svg>](http://php.net/manual/fr/function.session-destroy.php) supprime la session et les données associées. --- ## Mise en oeuvre d'une session * Le langage PHP doit mettre en place un mécanisme pour ajouter un lien entre requêtes d'une session * A chaque session PHP crée un numéro unique **`SESSIONID`** * Comment transmettre ce numéro de session de requête en requête ? * Utilisation d'un cookie * Si les cookies sont interdit par le client, la réécriture d'URL est utilisée, le numéro de session sera systématiquement ajouté comme paramètre que le client enverra vers le serveur. ``` html <a href="commande.php?PHPSESSID=2eb89f3344520d11969a79aea6bd2fdd">Passer la commande</a> ``` --- # Modèle MVC et MVVC --- ## Le modèle MVC * **Modèle** : Le système d'information utilisé pour construire les réponses aux requêtes * **Vue** : La face visible de l'application, la présentation du résultat au client (à partir de la requête et des données dans le modèle) * **Contrôleur** : Le chef d'orchestre, il analyse la requête, déclenche les traitements sur le modèle et lance la construction de la vue ![][id3] --- ## Le MVVM: **_Model View ViewModel_** * Le patron de conception **Modèle Vue Vue-Modèle**, découple les différents éléments. * La **Vue** ne traite pas les données, elle se contente de les afficher, le **Vue-Modèle** aura la charge de récupérer les données du **Modèle** et les fournir au format souhaité à la **Vue**. * **Vue** La vue concerne essentiellement l'aspect présentation de la données (les balises HTML avec ses attributs) * **Modèle** Fournit les données (base de données ou systèmes d'informations autres) * **Vue-Modèle** Fait le lien entre la Vue et le Modèle. C'est lui qui fait les conversions et gère les liaisons de données (_binding_) * Le **binding** entre A et B signifie que si A est modifié alors B est impacté et inversement. * Ce patron de conception utilise le langage de programmation **javascript** (un framework comme **angular** par exemple). --- ## Le MVVM: **_Model View ViewModel_** ![][id4] Figure vue [ici<svg style="height:0.8em;top:.04em;position:relative;fill:steelblue;" viewBox="0 0 512 512"><path d="M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"/></svg>](http://www.docdoku.com/blog/2015/02/17/architecturer-ses-applications-js-pattern-mvvm/) --- # PHP Objet --- ## Utilisation d'une classe * Une application écrite en PHP orientée objets forme une collaboration entre objets. * Une classe va utiliser d'autres classes. * Il faut rendre accessible le code de la classe dans la classe qui l'utilise. -- * Importance du nom du fichier qui contient la classe * Comme en java le **nom du fichier** correspond au **nom de la classe** * Une seule classe publique dans un fichier -- * Pour rendre accessible le code d'une classe `ClasseB` située dans le fichier `ClasseB.php` dans une classe `ClasseA` située dans le fichier `ClasseA.php`, on utilise : -- ``` php <?php require_once 'ClasseB.php'; class ClasseA { $b = new ClasseB(); // ... } ``` --- ## Utilisation d'une classe, autres solutions .pull-left[ * `include()` ``` php <?php include 'ClasseB.php'; // Si le fichier n'est pas trouvé, aucune erreur class ClasseA { $b = new ClasseB(); // ... } ``` * `include_once()` ``` php <?php include_once 'ClasseB.php'; // Le fichier n'est inclus qu'1 fois // Si le fichier n'est pas trouvé, aucune erreur class ClasseA { $b = new ClasseB(); // ... } ``` ] -- .pull-right[ * `require()` ``` php <?php require 'ClasseB.php'; // Si le fichier n'est pas trouvé, arrêt du programme class ClasseA { $b = new ClasseB(); // ... } ``` * `require_once()` ``` php <?php require_once 'ClasseB.php'; // Le fichier n'est inclus qu'1 fois // Si le fichier n'est pas trouvé, arrêt du programme class ClasseA { $b = new ClasseB(); // ... } ``` ] --- ## Recherche automatique des classes * Lorsque qu'un script utilise beaucoup de classes, il devient fastidieux d'ajouter le nom des fichiers à inclure. * La solution : une utilisation d'un outil de recherche automatique des classes. * PHP permet d'enregistrer une ou plusieurs fonctions et de rechercher et charger automatiquement les classes utilisées dans un script. * La fonction [`spl_autoload_register`<svg style="height:0.8em;top:.04em;position:relative;fill:steelblue;" viewBox="0 0 512 512"><path d="M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"/></svg>](http://php.net/manual/fr/function.spl-autoload-register.php) permet d'enregistrer une nouvelle fonction de chargement automatique de classes. ``` php <?php function nomFichierCommeClasse( $classname ) { $file = "{$classname}.php"; if ( file_exists( $file ) ) { require_once( $file ); } } spl_autoload_register( 'nomFichierCommeClasse' ); $personne = new Personne( "Duchmol", "Robert" ); ``` --- ## Exemple d'utilisation du chargeur automatique .smaller[ ``` php <?php function nomFichierCommeClasse($classname) { $file = "{$classname}.php"; if (file_exists($file)) { require_once $file; } } spl_autoload_register('nomFichierCommeClasse'); $a = new ClasseAA(); ``` ] .smaller[ ``` php <?php class ClasseAA { public function __construct() { $b = new ClasseBB(10); echo $b.PHP_EOL; } } ``` ] .smaller[ ``` php <?php class ClasseBB { private $val; public function __construct($val) { $this->val = $val; } public function __toString() { return (string) $this->val; } } ``` ] --- ## Nécessité de normaliser le nommage des fichiers * Les editeurs de code PHP doivent facilement distribuer leur travail * Introduire la notion de librairie de classes que l'on doit pouvoir utiliser sans devoir fixer un emplacement dans l'arborescence * Avoir la possibilité d'utiliser un nom de classe utilisée dans une librairie développée par un tiers * Permettre une hiérarchie de classes -- Solution : Introduction de la notion de nommage et d'organisation des fichiers qui composent une application --- # PHP Standard Recommendation (PSR) --- ## PSR-4 : Le nommage des fichiers * Le standard [PSR-4<svg style="height:0.8em;top:.04em;position:relative;fill:steelblue;" viewBox="0 0 512 512"><path d="M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"/></svg>](https://www.php-fig.org/psr/psr-4/) précise les règles de nommage des fichiers. * Permet de proposer une implémentation d'une fonction de chargement automatique des classes PHP. -- * Utilise la notion de namespace * C'est le moyen de distinguer deux classes ayant le même nom et appartenant à des paquetages différents. * Equivalent du **`package`** en java. * Représente une notion de domaine, dans la documentation on parle souvent de _Vendor_ (ou encore _Namespace Prefix_ dans le standard PSR-4), le niveau principal du namespace. * Un exemple d'utilisation de namespace ``` php <?php namespace IutLens; class TP1 { // ... } ``` --- ## Utilisation d'une classe dans un namespace * Un autre exemple avec des sous domaines ``` php <?php namespace IutLens\Web\Client; class Requete { // ... } ``` * Déclaration d'une classe `Requete` dans le namespace `\IutLens\Web\Client`. ``` php <?php namespace IutLens\Web\Client; class Requete { // ... } ``` * Utilisation de cette classe dans un autre fichier ``` php <?php $requete = new \IutLens\Web\Client\Requete('GET','http://localhost/index.html'); ``` --- ## Utilisation du standard PSR-4 .smaller[ | Nom de la classe totalement qualifié | Préfixe du nom | Répertoire de base | Chemin de la classe | |----------------------------|----------------------|-------------------------------|-------------------------------------------------| | `\Acme\Log\Writer\File_Writer` | `Acme\Log\Writer` | `./acme-log-writer/lib/` | `./acme-log-writer/lib/File_Writer.php` | | `\Aura\Web\Response\Status` | `Aura\Web` | `/path/to/aura-web/src/` | `/path/to/aura-web/src/Response/Status.php` | | `\Symfony\Core\Request` | `Symfony\Core` | `./vendor/Symfony/Core/` | `./vendor/Symfony/Core/Request.php` | | `\Zend\Acl` | `Zend` | `/usr/includes/Zend/` | `/usr/includes/Zend/Acl.php` | ] --- ## Utilisation d'un alias * Quand le nom complet de la classe devient long, il est préférable de créer des alias. * Le mot clé `use` permet de créer un alias ``` php <?php use \IutLens\Web\Client\Requete // ... $req = new Requete(); ``` * Chemin relatif, chemin absolu : la recherche de la classe se fait relativement au paquetage courant (chemin relatif) sauf si vous indiquez un chemin absolu (qui commence par le symbole '`\`') * Un alias ne demande pas le symbole '`\`' comme premier caractère. .smaller[ ``` php <?php namespace main; use IutLens\Web\Client\Requete; use \IutLens\Web\Client\Reponse; // ... $requete = new IutLens\Web\Client\Requete(); // provoque une erreur $req = new Requete(); // est correct $rep = new Reponse(); // est correct ``` ] --- # La commande `composer` --- ## Création d'un projet * La commande [`composer`<svg style="height:0.8em;top:.04em;position:relative;fill:steelblue;" viewBox="0 0 512 512"><path d="M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"/></svg>](https://getcomposer.org/) * permet de gérer les dépendances de votre projet. * propose une fonction qui gère le chargement automatique des classes qui respectent la norme proposeée par PSR-4 * utilise un fichier de configuration `composer.json` pour la gestion de votre projet * Création du fichier de configuration `composer.json` ``` bash [~robert] composer init ``` * Fichier `composer.json` produit ``` json { "name": "pweb_1/tp1", "authors": [ { "name": "Hemery Fred", "email": "fred.hemery@univ-artois.fr" } ], "require": {} } ``` --- ## Ajout de dépendances ``` bash [~robert] composer require michelf/php-markdown ``` * Résultat : ``` json { "name": "pweb_1/tp1", "authors": [ { "name": "Hemery Fred", "email": "fred.hemery@univ-artois.fr" } ], "require": { "michelf/php-markdown": "^1.8" } } ``` * Ajoute * un répertoire `vendor` dans votre répertoire courant avec les classes de la librairie tiers. * un script php qui permet d'utiliser directement les classes de la dépendance ajoutée. --- ## Intégration de votre code * Pour gérer votre code en cours de développement, il faut éditer le fichier et ajouter : ``` json { "name": "pweb_1/tp1", "authors": [ { "name": "Hemery Fred", "email": "fred.hemery@univ-artois.fr" } ], "require": { "michelf/php-markdown": "^1.8" } { "autoload": { "psr-4": {"IutLens\\Web": "src/"} } } ``` * Dans l'exemple `IutLens\\Web` correspond au préfixe du nom de namespace, les classes et autres répertoires se trouveront dans le répertoire `src`. --- ## Utilisation * Une classe en développement .smaller[ ``` php <?php namespace IutLens\Cli; class ClasseA{ const BONJOUR = 'Bonjour monde ! '; } ``` ] * Un exemple de script qui utilise la mécanique mise en oeuvre .smaller[ ``` php <?php require_once __DIR__.'/../vendor/autoload.php'; use Michelf\Markdown; use IutLens\Cli\ClasseA; $bienvenue = ClasseA::BONJOUR; $str = <<<EOD # This is an H1 ## This is an H2 ### $bienvenue * un item * un autre item EOD; $my_html = Markdown::defaultTransform($str); echo $my_html; ``` ] --- # Pourquoi [Symfony<svg style="height:0.8em;top:.04em;position:relative;fill:steelblue;" viewBox="0 0 512 512"><path d="M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"/></svg>](https://symfony.com/) * Framework MVC * Gestion de Base données à l'aide d'un ORM [Doctrine<svg style="height:0.8em;top:.04em;position:relative;fill:steelblue;" viewBox="0 0 512 512"><path d="M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"/></svg>](https://www.doctrine-project.org/) et le cadre de conception (_design pattern_ **_Data Mapping_**) * Injection de Dépendances * Mécanisme de templates ([twig<svg style="height:0.8em;top:.04em;position:relative;fill:steelblue;" viewBox="0 0 512 512"><path d="M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"/></svg>](https://twig.symfony.com/) intégré) [id1]: images/protoHTTP.png "Figure 1. Le protocole HTTP" [id2]: images/schemaCookie.png "Figure 2. Les cookies" [id3]: images/MVC.png "Figure 3. Le modèle MVC" [id4]: images/MVVM-2.png "Figure 4. Le modèle MVVM"