$_GET
) et POST ($_POST
)isset
, htmlentities
$_COOKIE
) \(\rightarrow\) données stockées chez le client$_SESSION
) \(\rightarrow\) données stockées sur le serveurthis
try
/ catch
/ throw
Deux cycles vont s’enchaîner :
Attention, chaque TP est basé sur le précédent,
ne prenez pas de retard !
function doIt( bool $arg, int $i ) : void
{
// Traitements...
}
doIt( true, 1 );
Sans retour
function doItAgain() : string
{
// Traitements...
return $result;
}
$myString = doItAgain();
Avec retour
array
, bool
, float
, int
, string
et object
.En PHP, typer signifie transtyper si le type utilisé n’est pas le bon.
function add( float $a, float $b ) : float {
return $a + $b;
}
echo add( 3, 4 ); // Affiche 7
echo add( 3, 4.99 ); // Affiche 7.99
echo add( 3, "4.3" ); // Affiche 7.3
echo add( 3, "plop" ); // Error
Transtypage des arguments
function add( float $a, float $b ) : int {
return $a + $b;
}
echo add( 3, 4 ); // Affiche 7
echo add( 3, 4.99 ); // Affiche 7
echo add( 3, "4.3" ); // Affiche 7
echo add( 3, "plop" ); // Error
Transtypage de la valeur de retour
Note : Il est possible d’imposer un typage strict en déclarant cette instruction en début de fichier :
declare(strict_types=1);
\(\rightarrow\) Un lien intéressant qui triture le typage.
class Truc
{
public int $membre;
public function methode() { ... }
}
Définition de la classe Truc
$obj = new Truc();
echo var_dump($obj);
// Affiche :
// object(Truc)#1 (1) { ["membre"]=> NULL }
Instanciation d’un objet de type Truc
new
jusqu’à sa destruction.
class MaClasse {
public string $attribut1;
public int $attribut2 = 31;
}
// Création d'un objet
// de type MaClasse
$obj = new MaClasse();
// Accès aux attributs publics
echo $obj->attribut2;
// Modification d'un attribut
$obj->attribut1 = "W31";
->
suivi de son nom sans le symbole $
Attention, le typage des attributs ne fonctionne qu’avec PHP >= 7.4 !
class MaClasse
{
private int $val;
public function __construct( int $valeur ) { $this->val = $valeur; }
public function __destruct() {}
public function getVal() : int { return $this->val; }
public function setVal( int $valeur ) : void { $this->val = $valeur; }
}
// Création d'un objet
$obj = new MaClasse(5);
echo $obj->getVal();
// Affiche "5"
$obj->setVal( 31 );
echo $obj->getVal();
// Affiche "31"
$this
:\(\rightarrow\) L’implémentation d’une méthode définit un comportement pour tous les objets $this
sur lesquels elle sera appelée.
function diviser( int $num, int $denom ) : float
{
if ( $denom == 0 ) {
throw new Exception("Division par zéro");
}
return $num / $denom;
}
Déclenchement d’une exception.
try {
echo diviser(4,5);
echo diviser(4,0);
}
catch ( Exception $e ) {
echo "Erreur : " . $e->getMessage();
}
Capture d’une exception.
throw
try
catch
Exception
ou d’un sous-typeEn PHP, il est nécessaire d’utiliser une extension pour manipuler une base de données. La référence en la matière est l’extension PDO.
PDO est une interface d’abstraction, c’est-à-dire qu’elle permet d’écrire du code indépendamment du SGBD utilisé.
$SQL_DSN = 'sqlite:/home/.../bdd.db';
try {
$pdo = new PDO($SQL_DSN);
}
catch( PDOException $e ) {
echo 'Erreur : '.$e->getMessage();
exit;
}
SQLite
$SQL_DSN = 'mysql:host=bdd.site.fr;dbname=w31';
$SQL_LOGIN = 'login';
$SQL_PASS = 'password';
try {
$pdo = new PDO($SQL_DSN, $SQL_LOGIN, $SQL_PASS);
}
catch( PDOException $e ) {
echo 'Erreur : '.$e->getMessage();
exit;
}
MySQL/MariaDB
La création d’un objet PDO pour SQLite nécessite un seul argument, le DSN, contenant le type de SGBD et le chemin absolu du fichier de BDD.
Attention : Une PDOException
est déclenchée si la connexion échoue,
il faut toujours la “try-catcher” !
PDO::query( string $statement ) : PDOStatement
SELECT
).PDOStatement
contenant les données trouvées.false
en cas d’erreur.$request = $pdo->query( "SELECT * FROM Students" );
PDO::exec( string $statement ) : int
INSERT
, UPDATE
, DELETE
, etc.)$nbInsertions = $pdo->exec( "INSERT INTO Students(name) VALUES('Josh')" );
$nbUpates = $pdo->exec( "UPDATE Students SET name='John' WHERE name='Josh'" );
$nbDeletions = $pdo->exec( "DELETE FROM Students WHERE name='John'" );
$request = $pdo->query( "SELECT name FROM Students" );
$request
est un objet de la classe PDOStatement
.
foreach( $request as $row ) {
echo 'Nom : ' . $row['name'];
}
Parcours avec foreach
.
while ( $row = $request->fetch() ) {
echo 'Nom : ' . $row['name'];
}
Parcours avec while
et fetch
.
En complément de foreach
, la méthode fetch()
de la classe PDOStatement
permet de parcourir les données obtenues :
PDOStatement::fetch() : mixed
PDOStatement
.false
s’il n’y a pas de prochaine ligne.L’intérêt de la méthode fetch
se trouve dans les paramètres qu’on peut lui spécifier \(\rightarrow\) voir documentation.
PDO::prepare( string $statement ) : PDOStatement
PDOStatement
.$request = $pdo->prepare( "SELECT * FROM Students WHERE age > :value" );
PDOStatement::bindValue( mixed $param, mixed $val [, int $type ] ) : bool
$val
au marqueur $param
$request->bindvalue( ':value', 20, PDO::PARAM_INT );
PDOStatement::execute() : bool
$request->execute();
// 1.a Prépare la requête
$request = $pdo->prepare(
"SELECT name FROM Students
WHERE note > ? AND note < ?"
);
// 2.a Assigne 10 au 1er paramètre
$ok1 = $request->bindValue(
1, 10, PDO::PARAM_INT
);
// 3.a Assigne 20 au 2ème paramètre
$ok1 &= $request->bindValue(
2, 20, PDO::PARAM_INT
);
Marqueurs indexés : ?
// 1.b Prépare la requête
$request = $pdo->prepare(
"SELECT name FROM Students
WHERE note > :min AND note < :max"
);
// 2.b Assigne 10 au paramètre :min
$ok1 = $request->bindValue(
':min', 10, PDO::PARAM_INT
);
// 3.b Assigne 20 au paramètre :max
$ok1 &= $request->bindValue(
':max', 20, PDO::PARAM_INT
);
Marqueurs nommés : :name
// 4. On exécute la requête $request
$ok1 &= $request->execute();
// 5. On parcourt et affiche les données trouvées dans la base
foreach ( $request as $row ) {
echo "M. " . $row['name'] . ' a une note > 10';
}
Parcours des données identique.
Illustration des injections SQL au prochain TD.
MVC (Modèle-Vue-Contrôleur) est une architecture logicielle qui propose un découpage en trois entités :
Vous avez mis en place sans le savoir une architecture MVC avec l’authentification du TP2.
authenticate.php
manipule bdd.php
pour vérifier si l’utilisateur a le droit de se connecter et suivant le cas, sélectionne account.php
ou signin.php
.signout.php
déconnecte l’utilisateur et sélectionne signin.php
.bdd.php
est un modèle sous forme de tableau.authenticate.php
pour mettre à jour account.php
lorsque l’utilisateur se connecte.signin.php
affiche le formulaire d’authentification.account.php
affiche la page d’accueil personnalisée.interface Module
{
function name() : string;
function prof() : string;
}
class W31 implements Module
{
public string $prof;
function __construct( string $prof ) {
$this->prof = $prof;
}
function name() : string { return "W31"; }
function prof() : string { return $this->prof; }
}
interface Module
{
function name() : string;
function prof() : string;
}
function printModule( Module $mod )
{
echo $mod->name().' : '.$mod->prof();
}
class W31 implements Module {
function name() : string { return "W31"; }
function prof() : string { return "KRA"; }
}
class M31 implements Module {
function name() : string { return "M31"; }
function prof() : string { return "HAJ"; }
}
Définir une fonction qui manipule un objet implémentant une interface donnée garantit qu’il possède les méthodes de l’interface.
$mod1 = new W31();
printModule($mod1);
// Affiche "W31 : KRA"
$mod2 = new M31();
printModule($mod2);
// Affiche "M31 : HAJ"
\(\rightarrow\) la fonction est donc… générique par polymorphisme !
abstract class Module
{
private string $name;
function __construct( string $name ) {
$this->name = $name;
}
function print() : void {
echo $this->name.' : '.$this->prof();
}
abstract function prof() : string;
}
class W31 extends Module
{
function __construct() {
parent::__construct("W31");
}
function prof() : string {
return "KRA";
}
}
$obj = new W31();
$obj->print(); // Affiche "W31 : KRA"
abstract class MaClasseAbstraite
{
private $attribut1;
protected $attribut2;
abstract public function methode1();
abstract public function methode2();
public function methode3() { ... }
public function methode4() { ... }
}
class MaClasse extends MaClasseAbstraite
{
public function methode1() { ... }
public function methode2() { ... }
public function methode4() { ... }
}
$obj = new MaClasse();
$obj->methode2(); // OK
$obj->methode3(); // OK
$obj->methode4(); // OK
Comme les interfaces, elles permettent d’écrire du code générique. De plus, elles permettent de mutualiser du code.
Une classe qui hérite d’une classe abstraite :
abstract
de la classe mère