PHP moderne¶
Quelques notions un peu plus avancées en PHP qu’il est bon de connaître et d’utiliser à bon escient !
Espaces de nommage en PHP¶
Tout d’abord, quelques notions sur les espaces de nommage en PHP qui ressemblent un peu à ceux du C++ ou aux packages Java avec quelques différences de notation.
Utiliser un espace de nommage en PHP¶
<?php
// on déclare l'usage d'un espace de nommage
use Symfony\Component\HttpFoundation\Request;
$request = Request::create('/controleur.php');
// au lieu de :
$response = new \Symfony\Component\HttpFoundation\Request('/controleur.php');
Créer un espace de nommage en PHP¶
On déclare un Espace de nommage en PHP avec le mot clef namespace. Supposons de plus qu’une méthode d’une classe de cet espace de nommage émette une exception.
<?php
namespace fr\iut45\roza;
class Calcule
{
public function divise(a,b)
{
if ( b ===0) throw new Exception('division par zéro !');
// ...
}
}
A quel espace de nommage appartient Exception ?? Il faut être plus précis et indiquer qu’on fait bien référence à la classe Exception de l’espace de nommage global ou racine :
<?php
namespace fr\iut45\roza;
class Calcule
{
public function divise(a,b)
{
if ( b ===0) throw new \Exception('division par zéro !');
// ...
}
}
Classes, fonctions anonymes et closures en PHP¶
Fonctions anonymes et lambdas en PHP¶
On peut utiliser des fonctions anonymes et des lambdas en PHP !
<?php
// anonymous function = fonction anonyme
$carres = array_map(function($n){ return pow($n,2); }, [1,2,3]);
print_r($carres);
// avec des lambdas à la manière de python ou des "fat arrow" JS
$carres = array_map(fn($n): int => pow($n,2) , [1,2,3,4]);
print_r($carres);
Resultat brut html :¶
Array
(
[0] => 1
[1] => 4
[2] => 9
)
Array
(
[0] => 1
[1] => 4
[2] => 9
[3] => 16
)
Classes anonymes en PHP¶
On peut également utiliser des classes anonymes en PHP, à la manière de Java :
<?php
interface Logger {
public function log(string $msg);
}
class Application {
private $logger;
public function getLogger(): Logger {
return $this->logger;
}
public function setLogger(Logger $logger) {
$this->logger = $logger;
}
}
$app = new Application;
$app->setLogger(new class implements Logger {
public function log(string $msg) {
echo $msg;
}
});
var_dump($app->getLogger());
Resultat brut html :¶
object(Logger@anonymous)#2 (0) {
}
Attacher un état à une closure en PHP¶
On utilise le mot-clef use dans un autre sens ici, pour attacher un état à une closure implémentée dans une fonction anonyme :
<?php
$app = new Micro(); //Phalcon ou new Silex\Application() (Silex)
$app['debug'] = true;
$app->get('/api/contact/{id}',
function($id) use ($app) {
$ami = get_friend_by_id($id);
if (!$ami) $app->abort(404, "Contact inexistant");
else return json_encode($ami,JSON_PRETTY_PRINT);
});
Serveur Web embarqué de PHP¶
On peut le lancer depuis le répertoire de son choix¶
php -S localhost:8000
Pour y accéder depuis d’autres machines¶
php -S 0.0.0.0:8000
Avec une conf personnalisée¶
php -S 0.0.0.0:8000 -c myphp.ini
Avec un routeur principal¶
php -S 0.0.0.0:8000 index.php
Autres fonctionnalités spécifiques à PHP 7 et PHP 8¶
Support Unicode¶
<?php
$special1 = "\u{9998}";
$special2 = "\u{9999}";
echo "$special1 \n";
echo "$special2 \n";
Resultat brut html :¶
馘
香
Contrôle des types de paramètres¶
Ajouter éventuellement la directive declare(strict_types=1) mais pas obligatoire sur php récent …
<?php
declare(strict_types=1); // pas obligatoire (PHP récent)
function essai(int $param){
return $param + 1;
}
echo essai(2);
echo essai("2"); // provoque une erreur TypeError
Resultat brut¶
3PHP Fatal error: Uncaught TypeError: essai(): Argument #1 ($param) must be of type int, string given, called in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/ex-PHP7-PHP8/strictTypes.php on line 10 and defined in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/ex-PHP7-PHP8/strictTypes.php:4
Stack trace:
#0 /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/ex-PHP7-PHP8/strictTypes.php(10): essai('2')
#1 {main}
thrown in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/ex-PHP7-PHP8/strictTypes.php on line 4
Fatal error: Uncaught TypeError: essai(): Argument #1 ($param) must be of type int, string given, called in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/ex-PHP7-PHP8/strictTypes.php on line 10 and defined in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/ex-PHP7-PHP8/strictTypes.php:4
Stack trace:
#0 /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/ex-PHP7-PHP8/strictTypes.php(10): essai('2')
#1 {main}
thrown in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/ex-PHP7-PHP8/strictTypes.php on line 4
Contrôle des types de retour¶
On peut aussi déclarer le type de retour d’une fonction :
<?php
function maintenant0(): DateTime
{
return new DateTime('now');
}
function maintenant(): DateTime
{
return 3;// inavlide
}
function maintenant2(): DateTime
{
return "aujourd'hui"; //invalide
}
function foo(): DateTime
{
return null; // invalide
}
var_dump(maintenant0());//correct
var_dump(maintenant());//TypeError
var_dump(maintenant2());//TypeError
var_dump(foo());//TypeError
Resultat brut :¶
object(DateTime)#1 (3) {
["date"]=>
string(26) "2023-02-08 22:15:22.426524"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
PHP Fatal error: Uncaught TypeError: maintenant(): Return value must be of type DateTime, int returned in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/ex-PHP7-PHP8/returnType.php:10
Stack trace:
#0 /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/ex-PHP7-PHP8/returnType.php(24): maintenant()
#1 {main}
thrown in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/ex-PHP7-PHP8/returnType.php on line 10
Fatal error: Uncaught TypeError: maintenant(): Return value must be of type DateTime, int returned in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/ex-PHP7-PHP8/returnType.php:10
Stack trace:
#0 /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/ex-PHP7-PHP8/returnType.php(24): maintenant()
#1 {main}
thrown in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/ex-PHP7-PHP8/returnType.php on line 10
Tableaux constants¶
<?php
define('POISSONS', [
'sole',
'sardine',
'lotte'
]);
echo POISSONS[1].PHP_EOL; // affiche 'sardine'
Resultat brut :¶
sardine
Types scalaires en PHP¶
Les types scalaires permettent de représenter un nombre d’arguments variables stockés dans un tableau. Ici on a plus précisément un tableau de tableaux d’entiers et on souhaite renvoyer la somme avoir en résultat un tableau contenant les sommes des entiers de chaque tableau.
avec fonction anonyme¶
<?php
/* avec fonction anonyme */
function arraysSum(array ...$arrays): array
{
return array_map(function(array $array): int {
return array_sum($array);
}, $arrays);
}
print_r(arraysSum([1,2,3], [4,5,6], [7,8,9]));
Resultat brut :¶
Array
(
[0] => 6
[1] => 15
[2] => 24
)
avec fonction lambda¶
<?php
/* avec fonction lambda */
function arraysSum(array ...$arrays): array
{
return array_map(fn($array): int => array_sum($array), $arrays);
}
print_r(arraysSum([1,2,3], [4,5,6], [7,8,9]));
Resultat brut :¶
Array
(
[0] => 6
[1] => 15
[2] => 24
)
avec fonction nommée¶
<?php
/* en passant le nom de la fonction à array_map */
function arraysSum(array ...$arrays): array
{
return array_map('array_sum', $arrays);
}
print_r(arraysSum([1,2,3], [4,5,6], [7,8,9]));
Resultat brut :¶
Array
(
[0] => 6
[1] => 15
[2] => 24
)
Union types, opérateur null-safe et interface Stringable¶
En PHP 8 et supérieur on peut utiliser des Union types. Pour l’exemple, on reprend notre petite classe étudiant :
<?php
/** Classe Etudiant en PHP */
class Etudiant{
/** Identification unique d'un etudiant */
protected $etudiant_id;
/** Nom de l'etudiant */
protected $nom;
/** Date de naissance de l'etudiant */
protected $naissance;
public function __construct($id, $nom,$naissance){
$this->etudiant_id = (int)$id; // cast vers integer
$this->nom = (string)$nom; // cast vers string
$this->naissance= (int)$naissance; // cast vers date(timestamp)
}
/**
* Fonction de comparaison simplifiee entre etudiants
* == comparera id, nom et naissance
*/
public function equals(etudiant $etudiant){
return ($this->getId() == $etudiant->getId());
}
public function getId(){
return $this->etudiant_id;
}
public function getNom(){
return $this->nom;
}
public function getNaissance(){
return $this->naissance;
}
public function __toString(){
setlocale(LC_TIME, "fr_FR");
$ne=strftime('%A %d %B %Y',$this->naissance);
return 'etudiant: id=' . $this->getId().', nom='.$this->getNom()." $ne";
}
}
Union de types¶
<?php
// UnionTypes PHP8
function somme(int|float $a, int|float $b ): int|float {
return $a + $b;
}
echo somme(2,3) . ' ' . gettype(somme(2,3)) . PHP_EOL;
echo somme(2.5, 3.5) . ' ' .gettype(somme(2.5,3.5)) . PHP_EOL;
// Déclenche une TypeError
//echo somme('a','b') . PHP_EOL;
require('etudiant.php');
function nom(Etudiant|null $etu){
// ou function nom(?Etudiant $etu)
if (!empty($etu))
return strtoupper($etu->getNom());
else
return 'inconnu';
}
$etu = new Etudiant(234,"Talon",time());
echo nom($etu) . PHP_EOL;
echo nom(NULL) . PHP_EOL;
Resultat brut :¶
5 integer
6 double
TALON
inconnu
Union de types et null safe operator¶
<?php
require('etudiant.php');
function nom(Etudiant|null $etu){
return $etu?->getNom() ;
}
$etu = new Etudiant(234,"Talon",time());
echo nom($etu) . PHP_EOL; // Talon
echo nom(NULL) . PHP_EOL; // aucun affichage
// on peut aussi chainer les appels et faire des choses du type
$pays = $session?->user?->getAddresse()?->pays;
Union de types et interface Stringable¶
En PHP au moins 8, on peut utiliser l’interface Stringable que son réputés implémenter par défaut tous les objets qui offrent une méthode __toString() pour par exemple proposer en paramètre d’une fonction quelque chose qui est soit un string soit Stringable !
<?php
require('etudiant.php');
// on peut passer en argument un string ou quelque chose de Stringable
function maj(string|Stringable $chose)
{
if (gettype($chose) =='string'){
$res = $chose;
}
else {
$res = $chose->__toString();
}
return strtoupper($res);
}
$etu = new Etudiant(1234,"Talon",time());
echo maj($etu) . PHP_EOL;
echo maj('bonjour') . PHP_EOL;
Resultat brut :¶
PHP Deprecated: Function strftime() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/ex-PHP7-PHP8/etudiant.php on line 40
Deprecated: Function strftime() is deprecated in /Users/roza/work/iut/prog/PHP/php-depot/source/exemples/ex-PHP7-PHP8/etudiant.php on line 40
ETUDIANT: ID=1234, NOM=TALON MERCREDI 08 FéVRIER 2023
BONJOUR