– support stone thrones tickoon zoo ristoo fi,der otelo finder
Présentation
PHP: Hypertext Preprocessor est un langage libre de 1994. Exécuté coté serveur web, il peut générer du code HTML.
Avantages
- populaire
- interprété par le serveur, indépendant de l’OS
- non verbeux
- création de page web dynamiques
- disponible sur tous les hébergements
Inconvenients
- syntaxe fouillie, ajout de l’objet à posteriori
- prise en charge des types incomplete
- plus lent et moins à la mode que NodeJS
Utilisation
Il peut être déployé sur différents serveurs web comme
- Internet Information Services IIS, de Microsoft
- Apache HTTP Server de la Apache Software Foundation
- lighttpd de Jan Kneschke ;
- nginx d’Igor Sysoev ;
Attention, les anciens accès aux bases MySQL sont dépréciés (mysql_query par exemple).
Les métiers
- developer Back-end (J2E ou Java EE)
- developer Front-end
- developer Full-stack
- lead developer
- chief technology officer ( CTO )
Premier code
On doit indiquer les balises HTML et insérer du code PHP.
Tout code PHP commence par une balise < ?php et termine par ?> sauf pour les fichiers 100% PHP.
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>mon titre</title> </head> <body> <?php echo "Je suis un script PHP qui va être affiché en HTML » ; ?> </body> </html>
Envoie du code HTML depuis le serveur PHP
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>mon titre</title> </head> <body> Je suis un script PHP qui va être affiché en HTML </body> </html>
Toutes les variables commencent par des $, on termine les lignes d’instructions par des ;
Par défaut il n’y a pas de type de variables.
<?php $a=5; //commentaire /*com- mentaire */
Inclusion de code
On utilise include ou require pour importer du code. Il sera alors exécuté à l’endroit où il est inséré.
L’instruction require bloquera le script si une erreur survient, par exemple si le fichier n’est pas trouvé.
On peut utiliser require_once ou include_once pour n’inclure qu’une seule fois le script.
maPage.php
<?php echo « meumeu » ;
secondePage.php
<?php require_once ‘maPage.php’;
Changement automatique de page
On souhaite aller sur le site de Google en appelant une page
Il est nécessaire de ne pas placer de sortie HTML avant le header. Une balise HTML provoquera une erreur de la fonction header (On lui demande de changer de page alors qu’on lui a passé un script qui génère une page, d’où le conflit)
<?php header("Location: http://www.google.com/"); /* Pour être certain que le code se bloque à la redirection*/ exit;
Le typage
Il est possible d’obliger les fonctions à prendre certains types pour leurs paramètres. De grandes évolutions depuis la version 7.2
public function test(int $a) { echo $a; }
Variables prédéfinies
PHP possède plusieurs variables utiles accessibles sur vos pages.
http://www.php.net/manual/fr/reserved.variables.php
Les variables HTTP
Un tableau associatif des valeurs passées au script courant via le protocole HTTP et la méthode POST. Cf formulaire
session_start(); $_POST[‘monNameDeInput’] ;
Un tableau associatif des valeurs passées au script courant via le protocole HTTP et la méthode GET. Cf formulaire
session_start(); $_GET[‘monNameDeInput’] ;
Un tableau associatif des valeurs passées au script courant via le protocole http. Il contient les variables de $_GET, $__POST et $_COOKIE
session_start(); $_REQUEST[‘monNameDeInput’] ;
Les variables de sessions
Un tableau associatif des valeurs stockées dans les sessions, et accessible au script courant.
On pourra s’intéresser par la suite au tableau associatif cookie et files.
session_start(); $_SESSION[‘maVariable’] =28;
Les formulaires
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>mon titre</title> </head> <body> <form method="post" id="frmConnection" action="recuperation.php"> <label for="email"> Votre email:</label> <input type="email" name="txtEmail" id="txtEmail" autofocus /> </br> <label for=" txtPass "> Mot de passe :</label> <input type="password" name="txtPass" required /> <input type="submit" name="cmd" id="cmd" value=" envoie " /> </form> </body> </html>
Fichier recuperation.php
On récupère les champs d’un formulaire grâce aux attributs name
La fonction isset() vérifie que le paramètre est renseigné. Si le champ n’est pas rempli dans le formulaire, la variable n’existera pas dans recuperation.php, ce qui génère une erreur si on y accède.
<?php session_start(); if (isset($_POST[‘txtEmail’])) { echo $_POST[‘txtEmail’]; }
Retour sur même page de formulaire
maPage.php
La page sera rechargée avec l’affichage des données entrées
<?php session_start()?> <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>mon titre</title> </head> <body> <?php if(isset($_POST["cache"])){ echo "vos valeurs ".$_POST[txtEmail]." ".$_POST[txtPass]; }else{ ?> <form method="post" id="frmConnection" action=" maPage.php"> <label for="email"> Votre email:</label> <input type="email" name="txtEmail" id="txtEmail" autofocus /> </br> <label for=" txtPass "> Mot de passe :</label> <input type="password" name="txtPass" required /> <input type="hidden" name="cache" id=" cache " value="1" /> <input type="submit" name="cmd" id="cmd" value=" envoie " /> </form> <?php } ?> </body> </html>
Tableau associatif
Création d’un tableau associatif à deux dimensions et affichage
$produits = [ 'bulbes' => ['poids' => 200, 'quantite' => 9, 'prix' => 15], 'rosiers' => ['poids' => 10, 'quantite' => 20, 'prix' => 2], 'massifs' => ['poids' => 10, 'quantite' => 30, 'prix' => 6] ]; echo $produits['bulbes']['quantite']; echo '<br> <br>'; foreach ($produits as &$value) { // echo $value['quantite'].' '; foreach ($value as &$ssvalue) { echo $ssvalue;echo '<br>'; } }
Liste déroulante dynamique
$mesCLients est un tableau d’objet Client contenant l’email et d’autres variables
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>mon titre</title> </head> <body> <?php $mesClients =["Lina","Winie","John","Harry"]; print("<select name=’maListe’ size=’1’>"); foreach($mesClients as client){ print("<option>".$client." </option>"); } print("</select >"); ?> </body> </html>
Lecture écriture de fichier
écriture
file_put_contents('exemple.json', json_encode($produits));
réécriture
file_put_contents('exemple.json', 'waza',FILE_APPEND);
lecture
$mesproduits = file_get_contents('exemple.json');
Exemple d’écriture d’un tableau en fichier json et récupération en php
<?php $produits = [ 'bulbes' => ['poids' => 200, 'quantite' => 9, 'prix' => 15], 'rosiers' => ['poids' => 10, 'quantite' => 20, 'prix' => 2], 'massifs' => ['poids' => 10, 'quantite' => 30, 'prix' => 6] ]; echo $produits['bulbes']['quantite']; foreach ($produits as &$value) { // echo $value['quantite'].' '; foreach ($value as &$ssvalue) { echo $ssvalue;echo '<br>'; } } file_put_contents('exemple.json', 'Ecriture dans un fichier'); file_put_contents('exemple.json', 'Ecriture dans un fichier2',FILE_APPEND); var_dump(json_encode($produits)); var_dump($produits); file_put_contents('exemple.json', json_encode($produits)); file_put_contents('exemple.json', 'waza',FILE_APPEND); $mesproduits = file_get_contents('exemple.json'); var_dump($mesproduits); $b=json_decode($mesproduits, true); var_dump($b); //file_put_contents('exemple.json',"\n waza",FILE_APPEND); $json_errors = array( JSON_ERROR_NONE => 'No error has occurred', JSON_ERROR_DEPTH => 'The maximum stack depth has been exceeded', JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded', JSON_ERROR_SYNTAX => 'Syntax error', ); echo 'Last error : ', $json_errors[json_last_error()], PHP_EOL, PHP_EOL; ?>
Connexion aux bases de données
L’API PDO
L’API PDO est une interface de programmation d’application (Application Programming Interface). Elle regroupe les classes qui vont permettre de réaliser des fonctions aux SGBDR via PHP.,L’API PDO requiert PHP 5.1 au minimum. Attention, les anciens accès aux bases MySQL sont dépréciés (mysql_query par exemple). On ne peut donc plus les utiliser. Ils sont considérés comme non sécurisés et génère une alerte.,Toutefois, il n’est pas obligatoire d’utiliser PDO. D’autres API existent.
Si vous ne souhaitez pas d’une application portable sur plusieurs SGBDR et profiter au maximum des fonctionnalités qu’offre par exemple MySQL dans ses dernières versions, il faut utiliser l’API Mysqli. MySQLi pour Mysql improved permet d’avoir plus de fonctionnalités que PDO pour MySQL. Par contre, une grande partie du code sera à modifier si vous changez de SGBDR. Cette extension n’est utile qu’à partie de la version 4.3.1 de MySQL.
Création d’une connexion MySQL
Les paramètres du constructeur sont des chaines de caractères. Seul le premier est obligatoire.
On instancie l’objet PDO avec au minimum le Data Source Name ou DSN. Le DSN contient les informations pour se connecter à la BD du SGBDR quel que soit l’utilisateur. Le login et le mot de passe sont des paramètres optionnels.
Attention la syntaxe du Data Source Name est dépendante de chaque base de données. D’après le site de php.net :
Le try{}catch{} permet de capturer les exceptions déclenchées par la création de l’objet en cas d’erreurs.
<?php $dsn='mysql:dbname=testdb;host=127.0.0.1'; $user='dbuser'; $password='dbpass'; try{ $dbh=new PDO($dsn,$user,$password,array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING)); }catch(PDOException $e){ echo'Connexion échouée:'.$e->getMessage(); }
PostgreSQL et port
<?php $dsn = "pgsql:host=192.168.1.14;port=5432;dbname=maBase"; try { $dbh = new PDO($dsn, »root », » »); } catch (PDOException $e) { echo 'Connexion échouée : ' . $e->getMessage(); }
Exécution de requêtes
Après avoir réalisée une connexion, il est possible d’effectuer des requêtes. Deux manières s’offre à nous.
Exec
<?php $sql="DELETEFROMclientWHEREnom='Dupond'"; $count=$dbh->exec($sql); print("Effacementde$countlignes.\n");
La fonction d’instance exec renvoie le nombre de lignes affectées par la requête. Cette fonction peut aussi générer des erreurs (généralement une erreur dans la requête SQL). Il est possible de les afficher grâce à l’instruction « or die ». On réutilise l’objet PDO dbh créé précédemment.
Query
Le nom des colonnes sera exactement les mêmes que celles de la base de données. Il faut éviter les accents et les espaces qui sont sources d’erreur lors du passage des informations du SGBDR au serveur PHP.
<?php $sql="SELECT nom, prenom FROM client"; $statement=$dbh->query($sql) ordie(print_r($dbh->errorInfo(),true)); foreach ($statement->fetchAll(PDO::FETCH_OBJ) as $ligne) { echo 'Utilisateur : '.$ligne->nom.'<br>'; } $statement->closeCursor();
Query exécute une requête SQL, retourne un jeu de résultats en tant qu’objet PDOStatement. La fonction setFetchMode de l’objet PDOStatement va influer sur l’accès des données.
Il faut imaginer le résultat sous forme de tableau. Ce tableau se nomme un curseur. Quand on exécute la fonction fetch, on place l’accès au curseur à la première ligne.
Nom | Prenom |
Durand | Dinan |
Daria | David |
Lini | Louis |
Pour passer à la deuxième ligne on exécute une nouvelle fois la fonction fetch.
Nom | Prenom |
Durand | Dinan |
Daria | David |
Lini | Louis |
Pour libérer la connexion du serveur PHP au SGBDR, on ferme le curseur (closeCursor). On accède à une case du tableau en étant d’abord sur la bonne ligne puis en accédant à la colonne correspondante.
Les requêtes préparées
Les requêtes préparées permettent d’améliorer les performances et la sécurité. Le pilote sera autorisé à utiliser le cache coté client ou serveur. Ce type de requête protège des injections SQL. Il n’est plus nécessaire d’utiliser des fonctions spécifiques pour s’en prémunir. La requête est préparée avec des variables appelées marqueurs que l’on va insérer dans la requête SQL. On peut ré-exécuter la requête de cette manière profitant pleinement du cache. On préférera cette méthode aux méthodes précédentes surtout pour des variables récupérées par un client.
exec
<?php $sql="DELETE FROM client WHERE nom=:nom"; $statement=$dbh->prepare($sql); $nom ="harry"; $statement->bindParam(":nom", $nom); $b=$statement->execute();
Cette méthode bien que sécurisée, ne renverra que true dans la variable b ou false si elle n’est pas exécutée.
query
<?php $sql = "SELECT nom, prenom FROM client WHERE login=:login AND mdp=:mdp"; $resultats = $dbh->prepare($sql); $login = "login"; $mdp = "mdp"; $resultats->bindParam(":login", $ login); $resultats->bindParam(":mdp", $mdp); $resultats->execute(); foreach ($resultats->fetchAll(PDO::FETCH_OBJ) as $ligne) { echo 'Utilisateur : ' . $ligne->nom . '<br>'; }
PHP Objet
Les objets en PHP fonctionnent par référence. Si on enregistre un objet dans une variable, ce sera une référence vers cet objet qui sera enregistré.
La classe
<?php class Client { private $nom; public function getNom() { return $this->nom; } }
Utilisation d’un objet
$monClient = new Client();
On accède à une variable d’un objet de la manière suivante
$monClient->nom ;
L’objet this fonctionne dans une méthode d’instance comme en Java
$this->nom ;
Les visibilités
Les visibilités s’appliquent sur les variables et les fonctions. Elles sont identiques à Java : public, protected, ou private. On respectera les principes de l’encapsulation.
Comparaison d’objets
On utilise deux manières pour comparer les objets.
Le == permet de comparer les valeurs de l’objet. Ils doivent être de la même classe et posséder les mêmes variables de valeurs identiques.
Le === vérifie la référence de l’objet. L’objet doit donc ici être le même alors qu’avec l’autre méthode, l’objet doit être égal.
Les constantes
Ceci est différent de Java, on n’utilise pas le mot clef final
class A { const ZOZO= 'valeur constante'; } printA::ZOZO;
Par contre le mot clef final est utilisé de la même manière pour les classes et les méthodes. Une méthode final ne pourra être surchargée et une classe final ne pourra être héritée.
final public function waza() { echo "c'est la fin !"; }
Le mot clef static
<?php class A { public static $maVarStatic = ‘titi‘; public static function maFonction() { echo "ma fonction"; } } printA::$maVarStatic; printA::maFonction();
Parcours de collection
<?php foreach ($collection as $key => $value) { print $key => $value; } foreach ($collection as $value) { print $value; }
Le constructeur
<?php class Client { function __construct() { print"constructeur de la classe mere"; } }
On note _ _ avant construct pour réaliser un constructeur.
Les méthodes ayant le même nom que la classe dans laquelle elle se trouve ne sont plus traitées comme des constructeurs.
Client() sera considérée comme une fonction et non comme un constructeur.
function Client() { print "simple fonction"; }
Constructeur avec paramètres
class Client{ function __construct($param1, $param2) { print "constructeur avec 2 paramètres"; } }
L’héritage
Comme en Java, Il n’est pas possible d’hériter de plusieurs classes. La notation des variables et méthides static est soulignée.
class Fille extends Mere{ }
Le mot réservé self désigne la classe elle-même (this). Le mot parent désigne la classe mère (super).
<?php class Mere { public static $maVarStatic = "titi"; public $var; const CONST_VALUE = "Unevaleurconstante"; public static function Value(){ return self::$maVarStatic; } public static function maFonction(){} public function maDeuxiemeFonction(){} } /*****************************************/ class Fille extends Mere { public function renvoieStatic() { parent::maFonction(); parent::$maVarStatic; } public function maDeuxiemeFonction() { parent::maDeuxiemeFonction(); } } /*******************************************/ printMaFille::$maVarStatic;b //accès à la variable static $mam= new Mere(); $mam->var; $fille = new Fille(); print $fille->renvoieStatic();
Constructeur
Parent remplace ici super de Java.
class Mere { function __construct() { print "constructeur de la classe mere"; } } class Fille extends Mere { function __construct() { parent::__construct(); print "constructeur de la classe fille"; } }
Les classes et méthodes abstraites
Même comportement qu’en Java. Il est nécessaire d’implémenter les méthodes abstraites. La notation des classes abstraite est en italique.
abstract class Personne { // Force les classes filles à définir cette méthode abstract protected function getValue(); abstract protected function setValue($a); } class Client extends Personne { protected function getValue() { return "ConcreteClass1"; } public function setValue($a) { return $a; } }
Les interfaces
Toutes les méthodes des interfaces doivent être implémentées dans la classe.
interface iTemplate { public function setVariable($name, $var); public function getHtml($template); } class Template implements iTemplate { private $vars = array(); public function setVariable($name, $var) { $this->vars[$name] = $var; } public function getHtml($template) { foreach($this->vars as $name => $value) { $template = str_replace('{' . $name . '}', $value, $template); } return $template; } } // Ceci ne fonctionnera pas class BadTemplate implements iTemplate { private $vars = array(); public function setVariable($name, $var) { $this->vars[$name] = $var; } }
Data Access Object Pattern
Un mapping objet et base relationnel permet de créer l’illusion d’une correspondance entre la base de données et les objets du langage de programmation. On fait donc correspondre les attributs des objets avec les attributs de la base de données. On parle d’ORM (object-relational mapping). L’exemple qui suit est un DAO réalisé soi-meme. Il existe des ORM à installer comme Doctrine ou Eloquent.
Le pattern DAO consiste à ajouter un ensemble d’objets dont le rôle sera d’aller lire, écrire, modifier, supprimer. Cet ensemble d’objet s’appelle la couche DAO. Ce pattern utilise des classes génériques. On part de nos classes et on réalise des classes qui vont faire la liaison avec la base de données. Ces classes vont porter le nom du pattern : XxxDAO. Ces classes héritent d’une classe DAO qui définit la généricité.
En PHP 7.4, les classes génériques ne sont pas encore implémentées. On utilise une interface à la place.
L’interface qui oblige nos classes DAO à implémenter ces fonctions
interface ManagerInterface { function setConnection() ; function select(int $id); function insert( $obj): bool; function update( $obj): bool; function delete( $obj): bool; function findAll(): array; }
La classe Personne
class Personne { private int $id; private string $nom; public function getId():int { return $this->id; } public function setId(int $id) { $this->id = $id; } public function getNom():string { return $this->nom; } public function setNom(string $nom) { $this->nom = $nom; } public function __toString(){ return $this->id." ".$this->nom; } }
La classe PersonneDAO
<?php class PersonneDao implements ManagerInterface { private PDO $connection; public function setConnection() { $dsn='mysql:dbname=testdb;host=127.0.0.1'; $user='root'; $password=''; try{ $dbh=new PDO($dsn,$user,$password); $this->connection=$dbh; }catch(PDOException $e){ echo'Connexion échouée:'.$e->getMessage(); } } public function insert( $obj):bool { $result=false; try { /*$sql="SELECT max(id)+1 as id FROM personne"; $statement=$this->connection->query($sql,PDO::FETCH_ASSOC) ; $row = $statement -> fetch(); $id=$row['id'];*/ $id=$obj->getId(); $nom=$obj->getNom(); $sql="INSERT INTO personne (id, nom) VALUES ( '$id' , '$nom')"; echo $sql; $nbLignes=$this->connection->exec($sql) ; if($nbLignes==1) $result=true; } catch (PDOException $e) { echo'insert échoué:'.$e->getMessage(); } return $result; } public function select(int $id):Personne { $p = new Personne(); try { $sql="SELECT * FROM personne where id = '$id'"; $statement=$this->connection->query($sql,PDO::FETCH_ASSOC) ; $row = $statement -> fetch(); $p->setNom($row['nom']); $p->setId($row['id']); } catch (PDOException $e) { echo'select échoué:'.$e->getMessage(); } return $p; } public function update( $obj):bool { $result=false; try { $id=$obj->getId(); $nom=$obj->getNom(); $sql="UPDATE personne SET nom = '$nom' WHERE id = '$id'"; echo $sql; $nbLignes=$this->connection->exec($sql) ; if($nbLignes==1) $result=true; } catch (PDOException $e) { echo'update échoué:'.$e->getMessage(); } return $result; } public function delete( $obj):bool { $result=false; try { $id=$obj->getId(); $sql="DELETE FROM personne WHERE id = '$id'"; echo $sql; $nbLignes=$this->connection->exec($sql) ; if($nbLignes==1) $result=true; } catch (PDOException $e) { echo'delete échoué:'.$e->getMessage(); } return $result; } //ici le tableau ne contient pas des objets de type Personne public function findAll():array { $personnes = null; try { $sql="SELECT * FROM personne"; $statement=$this->connection->query($sql); $personnes = $statement->fetchAll(PDO::FETCH_OBJ); } catch (PDOException $e) { echo'select all échoué:'.$e->getMessage(); } return $personnes; } } echo "debut du programme"; $a=new Personne(); $a->setNom("harry"); $a->setId(32); var_dump($a); $b=new Personne(); $b->setNom("harold"); $b->setId(31); $persodao=new PersonneDao(); $persodao->setConnection(); $persodao->insert($a); $persodao->insert($b); $a->setNom("jo"); $persodao->update($a); $unePersonne=$persodao->select(32); echo "<br><br>".$unePersonne."<br><br>"; $tb=$persodao->findAll(); var_dump($tb); foreach ($tb as $row ) { echo $row->nom."<br><br>"; } $tb[] = $b; var_dump($tb); $persodao->delete($a); /*CREATE TABLE IF NOT EXISTS `personne` ( `id` int(11) NOT NULL, `nom` varchar(30) NOT NULL, PRIMARY KEY (`id`) )*/ ?>