PHP

Présentation

  • Développeur web freelance depuis 5 ans

  • http://www.boxydev.com

  • Expérience en agence web, E-Commerce (annonceur)

  • Formation Informatique et Autodidacte

  • Formateur et fan des OSS, contributeur à mes heures perdues

  • Solutions phares : Wordpress, Symfony, Magento, Prestashop, Angular

  • Langages : PHP, MySQL, HTML, CSS, JS

  • Outils : Git, Docker, Vagrant, Trello
  • Stack: ArchLinux, Gentoo, Mac OS (Unix addict)

Qu'est-ce que PHP ?

PHP signifie "Hypertext Preprocessor" (acronyme récursif).

C'est un langage de programmation qui est utilisé pour créer des pages web dynamiques. Il est compilé à la volée avec un serveur HTTP.

Il est utilisé par des millions de sites web dans le monde dont Facebook et Wikipédia.

Pourquoi ?

- Un espace membre

- Un site ecommerce

- Un forum

- Un compteur de visites

- Envoi de fichier via un formulaire

Site statique vs Site dynamique

Structure et contenu

Animations

Style et design

Dynamique

Base de données

<=

Client vs Server

Historique

Il a été créé en 1994 par Rasmus Lerdorf. Personal Home Page Tools

 

Historique des versions de PHP :

1.0 : 1995 - 2.0 : 1997

3.0 : 1998 - 4.0 : 2000

5.0 : 2004 - 7.0 : 2015

Versions de PHP conseillées en 2022

7.4, 8.0, 8.1

 

Site officiel : https://php.net

Ressources

Soyez prudents et critiques face aux codes proposés par la communauté. Attention aux commentaires et à la date de publication.

Installation

- MacOS : MAMP

- Windows : WAMP

- Linux : LAMP

- Tous : XAMPP / Laragon

 

La première lettre représente le système d'exploitation.

AMP signifie Apache, MySQL, PHP

Ready ?

- Un fichier PHP doit toujours avoir l'extension .php

- Les fichiers PHP doivent être dans le dossier htdocs de notre XAMP

- Le serveur Apache (HTTP) doit être lancé sur le port 80

- Les fichiers de configuration peuvent être php.ini pour PHP, apache.conf pour Apache, my.cnf pour MySQL

- On peut accéder à notre site via http://localhost et si un fichier index.php est présent, il sera chargé

Comment écrire du PHP ?

?>

- Un code PHP doit toujours commencer par l'ouverture de balise PHP

<?php

- Un code PHP peut se terminer par une fermeture de balise PHP (Pas obligatoire si le fichier se termine par du code PHP)

- Entre ces 2 balises, on écrira notre code PHP

- On peut ouvrir et fermer les balises PHP plusieurs fois d'affilée

Instruction en PHP

<?php

echo 'Texte entre quotes';
echo "ou bien entre double quotes";

?>

Une instruction est un ordre que l'on donne au langage

Chaque instruction PHP se termine par un ;

On peut afficher une chaine de caractères avec une instruction "echo"

Dans le navigateur, on ne verra que le texte et pas le code PHP

Les commentaires en PHP

<?php

// Un commentaire sur une seule ligne

/*
Un commentaire
sur plusieurs
lignes
*/

// Un bout de code commenté
/*
echo 'test';
*/

Commenter le code peut aider à se repérer dans son code ou aussi à rechercher les erreurs

Et l'HTML ?

<!DOCTYPE html>
<html>
<head>
    <title>Titre</title>
</head>
<body>
    <?php
        echo 'Chaine affichée en PHP';
        // Si on veut utiliser les quotes dans la chaine, il faut les échapper avec un \
        echo 'L\'HTML dans le PHP';
        // On peut utiliser du HTML dans le PHP
        echo 'Chaine affichée en PHP <br />';
    
    ?>
    Chaine affichée en HTML
</body>
</html>

On peut continuer à faire de l'HTML sans soucis

Les variables

Une variable est une boîte avec une étiquette contenant une donnée.

<?php

$age = 26; // Initialise une variable et lui affecte la valeur 26
$mon_age = 26; // Underscore
$monAge = 26; // lowerCamelCase
$doubleAge = $monAge * 2; // $doubleAge vaut 52

echo $doubleAge; // Affiche 52
  • En PHP, une variable commence toujours par $
  • Par convention, choisir un nom de variable compréhensible.
  • Eviter les accents, caractères spéciaux
  • Ne doit pas commencer par un chiffre
  • CamelCase ou under_score

Types de variables

Il existe 8 types de données en PHP

<?php

$string = 'Hello';
$integer = 26;
$float = 3.14;
$boolean = true;
$array = [1, 2, 3];
$array2 = array(1, 2, 3);
// Tableau associatif
$array3 = ['a' => 1, 'b' => 2, 'c' => 3];
$object = new Object();
$null = null;
$resource = fopen('C:\fichier.txt');

Attention au typage faible

Concaténation

La concaténakwa ?

La concaténation permet de mettre à bout au moins 2 chaines de caractères

<?php

/* Opérateur de concaténation */
$a = 'Hello ';
$b = $a . 'World !'; // $a ne change pas mais $b vaut désormais "Hello World !"

/* Opérateur d'affectation concaténant */
$c = 'Hello ';
// On concatène cette chaîne à la précédente, $c vaut désormais "Hello World !"
$c .= 'World !';

/* Il est tout à fait possible de combiner les deux */
$d = 'Hello ';
$e = 'World ';
$d .= $e . '!'; // $e ne change pas, mais $d vaut désormais "Hello World !"
echo $d;

Exercice simple

  1. Dans le dossier, créer un fichier hello.php
  2. Définir une variable contenant votre prénom
  3. Afficher "Bonjour prénom" dans un h1

Opérations

Opérateurs arithmétiques


<?php

$a = 10; // Ici, c'est l'opérateur d'affectation
// Ci-dessous, opérateurs arithmétiques
$a + 30; // Addition 40
echo 10 - 5; // Soustraction 5
echo 3 * 2; // Multiplication 6
$a = 3 + 3; // on peut modifier une variable en cours de route
echo $a / 2; // Division 3 car a vaut 6
echo 10 % 3; // Modulo (Reste de la division) 1
echo 10 ** 2; // Exponentielle: 10 à la puissance 2 (PHP 5.6+) 100
echo -$a; // -10

$a += $b; // équivaut à $a = $a + $b;
$a -= $b; // équivaut à $a = $a - $b;
$a *= $b; // équivaut à $a = $a * $b;
$a /= $b; // équivaut à $a = $a / $b;
$a %= $b; // équivaut à $a = $a % $b;

Comparaison

Les opérateurs de comparaison renvoient true ou false

<?php

$a == $b; // vrai si $a est égal à $b
// vrai si $a est égal à $b et qu'ils sont du même type (integer, string, etc.)
$a === $b;
// vrai si $a est différent de $b
$a != $b; /*ou*/ echo $a <> $b;
$a !== $b; // vrai si $a est différent de $b ou qu'ils ne sont pas du même type
$a < $b; // vrai si $a est strictement inférieur à $b
$a > $b; // vrai si $a est strictement supérieur à $b
$a <= $b; // vrai si $a est inférieur ou égal à $b
$a >= $b; // vrai si $a est supérieur ou égal à $b
!$a; // vrai si $a vaut false

Conditions

Cas d'utilisation des opérateurs de comparaison.

Pour rappel, une condition est "SI quelque chose est vrai FAIS quelque chose SINON FAIS autre chose

Attention, les blocs d'instructions { } ne se termine pas par un ;

<?php

$a = 3;
$condition = 0 === false;

if ($a == 0) {
    // Si $a vaut 0, les instructions présentes ici seront exécutées
} elseif ($a > 12 && $a <= 42) {
    // Si $a est supérieur à 12 et inférieur ou égal à 42,
    // les instructions présentes ici seront exécutées.
} else if ($condition) {
    // Si $condition est vraie, l'instruction présente ici sera exécutée.
} else {
    // Sinon, si aucune des 2 conditions précédentes n'est remplie,
    // les instructions présentes ici seront exécutées.
    // Ici, $a vaut 3, il ne vaut donc pas 0 et n'est pas compris entre 12 et 42 inclus.
    // C'est donc ce bloc d'instruction qui sera exécuté et non les 2 précédents.
}

Opérateurs logiques

<?php

$a && $b; $a and $b; // True si $a ET $b sont true
$a || $b; $a or $b; // True si $a OU $b est true
$a xor $b; // True si $a OU $b est true mais pas les 2 à la fois

if ($a && $b && $c) {
    // On fais quelque chose
}

// Attention aux priorités, le AND est comme une multiplication (prioritaire)
// Et le OR comme une addition (pas prioritaire)
if ($a || $b && $c) {
    
}

Permet d'associer des opérations

Incrémentation

<?php

$a = 0;

++$a; // La variable est incrémentée de 1, puis elle est retournée
$a++; // La variable est retournée, puis incrémentée de 1
--$a; // La variable est décrémentée de 1, puis elle est retournée
$a--; // La variable est retournée, puis décrémentée de 1

L'incrémentation (et la décrémentation) permettent d'ajouter ou d'enlever 1 à un nombre ou une chaine de caractères.

Les erreurs

<?php

echo $a; // Affiche une NOTICE, mais le script ne s'arrête pas
echo 1 / 0; // Affiche un WARNING, division par zéro

echo 3;
echo 4 // Affiche une ERROR Parse error: syntax error
echo 6;

Il est normal de faire des erreurs, le plus important est de savoir les debuger.

3 niveaux d'erreurs : NOTICE, WARNING, ERROR

Debug

<?php

$tableau = [1, 2, 3];

print_r($tableau); // Affiche le contenu du tableau non formaté
die('Stop le script'); // Arrête le script avec un message ou pas
var_dump($tableau); // Affiche le contenu du tableau formaté

Il existe 3 fonctions importantes en PHP pour s'aider dans le debug d'erreur

Exercices

  1. Créer un fichier major.php
  2. Créer une variable age comprise entre 0 et 20.
  3. Ecrire une condition qui permet de vérifier si la personne est majeure. Si c'est le cas, on affiche "Vous pouvez entrer" sinon "Interdit"
  4. Ajouter à la condition:
    - Si la personne a entre 16 ET 18 ans non inclus
    -> "Vous êtes presque majeur"
    - Si la personne a entre 14 ET 16 ans non inclus
    -> "Vous êtes jeune"
    - Si la personne a moins de 14 ans
    -> "Vous êtes trop jeune"

Exercices

  1. Créer un fichier operation.php
  2. Stocker 15 dans une variable.
  3. Stocker 5 dans une autre variable.
  4. Stocker 8 dans une autre variable.
  5. Afficher ceci dans la page (en dynamique) :

15 + 5 + 8 = 28

15 x (8 - 5) = 45

(8 + 5) / 15 = 0.86

Si une des opérations a un résultat inférieur à 20, afficher "Une des opérations renvoie moins de 20" en bas de la page

Serveur HTTP

HTTP (HyperText Transfer Protocol) est un langage qui permet à 2 machines de communiquer ensemble, le client et le serveur.

Le client envoie une requête

 

 

Le serveur envoie une réponse

GET / HTTP/1.1
Host: google.fr
Accept: text/html
User-Agent: Mozilla/5.0 (Macintosh)
HTTP/1.1 200 OK 
Date: Sun, 20 May2018 14:05:05 GMT
Server: apache/2.4.33
Content-Type: text/html 

<html>
  Vous êtes sur Google
</html>

Codes HTTP

100 : Information

200 : Succès

300 : Redirection

400 : Erreur du client

500 : Erreur du serveur

Le serveur renvoie toujours un code dans la réponse (200, 404, 403, 500).

Les boucles

<?php
/* for
elle est composée d'une instruction d'initialisation, d'une condition d'exécution
et d'une instruction à exécuter à chaque itération après le bloc d'instruction de la boucle
*/
for ($i = 0; $i < 10; $i++) {
    // instructions
}

/* foreach
particulièrement utile, elle permet de parcourir un tableau (ou les propriétés d'un objet)
*/
$a = array(1, 2, 3);
foreach ($a as $item) {
    // instructions
}

// foreach permet également de récupérer la clé associée à la valeur dans le tableau
$fruits = ['A' => 'abricot', 'B' => 'banane', 'C' => 'cerise'];
foreach ($fruits as $lettre => $fruit) {
    echo $lettre . '  :  '  . $fruit;
    // Affichera pour la première itération "A  : abricot"
}

Permet de répéter des instructions en fonction d'une ou plusieurs conditions particulière

Les boucles - while

<?php
/* while
elle est similaire à for si ce n'est
qu'elle n'a comme paramètre que la condition d'exécution
*/
$i = 0;
while ($i < 10) {
    // instructions
    $i++;
}

/* do…while
fonctionne comme while, excepté que les instructions
qu'elle conditionne sont exécutées 1 fois avant que la condition soit testée
*/
$i = 0;
do {
    // instructions
    $i++;
} while($i < 10);

Exercices

1. Ecrire une boucle qui affiche les nombres de 10 à 1

2. Ecrire une boucle qui affiche uniquement les nombres pairs entre 1 et 100

3. Ecrire le code permettant de trouver le PGCD de 2 nombres

4. Coder le jeu du FizzBuzz

Parcourir les nombres de 0 à 100

Quand le nombre est un multiple de 3, afficher Fizz.

Quand le nombre est un multiple de 5, afficher Buzz.

Quand le nombre est un multiple de 15, afficher FizzBuzz.

Sinon, afficher le nombre

Exercices

  1. Créer une boucle qui affiche 10 étoiles (*)
  2. Imbriquer la boucle dans une autre boucle afin d'afficher 10 lignes de 10 étoiles
  3. Nous obtenons un carré. Trouver un moyen de modifier le code pour obtenir un triangle rectangle.

Exercices

1. Afficher la table de multiplication du chiffre 5

5 x 1 = 5

5 x 2 = 10

...

2. Afficher l'ensemble des tables de multiplications de 1 à 10.

<?php

// Pour vous aider

for ($i = 1; $i <= 10; $i++) {
    echo '1 x ' . $i;
}

Exercices

Grâce aux boucles et un peu d'HTML, essayez de reproduire ce tableau :

Fonctions internes de PHP

<?php

/* isset() Si la variable $a n'existe pas déjà, on la défini avec comme valeur 42. */
if (!isset($a)) {
    $a = 42;
}

/* empty() Si la variable $a n'est pas vide, on affiche sa valeur. */
if (!empty($a)) {
    echo $a;
}

/* unset() Maintenant qu'on a défini puis utilisé la variable $a, on la détruit. */
unset($a);

/* time(); affecte à $t le nombre de secondes écoulées depuis le 01/01/1970
à l'instant ou l'instruction est exécutée. */
$t = time();

/* date() Affichera la date au format JJ / MM / AAAA, par exemple 21 / 05 / 2018. */
echo date('d / m / Y', $t);

/* count() Affichera 3, car $b contient 3 valeurs. */
$b = array('pomme', 'poire', 'abricot');
echo count($b);

/* strlen() Affichera 13, car $c contient 13 caractères (cela inclut les espaces) */
$c = 'Hello World !';
echo strlen($c);

Gestion des dates PHP

<?php

// La fonction date permet d'afficher une date sous un certain format
// Elle prend en second paramètre un timestamp de la date désirée
// Par défaut, c'est le timestamp courant
echo date('c'); // Affichera "2004-02-12T15:19:21+00:00"
echo "Nous sommes à la semaine " . date('W'); // Affichera "Nous sommes à la semaine 42"
echo date('d m Y H:i'); // Affichera "03 09 2015 18:48"
echo date('H\h i\m s\s'); // Affichera "18h 55m 36s"

time(); // Renvoie le timestamp courant

// strtotime est l'inverse de date, on peut passer un texte plutôt que le timestamp
// Usage simple
echo strtotime('now'); // Affichera le timestamp actuel, équivalent à time()
echo strtotime('9 january 2007'); // Affichera le timestamp de cette date, 1168297200

// Usage relatif
// Affichera le timestamp du lendemain du jour d'exécution du script
echo strtotime('+1 day');
// Affichera le timestamp relatif au jour d'exécution
// du script avec 2 semaines 1 jour 5 heures et 30 secondes d'ajoutées à celui-ci
echo strtotime('+2 weeks 1 day 5 hours 30 seconds');
// Affichera le timestamp du lundi précédent le plus proche du jour d'exécution du script
echo strtotime('last monday');
// Usage avec paramètre
// Affichera le timestamp correspondant à 6 mois après celui passé en paramètre
echo strtotime('+6 months', $timestamp);

Exercices

1. Nous cherchons à afficher la date du jour au format "Tuesday 16 february 2021, il est 10h51 et 12 secondes". Cherchez sur Google la fonction PHP permettant de faire cela. Comment choisir le format de la date ?

2. Nous voulons récupérer le jour qu'il sera dans 10 jours exactement. Pensez que strtotime renvoie un timestamp.

3. Combien de jours reste-t-il avant Noël ?

Les tableaux

<?php

// Tableau numérique à une dimension
$notes = [10, 20, 15];
// Comment récupérer le 20 ?
$notes[1];
// Tableau associatif à une dimension
$notes = ['Jean' => 10, 'Eric' => 20, 'Matthieu' => 15];
// Comment récupérer le 20 ?
$notes['Eric'];

// Tableau numérique à 2 dimensions
$morpion = [
    ['X', 'O', 'X'],
    ['X', 'Xa', 'O'],
    ['X', 'O', 'O']
];

// Alternative
$morpion = array(); // J'initialise un tableau vide
$morpion[0] = array('X', 'O', 'X');
$morpion[1] = array('X', 'Xa', 'O');
$morpion[2] = array('X', 'O', 'O');
// Comment récupérer Xa ?
$morpion[1][1];

Exercices

Déclarer un tableau qui stocke les informations suivantes :

 

 

 


Afficher le résultat suivant en utilisant la boucle foreach :

La capitale de France est Paris.

La capitale de Espagne est Madrid.

La capitale de Italie est Rome.

<?php

$capitales = [
    'France' => 'Paris',
    'Espagne' => 'Madrid',
    'Italie' => 'Rome',
];

Exercices

D'après le tableau suivant :

<?php

$population = [
    'France' => 67595000,
    'Suede' => 9998000,
    'Suisse' => 8417000,
    'Kosovo' => 1820631,
    'Malte' => 434403,
    'Mexique' => 122273500,
    'Allemagne' => 82800000,
];

1. Lister les pays ayant plus ou 20 millions d'habitants

2. Donner la population totale des pays Européens

Exercices

<?php

$eleves = [
    0 => [
        'nom' => 'Matthieu',
        'notes' => [10, 8, 16, 20, 17, 16, 15, 2]
    ],
    1 => [
        'nom' => 'Thomas',
        'notes' => [4, 18, 12, 15, 13, 7]
    ],
    2 => [
        'nom' => 'Jean',
        'notes' => [17, 14, 6, 2, 16, 18, 9]
    ],
    3 => [
        'nom' => 'Enzo',
        'notes' => [1, 14, 6, 2, 1, 8, 9]
    ]
];

1/ Afficher la liste de tous les éléves avec leurs notes.

Exemple :

Matthieu a eu 10, 8, 16, 20, 17, 16, 15 et 2

Thomas a eu 4, 18, 12, 15, 13 et 7

Jean a eu 17, 14, 6, 2, 16, 18 et 9

2/ Calculer la moyenne de Jean. On part de $eleves[2]['notes']

La fonction count permet de compter les éléments d'un tableau

3/ Combien d'élèves ont la moyenne ?
Exemple :
Matthieu a la moyenne
Jean n'a pas la moyenne
Thomas a la moyenne
Nombre d'éléves avec la moyenne : 2

4/ Quel(s) éléve(s) a(ont) la meilleure note ?
Exemple: Thomas a la meilleure note : 19

5/ Qui a eu au moins un 20 ?
Exemple: Personne n'a eu 20
         Quelqu'un a eu 20

Fonctions utilisateur

On peut créer des fonctions afin d'y ranger une portion de code que l'on souhaite réutiliser plus tard.

<?php

// Déclare une fonction hello
function hello($argument) {
    return 'Hello ' . $argument;
}

echo hello('world!'); // L'appel de la fonction affiche Hello world!

// Attention, on ne peut pas nommer 2 fonctions avec le même nom
function say($argument, $argument2) {
    return $argument . ' ' . $argument2;
}

echo say('Hello', 'world!'); // L'appel de la fonction affiche Hello world!

Portée des variables

La portée d'une variable est l'existence de celle-ci dans un contexte (dans le script ou dans une fonction)

<?php

$a = 10; // Portée globale

function toto()
{
    $b = 2;  /* Portée locale*/

    echo $a; // Erreur
}

toto();
echo $b; // Erreur

// Comment accèder à $a dans la fonction ?

function toto()
{
    global $a;
    echo $a; // Fonctionne
}

Exercices

  1. Créer une fonction calculant le carré d'un nombre
  2. Créer une fonction calculant l'aire d'un rectangle et une fonction pour celle d'un cercle
  3. Créer une fonction calculant le prix TTC d'un prix HT. Nous aurons besoin de 2 paramètres, le prix HT et le taux.
  4. Ajouter un 3ème paramètre à cette fonction permettant de l'utiliser dans les 2 sens (HT vers TTC ou TTC vers HT)

Les superglobales

<?php

$_GET; // Tableau contenant toutes les données passée dans l'URL
// index.php?key=valeur&key2=valeur2 donne $_GET = ['key' => 'valeur', 'key2' => 'valeur2'];

$_POST; // Tableau contenant toutes les données passée dans un formulaire
// <input name="key" value="valeur"> donne $_POST = ['key' => 'valeur'];
// Attention, la méthode du formulaire doit être en POST sinon on est
// dans l'exemple du dessus et les données du formulaire seront exposées
// dans l'URL. En POST, les données sont masquées (mais pas chiffrées).

$_GET et $_POST sont des variables superglobales.

$_SERVER contient des informations sur le serveur et le client. $_SESSION sur la session et $_COOKIE sur les cookies.

URL et formulaire

http://localhost/php/search.php?q=query

<?php

if (isset($_GET['q'])) {
    echo 'on cherche ' . $_GET['q'];
}
<?php

if (isset($_POST)) {
    // $_POST contient ['nom' => 'Valeur', 'prenom' => 'Valeur']
}

?>

<!-- L'attribut action permet de rediriger l'URL vers un autre fichier -->
<form method="POST" action="index.php">
    <input type="text" name="nom">
    <input type="text" name="prenom">
</form>

Pour un formulaire, l'attribut name est important.

Exercices

  1. Créer un formulaire sur calculator.php
  2. Dans ce formulaire, créer un champ nombre1 et un champ nombre2
  3. Au clic sur le bouton "Calculer", faire la somme du nombre1 et du nombre2
  4. Ajouter un champ radio ou select permettant de choisir l'opération (+, -, /, *)
  5. En bonus, indiquer le nombre qui est le plus grand et celui qui est le plus petit.

Exercices

  1. Créer un formulaire avec un champ où on saisit une valeur en euros
  2. Ajouter un bouton "Convertir". Au clic, on affiche la conversion en Bitcoins
  3. Ajouter un select pour choisir le sens de conversion :
    - Euros vers bitcoins
    - Bitcoins vers euros

Exercices

  1. Créer un formulaire avec un champ pour saisir un nom et un autre avec un âge.
  2. Ajouter un bouton "Présenter". Au clic, on affiche "Bonjour Toto, vous avez 31 ans. Vous êtes majeur." ou "Bonjour Toto, vous avez 17 ans. Vous êtes mineur."
  3. Ajouter des champs radio pour choisir le genre de la personne. L'ajouter à la phrase.

Exercices

  1. Nous allons créer 2 pages PHP, videos.php et video.php
  2. La page videos.php contiendra 4 boutons, un clic sur un bouton nous emmène vers video.php?id=123456
  3. Sur la page video.php, récupérer le paramètre id s'il est présent, sinon, on affiche une 404. Un bouton permettra de retourner à la liste.
  4. Cet id sera celui d'une vidéo Youtube, vous afficherez donc l'iframe de la vidéo concernée sur la page.
  5. BONUS : Ajouter un paramètre GET permettant de modifier la couleur de fond du lecteur vidéo.
  6. BONUS : Ranger une liste de vidéos dans un tableau et afficher ce tableau à la place des boutons.

Stratégie de validation des données

En tant que développeur, il est très important de pouvoir valider les données afin de protéger le site d'attaques potentielles.

<?php

$nom = '';
$nombre1 = 'a';
$email = 'matthieu';

if (strlen($nom) == 0) {
    exit('Votre nom ne doit pas être vide');
}

if (!ctype_digit($nombre1)) {
    exit('Le nombre1 n\'est pas un nombre valide');
}

if (false == filter_var($email, FILTER_VALIDATE_EMAIL)) {
    exit('Cet email n\'est pas valide');
}

Exercices

  1. Créer un fichier contact.php
  2. Créer un formulaire avec 4 champs
  3. Email, Sujet, Message et Civilité
  4. L'email doit être obligatoire et valide
  5. Le sujet ne doit pas être vide
  6. Le message (textarea) doit faire au minimum 15 caractères
  7. Le sujet doit être une de ces 3 valeurs :
    - Proposition de stage, Proposition d'emploi, Demande de projet
  8. Le champ civilité est un radio avec deux choix: Mme ou Mr.
  9. Vous afficherez un message de succès avec toutes les informations du formulaire si tout est ok sinon vous afficherez les erreurs.
  10. Comment feriez-vous pour afficher chaque message d'erreur en dessous de chaque champ ? Implémentez une solution dans l'exercice.
$errors[] = 'Une erreur';
$errors['email'] = 'Une erreur';

Exercices

  1. Créer un formulaire avec 3 champs: Début, fin et pas.
  2. Le début sera un nombre entre 0 et 10. La fin sera un nombre entre début + 1 et début + 100. Le pas sera un nombre entre 1 et 10.
  3. Avec une boucle et les valeurs du formulaire, afficher les nombres de début à fin en allant de pas en pas. Exemple: Boucle de 0 à 10 de 1 en 1.

Fonctions sur les chaines

<?php

$email = 'matthieu@boxydev.com';
echo strlen($email); // Affiche 20

// Affiche 'Un nombre 10 et une chaine toto'.
echo sprintf('Un nombre %d et une chaine %s.', 10, 'toto');

// Affiche '@boxydev.com', stristr idem mais insensible à la casse
echo strstr($email, '@');

// Affiche 8, la taille de la chaine avant @, stripos idem mais insensible à la casse
echo strpos($email, '@');

// Affiche matthieu@gmail.com, str_ireplace idem mais insensible à la casse
echo str_replace('boxydev', 'gmail', $email);

echo substr('abcdef', 2, 2); // Affiche "cd"
echo substr('abcdef', 1, 3); // Affiche "bcd"
echo substr('abcdef', 3);    // Affiche "def"

echo substr("abcdef", -1); // Affiche "f"
echo substr("abcdef", -2); // Affiche "ef"
echo substr("abcdef", -3, 1); // Affiche "d"

echo strrev('Hello world!'); // Affiche "!dlrow olleH"

// Une chaine est un tableau
echo $email[8]; // @

Fonctions sur les chaines 2

<?php

$keywords = "php, js, html, css";
$array_keywords = explode(', ', $keywords);
echo $array_keywords[0]; // Affiche 'php'
echo $array_keywords[1]; // Affiche 'js'
echo $array_keywords[2]; // Affiche 'html'
echo $array_keywords[3]; // Affiche 'css'

$keywords = ['php', 'js', 'html', 'css'];
$string_keywords = implode(', ', $keywords);
echo $string_keywords; // Affiche "php, js, html, css"

$message = 'Hello World';
echo strtolower($message); // Affiche 'hello world';
echo strtoupper($message); // Affiche 'HELLO WORLD';

$message = '    Hello World  ';
echo trim($message); // Affiche 'Hello World';

$message = '<h1>Hello World, </h1><p>How are you ?</p>';
echo strip_tags($message); // Affiche 'Hello World, How are you ?'
echo strip_tags($message, '<h1>'); // Affiche '<h1>Hello World, </h1>How are you ?'

Exercices

  1. Acronyme : Créer une fonction qui prend en argument une chaine (World of Warcraft) et qui retourne les initiales de chaque mot en majuscule (WOW).
  2. Conjugaison : Créer une fonction qui permet de conjuguer un verbe (chercher par exemple). Cela doit renvoyer toutes les conjugaisons au présent.

Vous allez bien sûr créer un formulaire pour chacun de ces exercices afin que cela soit bien dynamique.

Exercices

3. Statistiques : On va créer un tableau avec des adresses e-mail. Le but est d'extraire le nom du serveur après le @. On calculera ensuite le pourcentage d'utilisation de chaque fournisseur. Par exemple :

Gmail : 40%

Outlook: 20%

Orange: 20%

Autre: 20%

BONUS: Générer une liste de checkboxes pour chaque fournisseur. On pourra choisir plusieurs fournisseurs et cliquer sur un bouton nous permettant de filtrer les emails par fournisseurs.

<input type="checkbox" name="filters[]" value="blue">

Exercices

- Créer un formulaire avec un champ langages préférés. On pourra saisir "react, php, js".

- On affichera ensuite cette liste sous forme de ul li en ayant pris soin de transformer la chaine en tableau pour pouvoir le faire facilement.

- On vérifiera les erreurs, par exemple, si on saisit "php,,,js,,", on aura php et js qui seront dans la liste.

- Aussi, on pourra prévoir une liste de langages valides parmi lesquelles l'utilisateur pourra faire son choix. On s'assurera donc qu'il saisit bien un langage valide dans cette liste.

Exercice Formulaire couleurs

Créer un tableau contenant une liste de couleurs.

Afficher cette liste dans un formulaire avec des checkboxes. Chaque checkbox sera associée à une couleur.

L'utilisateur pourra choisir ses couleurs préférées. Au moment de la soumission du formulaire, on affichera la liste des couleurs choisies ainsi qu'un petit carré représentant la couleur.

<input type="checkbox" name="colors[]" value="blue">

Inclusion

On peut organiser notre code PHP dans plusieurs fichiers grâce aux inclusions.

<?php

/**
 * Incluera le contenu de header.php
 * Génère une erreur fatale en cas d'erreur
 */
// Exécute le contenu de header.php
require('header.php');


/**
 * Incluera le contenu de header.php
 * Déclenche un warning en cas d'erreur
 */
// Exécute le contenu de header.php
include('header.php');

Inclusion 2

<?php

/**
 * Le fichier header.php
 * ne sera inclus qu'à la premier instruction.
 */
include_once('header.php');
include_once('header.php');
include_once('header.php');

/*
PHP met à notre disposition des constantes magiques qui peuvent
s'avérer très utiles pour l'inclusion :
__DIR__ - Le répertoire du script actuel
__FILE__ - Le fichier du script actuel
__LINE__ - La ligne actuelle dans le script
__FUNCTION__ - Le nom de la fonction actuelle
*/

/**
 * Inclus le fichier header.php qui se situe dans
 * le même répértoire que celui du script
 */

//  Permet d'éviter les ambiguités
include(__DIR__.'/header.php');

Exercices

.
├── contact.php
├── index.php
└── partials
    ├── footer.php
    └── header.php
  1. Reproduire cette structure dans un dossier

2. index.php et contact.php doivent inclure header.php et footer.php

3. Intégrer la page HTML suivante en prenant soin de cleaner la page ou alors intégrer votre propre design avec Tailwind

4. Intégrer l'exercice des vidéos dans une page différente en intégrant la page au menu

5. Intégrer le formulaire de contact sur la page contact.php

Exercices

Ici, je peux vous donner des exercices de révisions.

PDO

L'extension PHP Data Objects (PDO) est une interface permettant d'interroger différents types de base de données. Elle est généralement utilisée en interface pour MySQL.

On peut facilement switcher entre MySQL, sqlite, PostgreSQL sans modifier le code.

Performant et possède des méthodes permettant de se prémunir des injections SQL.

ATTENTION, ne plus utiliser mysql_connect()

Utilisation

PDO est une classe. Elle doit être instanciée. Son instance représente la connexion de PHP à la base de données.

<?php

// $db est un objet PDO
// Le premier paramètre est le DSN (Data Source Name)
$db = new PDO('mysql:host=localhost;dbname=ma_bdd', 'login', 'password');

// $query est un objet PDOStatement
$query = $db->query('SELECT * FROM ma_table');

// $result et $results sont des tableaux / objets
// contenant les colonnes en clé et les données en valeur
$result = $query->fetch(); // Renvoie une seule ligne de résultat
$results = $query->fetchAll(); // Renvoie toutes les lignes de résultat

Erreurs

Il peut y avoir des erreurs à la connexion. Dans ce cas, il faut vérifier la syntaxe ou alors que les accès soient corrects.

<?php

$db = new PDO('mysql:host=localhost;dbname=ma_bdd', 'login', 'password');

// [2002] php_network_getaddresses: getaddrinfo failed: Hôte inconnu
// [2002] Une tentative de connexion a échoué car le parti connecté
// n'a pas répondu convenablement au-delà d'une certaine durée
// ou une connexion établie a échoué car l'hôte de connexion n'a pas répondu.
// Erreur de couple login/mot de passe
// [1045] Access denied for user 'root'@'localhost' (using password: YES)
// La base de données n'existe pas
// [1049] Unknown database 'db_name'

Récupérer des résultats

<?php

$db = new PDO('mysql:host=localhost;dbname=ma_bdd', 'login', 'password', [
    // On récupère tous les résultats en tableau associatif
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);

$db->query('SELECT * FROM table');
// Renvoie toutes les lignes de résultat
// sous forme d'un tableau indexé numériquement
$db->fetch(PDO::FETCH_NUM);

// PDO::FETCH_BOTH Renvoie toutes les lignes de résultat
// sous forme d'un tableau associatif

On peut modifier la façon dont on récupère les résultats.

Injection SQL

L'injection SQL consiste à profiter d'une faille dans les paramètres d'une requête SQL afin d'exécuter un code malicieux.

<?php

$id = $_GET['id']; // Si je passe "10; DROP DATABASE site;" dans l'url ??

$query = $db->query('SELECT * FROM user WHERE id = '.$id);
// La requête sera SELECT * FROM user WHERE id = 10; DROP DATABASE site;
$user = $query->fetch();

Injection SQL 2

On peut utiliser une requête préparée afin de se prémunir des injections SQL.

<?php

$id = intval($_GET['id']);
// Si je passe "10; DROP DATABASE site;" dans l'url,
// cela renverra 10

$query = $db->query('SELECT * FROM user WHERE id = '.$id);
// La requête sera SELECT * FROM user WHERE id = 10
$user = $query->fetch();

// C'est mieux, mais il vaut mieux utiliser une requête préparée.
$search = $_GET['q'];

$query = $db->prepare('SELECT * FROM articles WHERE title LIKE :search');
// Si je passe "chaine; DROP DATABASE site" dans la requête
// SELECT * FROM articles WHERE title LIKE "chaine; DROP DATABASE site"
$query->bindValue(':search', $search, PDO::PARAM_STR);
$query->execute(); // Ne pas oublier d'exécuter la requête
$search_results = $query->fetchAll();

Attaque XSS

L'attaque XSS (cross-site scripting) consiste à injecter du contenu dans une page comme une balise script par exemple.

<?php
$pseudo = $_POST['pseudo'];

$query = $db->prepare('INSERT INTO
user (pseudo)
VALUES (:pseudo)');
$query->bindValue(':pseudo', $pseudo, PDO::PARAM_STR);
$query->execute();
?>
<form method="POST">
    <input name="pseudo" type="text" />
    <input type="submit" value="OK" />
</form>
<?php
$query = $db->query('SELECT pseudo FROM user');
$users = $query->fetchAll();

foreach($users as $user) {
    echo $user['pseudo'].'<br>';
}

Que se passe t-il si j'ajoute un utilisateur avec le pseudo <script>location.href = 'http://www.google.fr';</script>

Attaque XSS 2

Pour se prémunir des attaques XSS, il faut utiliser des fonctions PHP

<?php

// Supprime toutes les balises HTML
$pseudo = strip_tags($_POST['pseudo']);
// Remplace tous les caractères HTML par leur équivalent en HTML entities
$pseudo = htmlspecialchars($_POST['pseudo']);

$query = $db->prepare('INSERT INTO
user (pseudo)
VALUES (:pseudo)');
$query->bindValue(':pseudo', $pseudo, PDO::PARAM_STR);
$query->execute();
?>
<form method="POST">
    <input name="pseudo" type="text" />
    <input type="submit" value="OK" />
</form>

Requête préparée

<?php

$query = $db->prepare('SELECT * FROM ma_table WHERE id = :id');
// La méthode bindValue() permet de transmettre la valeur
// des paramètres d'une requête préparée.
// Elle prends 3 arguments
// Le nom du paramètre sous la forme :nom;
// La valeur du paramètre qui peut être une chaîne ou un nombre;
// Le type du paramètre
// (PDO::PARAM_STR pour les chaînes, PDO::PARAM_INT pour les nombres);
$query->bindValue(':id', 42, PDO::PARAM_INT);
// Avec des points d'intérrogation
// $query = $db->prepare('SELECT * FROM ma_table WHERE id = ?');
// $query->bindValue(1, 42, PDO::PARAM_INT);
$query->execute();
$result = $query->fetch();


// bindParam() est similaire mais permet de gagner en performances
// quand on a de nombreuses requêtes. le paramètre est lié à une
// variable qui n'est pas encore définie.
$query = $db->prepare('INSERT INTO ma_table SET param = :param');
$query->bindParam(':param', $param, PDO::PARAM_INT);

for($i = 0; $i < 10; $i++) {
    $param = $i;
    $query->execute();
}   

Requêtes CRUD

<?php

// Insertion
$query = $db->prepare('INSERT INTO ma_table (col1, col2) VALUES (:value1, :value2)');
$query->bindValue(':value1', 123, PDO::PARAM_INT);
$query->bindValue(':value2', 'test', PDO::PARAM_STR);
$query->execute();
// Retourne l'identifiant inséré par la requête
// (nécessite une clé primaire en AUTO_INCREMENT)
$insert_id = $db->lastInsertId();

// Update
$query = $db->prepare('UPDATE ma_table SET col = :value WHERE id = :id');
$query->bindValue(':value', 'test', PDO::PARAM_STR);
$query->bindValue(':id', 123, PDO::PARAM_INT);
$query->execute();
// Retourne le nombre de lignes affectées par la requête
$affected_rows = $query->rowCount();

// Suppression
$query = $db->prepare('DELETE FROM ma_table WHERE id = :id');
$query->bindValue(':id', 123, PDO::PARAM_INT);
$query->execute();
// Retourne le nombre de lignes affectées par la requête
$affected_rows = $query->rowCount();

Exercice

  1. Créer une BDD et une table contacts
  2. Créer les colonnes id (INT primary), name (VARCHAR 255) et message (TEXT)
  3. Créer une page php avec un formulaire permettant d'ajouter son nom et un message
  4. A la soumission du formulaire, vérifiez les erreurs. Le nom ne doit pas être vide et le message doit faire 15 caractères minimum.
  5. S'il n'y a aucune erreur, on ajoute le message dans la BDD une fois le formulaire soumis et on affiche un message de succès sinon on affichera les erreurs dans un cadre rouge.
  6. On affichera la liste des message en dessous du formulaire.
  7. Si on a 5 messages dans la table, on affiche une erreur disant que la limite des messages est atteinte.
  8. Ajouter un lien pour chaque message permettant de le supprimer (une page PHP contenant une requête en DELETE et redirigeant ensuite vers la liste avec un header location).
  9. BONUS: Ajouter une colonne created_at pour avoir la date d'ajout du message
  10. BONUS: Créer une page renvoyant les messages en JSON.

Exercice

 

 

Ici, je peux vous donner un exercice sur des produits dans une base de données.

Upload de fichier - Formulaire

Nous savons envoyer des données en $_POST. Il est également possible d'envoyer des fichiers.

Un formulaire d'upload doit absolument contenir l'attribut "enctype".

<!-- L'attribut enctype doit absolument être "multipart/form-data",
et la méthode doit être POST -->
<form method="POST" enctype="multipart/form-data">
    <!-- La balise input type="file" permet de
    sélectionner un fichier sur son ordinateur.
    Ne pas oublier l'attribut "name"-->
    <input type="file" name="picture" />
    <input type="submit" value="Envoyer"/>
</form>

Upload de fichier - $_FILES

Le fichier uploadé n'est pas disponible dans $_POST mais dans $_FILES.

Array
(
    [picture] => Array
    (
        // Nom original du fichier uploadé via le formulaire
        [name] => MonFichierOriginal.jpg
        // Type "mime" du fichier, plus fiable que l'extension
        [type] => image/jpg
        // Chemin complet du fichier uploadé sur le serveur
        [tmp_name] => chemin_complet_du_fichier_sur_le_serveur
        // Un code d'erreur si il y a une erreur, 0 si tout est ok
        [error] => 0
        // La taille en octets du fichier uploadé
        [size] => 1000
    )
)

Upload de fichier - Traitement

// Retourne l'emplacement du fichier
$file = $_FILES['picture']['tmp_name'];

// Récupère le nom du fichier
$originalName = $_FILES['picture']['name'];
// Récupère l'extension du fichier
$extension = pathinfo($originalName)['extension'];

// Renomme le fichier
$md5 = md5($originalName.uniqid());
$filename = $md5.'.'.$extension;

// Déplace le fichier vers un répertoire
move_uploaded_file($file, __DIR__.'/upload/'.$filename);

Renommer le fichier peut être pratique afin d'être sûr qu'il porte un nom propre et unique.

Exercices

1. Nous allons créer un formulaire de candidature à une offre d'emploi

2. L'utilisateur pourra envoyer son CV en PDF. On devra vérifier le format et la taille (limité à 5mo).

3. L'utilisateur pourra saisir son prénom, on renommera le CV avec son prénom hashé en MD5 et une partie unique.

4. On stockera les utilisateurs dans une base de données avec le chemin du CV.

5. BONUS : On ajoutera l'upload d'une image. Idéalement, on essaiera de redimensionner l'image en 300x300 dans un nouveau fichier. Voir l'extension GD.

Traitement des fichiers

// Ouvre le fichier comme dans Word et retourne une ressource
$file = fopen('C:/xampp/htdocs/', 'r');
// Le 2ème paramètre est le mode de lecture
// "r" : "read-only". Ouvre le ficher en lecture seule.
// "r+" : Ouvre le ficher pour l'écriture et la lecture.
// (un "niveau" de plus que "r")
// "w+" : "write". Ouvre le fichier pour l'écriture et la lecture, et
// commence par le vider. Si le fichier n'existe pas, PHP tente de le créer.
// "a" : "append". Ouvre le fichier en écriture seule
// (voir un exemple plus loin), et place le pointeur à la fin du fichier.
// "a+" : "append". Ouvre le fichier en lecture et écriture,
// et place le pointeur à la fin du fichier.

PHP est un langage côté serveur et permet donc de manipuler des fichiers.

Traitement des fichiers - Lecture/Ecriture

// Ouvrir le fichier et placer le pointeur (le curseur) à la fin
$fileHandler = fopen('/var/log/db.log', 'a+');
// Ajouter une ligne pour la date d'aujourd'hui
$text = date('Y-m-d H:i:s') . ' : Une connexion a été ouverte';
fwrite($fileHandler, $text);

// Ouvrir le fichier et placer le pointeur au début
$fileHandler = fopen('/var/log/db.log', 'r');
// Enregistrer les dix premiers caractères
$start = fread($fileHandler, 10);
// Afficher le résultat
echo $start;

// On peut/doit fermer le fichier comme on ferme Word
fclose($fileHandler);

Traitement des fichiers - Raccourci

// Le code suivant récupère, dans la variable $fileContent,
// la totalité du fichier log.txt.
$fileContent = file_get_contents('log.txt');

// Le code suivant va enregistrer dans la variable $fileSection
// les dix caractères à la vingtième position du fichier
// log.txt (les caractères 20 à 29) :
$fileSection = file_get_contents('log.txt', NULL, NULL, 20, 10);

// Récupère l'intégralité du contenu du fichier
$fruits = file_get_contents('fruits.txt');
// Ajoute une ligne
$fruits .= "Cerise\n";
// Écrit le contenu mis à jour dans le fichier ouvert
file_put_contents('fruits.txt', $fruits);

// Pour ajouter le contenu dans un fichier existant
file_put_contents('fruits.txt', 'Fraise'.PHP_EOL, FILE_APPEND);

// Supprime le fichier
unlink('log.txt');

Traitement des fichiers - Fonctions

// Vérifie qu'un fichier existe
file_exists('./img/image.jpg');
// Modifie les permissions d'un fichier
chmod('./img/image.jpg', 0644);
// Vérifie qu'un dossier existe
is_dir('/var/site/img');
// Copie un fichier
copy('./img/image.jpg', './backup/img/image.jpg');
// Déplace ou renomme un fichier
rename('./img.png', '../img.png');
// Donne le nom du dossier d'un fichier
dirname(__FILE__) === __DIR__;
// Date de dernière modification d'un fichier
$filename = 'access.log';
if (file_exists($filename)) {
    echo "$filename a été modifié le " . date('d/m/Y à H:i:s.', filemtime($filename));
}

Exercices

1. Nous allons créer un formulaire de commande Click'N'Collect

2. L'utilisateur pourra saisir son email et choisir parmi une liste de produits (Select, checkbox ou textarea)

3. On stockera l'ensemble des demandes dans un fichier .txt que le vendeur pourra retrouver avec la date et l'heure

4. Idéalement, on créera une page pour le vendeur afin qu'il puisse retrouver l'ensemble des commandes (en lisant le contenu du fichier)

5. Chaque produit sera associé à un prix, sur la page du vendeur, on affichera donc le total de toutes les commandes.

Exercices

1. Nous allons créer un système de compteur

2. A chaque visite sur le site, on va stocker une valeur dans un fichier

3. A chaque nouvelle visite, on devra incrémenter la valeur actuelle du fichier de +1

4. On affichera bien sûr le nombre de visites sur le site

5. Si le visiteur est le 10ème, on affichera un petit message pour le féliciter

PHP 7

Evolution majeur de PHP.

PHP 6 a été abandonné.

2 fois plus performant que PHP 5.

 

Infographie

PHP 7 - Nouveautés

// Spaceship operator : <=>
// 0 si les deux opérandes sont égaux,
// 1 si celui de gauche est plus grand
// -1 si celui de droite est plus grand.

// Integers
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1

// Strings
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1

// Null coalesce operator : ??
// Avant
$var = isset($maVar) ? $maVar : 'valeur_par_defaut';
// Après
$var =  $maVar ?? 'valeur_par_defaut';

PHP 7 - Typage

// Si cette ligne est présente, les paramètres ne sont
// pas convertis vers le type attendu et cela
// retourne une erreur fatale
declare(strict_types=1);

// On spécifie que $nom doit être un string et $age un integer
function identite(string $nom, int $age) {
    echo $nom. 'a '.$age.' ans';
}

// On spécifie que la valeur du retour doit être un bolean.
function isAdult(int $age) : bool {
    return $age >= 18;
}

PHP 7 ne lève que des exceptions lors des erreurs, ce qui permet de catcher plus facilement les erreurs pour le développeur.

PHP 7 - Dépréciation

Les fonctions en mysql_* n'existent plus (extension mysql).

Les fonctions en ereg_* n'existent plus (extension ereg).

mcrypt est déprécié en 7.1 et supprimé en 7.2

Les sessions

Chaque utilisateur d'un site se voit attribué une session avec un identifiant unique. Les sessions expirent après quelques minutes.

// Pour utiliser les sessions
session_start();

// Affiche toutes les informations dans la session courante
print_r($_SESSION);

// Enregistrer une valeur en session
$_SESSION['ma_cle_tableau'] = 'toto';

// Accèder à une variable de session
echo $_SESSION['ma_cle_tableau'];

// Supprimer une variable de session
unset($_SESSION['ma_cle_tableau']);

// Redirection
header('Location: index.php');

Les cookies

Un cookie est une session qui est stockée sur la machine de l'utilisateur. Le cookie peut avoir une durée d'expiration.

// Pour créer un cookie qui expire dans 1 heure
setcookie('fiofio', 'Ici, je peux stocker des trucs', time() + 3600);

// Affiche tous les cookies du site
print_r($_COOKIE);

// Accèder à la valeur d'un cookie
echo $_COOKIE['fiofio'];

// Supprimer un cookie
setcookie('fiofio', '', 1);

Exercice

1. Créer un formulaire (index.php) où on demande à l'utilisateur login et mot de passe.

2. Si l'utilisateur se connecte avec admin et admin, c'est correct sinon on renvoie une erreur.

3. Quand il est connecté, on le redirige vers une page connecte.php en ayant au préalable enregistré une valeur en session.

4. On ajoute un bouton "Déconnexion" qui doit supprimer une variable de session pour déconnecter et rediriger l'utilisateur vers la page de connexion.

Exercice 2

5. Créer un nouveau formulaire d'inscription (Login et mot de passe)

6. On ajoutera l'utilisateur dans une table. On doit stocker le login et le mot de passe. L'utilisateur devra confirmer son mdp. On affichera les erreurs ou un succès.

7. Dans le formulaire de login, on peut maintenant vérifier que la personne qui se connecte est présente dans la table grâce à un SELECT et un WHERE.

8. Si la personne est présente avec le bon mot de passe, elle se connecte.

Exercice 3

9. Vérifier qu'un utilisateur ne puisse pas s'inscrire 2 fois avec le même pseudo.

10. On voudrait avoir le formulaire de login et d'inscription sur la même page. Comment pourrait-on faire ?

11. Pour plus de sécurité, on devra hasher le mot de passe à l'inscription. Cela veut dire qu'il faudra comparer le hash lors du login pour voir s'il correspond au mot de passe saisi.

12. Ajouter une case "Se rappeler de moi", au moment du login, on doit créer un cookie valide 1 année. A chaque requête sur le PHP, on regarde si un cookie est présent mais que la session est vide. Dans ce cas, on connecte l'utilisateur du cookie automatiquement. Attention aux failles de sécurité.

Les mots de passe

// Hachage de mot de passe selon l'algorithme bcrypt
$password = password_hash('toto', PASSWORD_DEFAULT);

// Retourne true ou false si correspondance
password_verify('toto', $password);

On ne conserve jamais les mots de passe en clair dans une base de données. On préférera les hacher.

On ne doit pas pouvoir retrouver le mot de passe. On doit comparer le vrai mot de passe et vérifier s'il y a une correspondance avec un hash.

NE PAS UTILISER md5 OU sha1

Composer

Gestionnaire de dépendances PHP

Déclarer et installer les bibliothèques/frameworks nécessaires pour un projet PHP

Equivalent de NPM pour le PHP

Composer - Installation

Mettre à jour facilement les librairies

S'assurer que tout le monde utilise la même version

Pour installer Composer : https://getcomposer.org/doc/00-intro.md

Composer - Usage

Composer s'utilise en CLI

# Je me déplace dans mon projet
cd monProjet/

# J'initialise composer comme pour git
composer init

# On répond aux différentes questions
# nous permettant de configurer notre projet

Composer.json

Le fichier composer.json définit notre projet ainsi que ses dépendances.

On peut trouver des dépendances sur Packagist.org

{
    "name": "matthieu/test",
    "authors": [
        {
            "name": "Matthieu Mota",
            "email": "matthieumota@gmail.com"
        }
    ],
    "require": {
        "fzaninotto/faker": "^1.7"
    }
}

Composer - Gestion

Pour gérer nos dépendances

# La commande va modifier notre fichier composer.json
# et installer la dépendance
composer require swiftmailer/swiftmailer

# Un dossier vendor sera crée, il possède toutes nos dépendances

# Si on récupére un projet existant,
# on peut installer les dépendances
# composer partira du fichier composer.lock
# qui vérouille les versions à installer
composer install

# Pour mettre à jour les dépendances sans
# se soucier du composer.lock
composer update

# On peut également modifier la section
# require du fichier composer.json et lancer
composer update

Composer - Versions

"require": {
    "vendor/package": "1.3.2", // seulement la 1.3.2

    // >, <, >=, <=
    "vendor/package": ">=1.3.2", // supérieur ou égal à 1.3.2
    "vendor/package": "<1.3.2", // inférieur à 1.3.2

    // *
    "vendor/package": "1.3.*", // >=1.3.0 <1.4.0

    // ~
    "vendor/package": "~1.3.2", // >=1.3.2 <1.4.0
    "vendor/package": "~1.3", // >=1.3.0 <2.0.0

    // ^
    "vendor/package": "^1.3.2", // >=1.3.2 <2.0.0
    "vendor/package": "^0.3.2", // >=0.3.2 <0.4.0 // sauf si la version majeur est 0
}

Possibilité d'utiliser des contraintes sur l'utilisation de versions

Pour tester : https://semver.mwl.be

Made with Slides.com