PHP

Histoire

Le web en 1993

CGI permet d'exécuter des applications de manière à générer le contenu d'une réponse dynamiquement sur le web, par exemple, en C en 1993:

PHP en 1994

PHP (à l'origine, Personal Home Page) est inventé pour simplifier la construction de la page, permettant d'introduire des variables à l'intérieur du texte, c'est à l'origine un langage de template:

Introduction

Aujourd'hui, PHP est un langage interprété utilisé principalement côté serveur dans des applications web.

On peut l'exécuter à l'aide de la ligne de commande php, par exemple:

<?php
// date.php
echo "Il est ".date('H:i:s')." !\n";

Et exécuter ce programme:

$ php date.php
Il est 17:25:12

Langage de template

Une particularité du langage est qu'il n'interprète que le contenu des balises PHP, qui commencent par <?php et ?>.

Le reste est envoyé sur la sortie standard ou vers le navigateur

Par exemple:

Hello world

Affichera "Hello world", tout comme:

<?php
echo "Hello world";

Ou encore:

Hello <?php echo "World"; ?>

Cette technique rend pratique la génération de formats textuels comme le HTML:

<h1>Bienvenue <?= $name ?></h1>

Vous avez <?= count($messages) ?> nouveaux messages:

<ul class="messages-list">
<?php foreach ($messages as $message) { ?>
    <li><?= $message['title'] ?></li>
<? } ?>
</ul>

Ici, la notation <?= $name ?> est un raccourci équivalente à <?php echo $name ?>

Principe du langage

Principes de bases

<?php
$a = 123;
$b = "456";
echo "a+b=".($a+$b)."\n";
$a = true;
  • Les variables sont préfixées par $
  • L'opérateur + est l'addition, et . la concaténation, il n'y a pas d’ambiguïté
  • Le typage est faible, $a peut prendre plusieurs type au cours de l'exécution

var_dump()

Une fonction pratique de PHP: var_dump(), qui vous affiche le contenu d'une variable quelle qu'elle soit:

<?php
$a = 123;
var_dump($a);
// int(123)
$a = [1, 2];
var_dump($a);
// array(2) {
//     [0]=>
//     int(1)
//     [1]=>
//     int(2)
// }

Tableaux

Le tableau en PHP, notés [] ou array() représente la structure de base utilisée dans le langage. Il peut être associatif ou non. Voici un exemple de deux tableaux, $fruits qui contient des éléments, et $couleurs qui est un tableau associatif qui fait correspondre le nom d'un fruit à sa couleur:

<?php
// Tableau d'éléments
$fruits = ['pomme', 'abricot', 'fraise'];
// $fruits[0] vaut "pomme" etc.

// Tableau associatif
$couleurs = [
    'pomme' => 'verte',
    'abricot' => 'orange',
    'fraise' => 'rouge'
];
// couleurs['pomme'] vaut 'verte' etc.

// Itération
foreach ($fruits as $fruit) {
    echo "Le fruit ".$fruit." a la couleur: ";
    echo $couleurs[$fruit]."\n";
}

Tableaux non associatifs

Voici un aperçu de quelques opérations classiques sur des tableaux non associatifs:

<?php
// Création d'un tableau vide
$numbers = [];

// Création d'un tableau non vide
$numbers = [1, 2, 3];

// Ajout de l'élément 4
$numbers[] = 4;

// Affichage de la taille du tableau
echo "Il y a ".count($numbers)." éléments:\n";

// Itération et affichage des éléments
foreach ($numbers as $number) {
    echo "- $number\n";
}

// Suppression en tête ou en queue
array_pop($numbers); // Suppression du dernier élément
array_shift($numbers); // Suppression du premier élément

Tableaux associatifs

Voici un aperçu des opérations classiques sur un tableau associatif:

<?php
// Création du tableau vide
$nameToAge = [];

// Création d'un tableau contenant déjà des éléments
$nameToAge = ['Ryan' => 30, 'Nina' => 12];

// Association d'un élément
$nameToAge['Gilbert'] = 56;

// Suppression d'un élément
unset($nameToAge['Ryan']);

// Vérification de l'existence
if (isset($nameToAge['Ryan'])) 
    echo "Ryan est présent!\n";

// Parcours
foreach ($nameToAge as $name => $age) 
    echo "$name a $age ans!\n";

Passerelle HTTP

Utilisé en mode serveur, PHP permet d'accéder à un ensemble d'informations sur la requête en cours.

Serveur intégré

Vous pouvez utiliser le serveur intégré de PHP, qui permet de lancer un serveur directement en ligne de commande:

php -S 127.0.0.1:8080

Cela lancera un serveur web qui interprétera les pages PHP. Si vous chargez http://127.0.0.1:8080/date.php, vous verrez apparaître le message dans votre navigateur.

Paramètres GET

Les paramètres GET sont passés dans l'URL de la requête, par exemple:

http://127.0.0.1:8080/index.php?prenom=Jack&nom=Smith

Ici, les variables prenom=Jack et nom=Smith sont passées en paramètre GET de la page index.php.

Ce dernier se retrouvera dans le tableau $_GET:

<?php
// index.php
if (isset($_GET['prenom']) && isset($_GET['nom'])) {
    echo "Bonjour ".$_GET['prenom']." ".$_GET['nom']."!";
}

Paramètres POST

Les paramètres POST sont passés dans le corps de la requête, ils peuvent par exemple être obtenus par un formulaire:

<form method="post" action="hello.php">
    Prénom: 
    <input type="text" name="prenom"/><br />
    Nom: 
    <input type="text" name="nom"/><br/>
    <hr />
    <input type="submit" value="Envoyer" />
</form>

Une fois le formulaire soumis, ces paramètres seront disponibles dans le tableau PHP $_POST:

<?php
// hello.php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    echo "Bonjour ".$_POST['prenom']." ".$_POST['nom']."!";
}

Fonctions

PHP comporte de nombreuses fonctions natives!

Pensez à vous documenter sur php.net!

Base de données

L'interface PDO de PHP est aujourd'hui un moyen uniforme d'accéder à de nombreuses bases de données différentes.

La connexion se fait en instanciant un objet de type PDO:

<?php
$pdo = new PDO($dsn, $user, $password)

Où:

  • $dsn, pour data source name est la chaîne de connexion à la base de données
  • $user est l'identifiant de l'utilisateur
  • $password est le mot de passe de l'utilisateur

Par exemple:

<?php
$dsn = "mysql:dbname=shows;host=info-titania";
$user = 'user';
$password = 'password';
$pdo = new PDO($dsn, $user, $password);

Etablira la connexion avec la base de données du département.

  • mysql est le nom du driver, car la base de données est du type MySQL/MariaDB,
  • info-titania est le nom d'hôte du serveur sur le réseau,
  • shows est la base de données sur le serveur.

Requête simple

La fonction PDO::query() permet d'effectuer une requête simple dans la base:

<?php
$sql = "SELECT title FROM series WHERE year_start < 2005";
$query = $pdo->query($sql);
foreach ($query as $row) {
    echo 'Nom : ' . $row['title']. "\n";
}

L'objet retourné par PDO::query() est itérable, et fournit des tableaux associatifs faisant correspondre les noms de colonnes aux valeurs.

Itération sur requête vs fetch()

L'itération sur la requête ($query) est en fait équivalente à des appels successifs de $query->fetch() jusqu'à récupérer la valeur FALSE:

<?php
foreach ($query as $row) {
}
// Est équivalent à
while ($row = $query->fetch()) {
}

Requête paramétrée

La fonction PDO::prepare() permet de créer une requête préparée, c'est à dire contenant un paramètre.

Par exemple:

$sql = "SELECT * FROM series WHERE title = :title";
$query = $pdo->prepare($sql);
if ($query->execute(['title' => 'Dexter'])) {
    foreach ($query as $row) {
        echo 'Nom : ' . $row['title']. ", année de début: " . $row['year_start'] . "\n";
    }
}

Ici, :title est un paramètre préparé de la requête qui est fourni au moment de l'exécution avec PDO::execute().

Une autre solution est de ne pas donner de nom aux paramètres, et d'utiliser le symbole ?:

$sql = "SELECT * FROM series WHERE title = ?";
$query = $pdo->prepare($sql);
$success = $query->execute(['Dexter']);
// ...

Dans ce cas, l'ordre des éléments du tableau de PDO::execute() sera pris en compte

Nombre de résultats

Il est possible d'utiliser la méthode rowCount() sur un objet de type PDOStatement (obtenu à l'aide de query() ou prepare()) pour savoir combien de lignes ont été retournées:

<?php

$query = $pdo->query('SELECT title FROM series');
echo "Il y a ".$query->rowCount()." résultats";

Attention, c'est cependant très différent que de faire:

<?php

$query = $pdo->query('SELECT COUNT(*) as nb FROM series');
$result = $query->fetch();
echo "Il y a ".$result['nb']." résultats";

Cookies et sessions

Cookies

Les cookies sont des données stockées par le navigateur à la demande du serveur web.

En PHP, on peut les créer à l'aide de setcookie:

<?php
// Crée un cookie "nom" qui a comme valeur "bob"
setcookie('nom', 'bob');

On peut alors accéder aux cookies définis à l'aide du tableau $_COOKIE:

<?php
// Le cookie nom a t-il été fourni ?
if (isset($_COOKIE['nom'])) { 
    echo "Bonjour ".$_COOKIE['nom'];
}

Sessions

Comment, à partir des cookies, créer un système d'identification ?

Sachant que les cookies sont stockés en clair, ils peuvent donc être modifiés arbitrairement par l'utilisateur.

Pour cela, on va générer aléatoirement un "jeton", qui permettra de reconnaître un utilisateur de manière unique, par exemple 0E28B4E12, et le stocker dans un cookie, par exemple ID.

Lorsque le client fournira ID=0E28B4E12, le serveur le reconnaîtra et pourra récupérer un "paquet" de variables qui lui sont associées.

Si le client prend un ID au hasard, il n'a statistiquement pas de chance de tomber sur un ID existant.

Ce mécanisme se nomme session, et est implémenté en PHP:

<?php
// Initialise le système de sessions
session_start();

if (isset($_SESSION['user'])) 
    echo "Bienvenue ".$_SESSION['user']."!";
} else {
    header('location: login.php');
}

Ici, on peut lire, écrire et vérifier la présence de valeurs dans le tableau $_SESSION, qui est stocké côté serveur.