HervéRenault.fr

PHPJavaScript

Mon aide-mémoire PHP-JavaScript

Cet document m'aide à passer d'un langage à l'autre. C'est mon pense-bête, mon antisèche quand je programme. Je pourrais le garder pour moi, mais je le mets en ligne pour pouvoir le retrouver à tout moment, où que je sois. Tant mieux s'il peut vous être utile, mais j'en doute. Le publier me motive aussi pour le maintenir en bon état et ne pas y écrire trop de bêtises. Une sorte de gymnastique intellectuelle. Et puis s'il n'était plus à jour, il ne me servirait plus.

J'avais fait une version PHP-Perl-Python-JavaScript-Java il y a quelques années, parce que j'ai commencé à travailler avec Perl et JavaScript, puis rapidement PHP, puis j'ai voulu apprendre Python parce qu'on m'en disait du bien mais je n'ai jamais travaillé avec, puis j'ai appris Java pour faire des applis Android que j'ai fini par abandonner, et enfin il ne reste plus que PHP et JavaScript. Plutôt que mettre à la poubelle cet énorme document que j'appelais mon "aide-mémoire multilingue", je le conserve pour le fun.

Ce document a une longue histoire et conserve encore des traces de PHP 5 et des remarques sur Internet Explorer. Quand je peux, j'y ajoute des éléments de PHP 7 ou 8 (à l'heure où j'écris) et de JS ES6, etc.

Dernière remarque, sur la présentation : c'est très compact, pour me permettre de retrouver rapidement ce que je cherche. Ce n'est donc pas un document didactique.

  PHP Javascript
doc php.net
MDN
essais
php -a
F12 ou Shift-Ctl-K dans Firefox 11+
ou node en ligne de commande
valider la syntaxe
php -l script.php
ESLint
une variable $a = 123;
TODO define, const...
a = 123;
var a = 123;
let a = 123;
const a = 123;
incrémenter $a++; ++$a;
a++; ++a;
diviser $a /= 2;        # 62.5
a /= 2;        // 62.5

modulo
$a = 5 % 2;
a = 5 % 2;
typage
$a = 1;
$a += "b"; # OK
a = 1;
a += "b"; // OK
if ...
if ($a == 1) {
   echo "un";
} elseif ($a == 2) {
   echo "deux";
} else {
   echo "je ne sais pas";
}
if (a == 1) {
    alert("un");
} else if (a == 2) {
    alert("deux");
} else {
    alert("je ne sais pas");
}
switch
switch($a) {
    case 1:
        echo "un";
        break;
    case 2:
        echo "deux";
        break;
    default:
        echo "je ne sais pas";
}
switch(a) {
    case 1:
        alert("un");
        break;
    case 2:
        alert("deux");
        break;
    default:
        alert("je ne sais pas");
}
if ($a == 2) {
    echo  "deux";
} elseif ($a == 'deux') {
    echo "deux en toutes lettres";
} else {
    echo "... je ne sais pas";
}
if (a == 2) {
    alert("deux");
} else if (a == "deux") {
    alert("deux en toutes lettres");
} else {
    alert("je n'sais pas");
}
particularité
PHP et JS
if ($a === "2") {
    echo "égaux et du même type";
} elseif ($a == "2") {
    echo "égaux (avec conversion)";
} else {
    echo "pas égaux";
}

# l'inverse de === est !==
if (a === "2") {
    alert("égaux et du même type");
} else if (a == "2") {
    alert("égaux (avec conversion)");
} else {
    alert("pas égaux");
}

// l'inverse de === est !==
variable non
initialisée
if (!isset($b)) {
    echo '$b non initialisée !';
    echo $b; // PHP Notice:  Undefined variable
}
if (typeof b == 'undefined') {
    alert("b non initialisée");
    alert(b); // ReferenceError: b is not defined
}
commenter
// une ligne
# une ligne
/*
plusieurs lignes
 */
// une ligne
/*
plusieurs lignes
 */
afficher sans passer à
la ligne
echo abs(-4);
document.write(Math.abs(-4));
en passant à la ligne
echo abs(-4)."\n";
document.writeln(Math.abs(-4));
// ou write(4 + "\n");
contenu sur plusieurs lignes ("heredoc" ou "here-doc") $a = <<<EOT
ligne 1
ligne 2
EOT;

echo $a;
// template literals ES6, cf MDN

a = `ligne 1
ligne 2`;

console.log(a);

// pour détecter si c'est utilisable (= pas IE)
function supportsLiterals() {
  try {
    return eval("''===``")
  }
  catch(e) {
    return false;
  }
}
écrire sur la sortie d'erreur fwrite(STDERR, "oups\n"); console.error("oups");
booléens
$a = TRUE; # true, True, TrUe ...
a = true;
opérateurs logiques
if (1 && 1) {
    echo "vrai\n";
}
if (1 and 1) {
    echo "idem\n";
}

if (1 || 0) {
    echo "vrai aussi\n";
}
if (1 or 0) {
    echo "idem\n";
}
if (true && true) {
    alert("vrai");
}
if (true || false) {
    alert("vrai aussi");
}
chaîne de
caractères
$a = "test";
$a = 'test';
a = "test";
a = 'test';

echo $a[2];  // ou $a{2}
alert(a.charAt(2));
concaténation
$a .= "foo";
a += "foo";

echo strlen($a);
// pour Unicode :
echo mb_strlen($a);
// ou encore :
echo grapheme_strlen($a)
alert(a.length);
code caractères
for ($i = 0; $i < strlen($a); $i++) {
    echo ord($a[$i])."\n";
}
for (i in a) {
    alert(a.charCodeAt(i));
}
normaliser les accents du Mac de 3 octets en 2 octets echo normalizer_normalize('é', Normalizer::FORM_C );
"stf"
echo substr($a,2,3);

// pour UTF-8 :
mb_substr('hé !',1,1,'UTF-8');
alert(a.substring(2,5)); // start, stop
// ou
alert(a.substr(2,3)); // start, length
// voir aussi slice()
"tfoo"
echo substr($a,3); alert(a.substring(3));
// ou
alert(a.substr(3));
"testf"
echo substr($a,0,-2); alert(a.substring(0,a.length - 2));

echo strtoupper($a);

// pour de l'UTF-8 :
echo mb_strtolower('HÉ !', 'UTF-8');
alert(a.toUpperCase());
"Testfoo"
echo ucfirst($a);
alert(a.charAt(0).toUpperCase()+a.substr(1));

echo ucwords("jorge luis borges");

// pour UTF-8 :
echo mb_convert_case('évariste galois', MB_CASE_TITLE, 'UTF-8');

chaîne de caractères sur plusieurs lignes echo "voici une ".
     "très longue ".
     "phrase";
alert("voici une "
+ "très longue "
+ "phrase");

if (strpos("hervérenault.fr", "a") > -1) {
    echo "a y est\n";
}
if ("hervérenault.fr".indexOf("a") > -1) {
    alert("a y est");
}
// note : IE8 n'a pas indexOf
// utiliser jQuery.inArray()

if (strpos("hervérenault.fr", "foo") === false) {
    echo "pas foo\n";
}
if ("hervérenault.fr".indexOf("foo") == -1) {
    alert("pas foo");
}
supprimer le retour à la ligne en fin de chaîne
$a = "bonjour\n";
$a = rtrim($a, "\n");
print "$a !\n";
// à partir d'IE10 ?
if (String.prototype.trim) {
    alert("bonjour\n".trim() + " !");
}

// sinon, aveec une regexp :
a = "bonjour\n".replace(/\n/, "");
alert(a + " !");

// ou jQuery.trim()
supprimer les blancs avant et après
$a = "  bonjour \t ";
echo "[".trim($a)."]";
idem précédent
formatage
printf("%s a %d ans\n", "Jean", 60); // avec ES6 : utiliser les template literals
let a = ['Jean', 60];
alert(`${a[0]} a ${a[1]} ans\n`);

// note : les template literals permettent
// d'autres choses très intéressantes

$s = sprintf("%s a %d ans\n", "Jean", 60); // avec ES6 : utiliser les templates literals
let a = ['Jean', 60];
s = `${a[0]} a ${a[1]} ans\n`;
regular expressions
(regexps)
$botte_de_foin = "Jean a 60 ans";
$aiguille = "j[ue]an";
if (preg_match("/$aiguille/i", $botte_de_foin)) {
    echo "trouvé en ignorant la casse !\n";
}
botte_de_foin = 'Jean a 60 ans';
aiguille = /j[ue]an/i;

// on peut écrire aussi :
aiguille = new RegExp('j[ue]an', 'i');

// on peut même passer une chaîne qui est convertie
// implicitement en objet RegExp (mais sans i)

if (botte_de_foin.match(aiguille)) {
    alert("trouvé en ignorant la casse !");
}
extraire des groupes d'une regexp
$a = "Jean a 60 ans";
if (preg_match("/([A-Z].*?) /", $a, $m)) {
    echo $m[1];
}
a = "Jean a 60 ans";
m = a.match("([A-Z].*?) ");
if (m) {
    alert(m[1]);
}
extraire toutes les occurences d'une regexp
$a = "Jean est plus vieux que Jérome et Jacques";
preg_match_all("/J\w+/u", $a, $m);
print_r($m);

# Note: /u pour que \w matche é
a = "Jean est plus vieux que Jérome et Jacques";
re = RegExp('([A-Z].*?) ', 'g');
while ((matches = re.exec(a)) !== null) {
    alert(matches[0]);
}

// ou en ES2020, si on peut ignorer IE, matchAll
substitutions
$a = preg_replace('/^\w+/', "Antoine", $a);
echo $a;
a = a.replace(/^\w+/, "Antoine");
alert(a);
avec backreference (référence arrière) echo preg_replace("/^(\w+)/", "Mon voisin $1", $a); alert(
a.replace(/^(\w+)/, "Mon voisin $1")
);
nombre de "a" substitués par "?" (2)
preg_replace('/a/', "?", $a, -1, $count);
echo $count;
// en deux étapes
m = a.match(/a/g);
a = a.replace(/a/g, "?");
alert(m.length);

idem en ignorant la casse (3)
preg_replace('/a/i', "?", $a, -1, $count);
echo $count;
m = a.match(/a/ig);
a = a.replace(/a/ig, "?");
alert(m.length);
matcher tout y compris un passage à la ligne (\n)
$a="Voici une ligne
et puis deux et voilà";
$a = preg_replace('/une.*?deux/s', "", $a);
echo $a;
a="Voici une ligne\net puis deux et voilà";
a = a.replace(/une[\s\S]*?deux/, "");
alert(a);
particularité PHP
// pour matcher de l'UTF-8
$a = "HÉ !";
echo preg_replace('/é/iu', 'a', $a);

chaîne contenant un nombre ?
$a = "123.45";
if (is_numeric($a)) {
    echo "ça ressemble à un nombre";
}
var a = '123.45';
if (!isNaN(a)) {
    alert('ça ressemble à un nombre');
}
variable contenant un entier ?
$a = 123;
if (is_int($a)) {
    echo "c'est un entier";
}
TODO
un décimal ?
$a = 123.45;
if (is_float($a)) {
    echo "c'est un décimal";
}
TODO
boucle
for ($x = 2; $x < 6; $x++) {
    echo "$x\n";
}

// ou

foreach (range(2, 5) as $x) {
    echo "$x\n";
}
for (var x = 2; x < 6; x++) {
    alert(x);
}

echo str_repeat(".", 3);

saute 3
arrête à 10
$a=0;
while(true) {
    $a++;
    if ($a == 3) continue;
    if ($a > 10) break;
    echo "$a\n";
}

liste hétérogène
$a = array(1, 2, 'foo', 'bar');

// à partir de PHP 5.4 :
// $a = [1, 2, 'foo', 'bar'];
a = [1, 2, 'foo', 'bar'];
// ou
a = new Array(1, 2, 'foo', 'bar');
// ou
a = Array(1, 2, 'foo', 'bar');
liste homogène
$a = array(1, 2, 3, 4);
a = [1, 2, 3, 4];
// ou avec Array()

echo $a[2];
alert(a[2]);

$a[] = 5;
// ou
array_push($a, 5);
a.push(5);

if (in_array(3, $a)) {
    echo "3 y est\n";
}
if (a.indexOf(3) > -1) {
    alert("3 y est");
}
// note : IE8 n'a pas indexOf
// utiliser jQuery.inArray()

foreach ($a as $b) {
    echo $b;
}
// pas tout à fait pareil
for (b in a) {
    alert(a[b]);
}

// seulement à partir de IE9 :
a.forEach(function(b) {
    alert(b);
});
liste d'affectations
list($b, $c, $d) = $a;    # le 4 est ignoré

# swap :
list($b, $c) = array($c, $b);
[b, c, d] = a;

// KO dans IE
type
if (is_array($a)) {
    echo "array";
}
if (a instanceof Array) {
    alert("Array");
}
join
$b = join(", ", $a);

// ou

$b = implode(", ", $a);
b = a.join(", ");
split
$a = explode(", ", $b); // pas de regexp !

// ou
$a = preg_split('/, /', $b);
// mais pas split : obsolète depuis 5.3
a = b.split(", ");

// ou
a = b.split(/, /);
variante
list($c, $d, $reste) = split(", ", $b, 3);


echo $a;
# affiche Array
alert(a);

print_r($a);
# ou plus précis :
var_dump($a);
console.log(a);

// ou plus basique :
for (b in a) {
    alert(b + ' => ' + a[b]);
}

echo $a[1];
alert(a[1]);

echo count($a);
alert(a.length);

echo $a[count($a) -1];
# ou
echo end($a);
alert(a[a.length -1]);

$b = array(1,1,1,2,3,3,4);
$b = array_unique($b);
print_r($b);

# affiche :
Array
(
    [0] => 1
    [3] => 2
    [4] => 3
    [6] => 4
)
# attention, $b[1] n'existe plus !

liste non modifiable
# sans équivalent ?
copier une liste $b = $a; /* JS copie par référence par défaut. Dans le jargon JS, c'est une "copie superficielle" (shallow copy) et pour faire une copie des valeurs comme en PHP, il faut une "copie profonde" (deep copy) comme ceci : */

b = JSON.parse(JSON.stringify(a));
listes dynamiques
imbriquées
$a = array(1,2,3,array(4,5),6,7);
a=[1,2,3,[4,5],6,7];
hash (table de hachage, "dictionnaire" en Python, "associative array" en PHP)
$a = array("foo" => 3, "bar" => 4, "baz" => NULL);
a = { "foo" : 3, "bar" : 4, "baz" : null };

// a est un objet
// "foo" est une propriété
// a n'est pas ordonné

echo $a["foo"]; alert(a["foo"]);
// ou
alert(a.foo);
taille d'un objet
echo count($a);
# ou
echo sizeof($a);
// à partir d'IE9 :
alert(Object.keys(a).length);

// sinon :
size = 0;
for (k in a) {
    size++;
}
alert(size);

// ou :
Object.size = function(o) {
    var size = 0;
    for (k in o) {
        size++;
    }
    return size;
}
alert(Object.size(a));

// mais pas ça, qui ajoute "size" à toute
// boucle for (... in ...) !
Object.prototype.size = function() {
    var size = 0;
    for (k in this) {
        // pour ne pas compter size !
        if (this.hasOwnProperty(k)) {
            size++;
        }
    }
    return size;
}
alert(a.size());


// ou avec jQuery : .size() et .length

if (! array_key_exists("truc", $a)) {
    echo "clé truc n'existe pas\n";
}
if (a["truc"] === undefined) {
    alert("clé truc n'existe pas");
}
// ou
if (!a.hasOwnProperty("truc"))

if ($a["baz"] == null) {
    echo "pas de valeur associée à baz\n";
}
// si pas de clé, PHP Notice: Undefined index

// attention !
if (!isset($a["baz"])) {
    echo "pas de clé OU de valeur associée !\n";
}
// attention++ !
if (empty($a["baz"])) {
    echo "idem OU valeur 0 ou chaine vide\n";
}
if (a["baz"] === null) {
    alert("pas de valeur associée à baz");
}

// attention !
if (a["baz"] == undefined) {
    alert("pas de clé OU de valeur associée !");
}
// idem :
if (a["baz"] == null) {
    alert("pas de clé OU de valeur associée");
}

foreach ($a as $k => $v) {
    echo "$k => $v\n";
}

// ou

reset($a);
while (list($k, $v) = each($a)) {
    echo "$k => $v\n";
}
for (k in a) {
    alert(k + " => " + a[k]);
}

unset($a["foo"]);
delete a["foo"];
intersection
(2,3)
array_intersect(array(1,2,3), array(2,3,4));

// fonctionne aussi avec des arrays assoc.

différence symétrique
(1,4)
$a = array(1,2,3);
$b = array(2,3,4);
$i = array_intersect($a,$b);
$d = array_merge(array_diff($a,$i), array_diff($b,$i));
TODO
trier une liste
$a = array(4, 2, 3, 10);

sort($a); // tri numérique
a = [4, 2, 3, 10];

a = a.sort(); // tri alphabétique

// tri numérique :
a.sort(function(x,y) { return x - y; });
avec des accents UTF-8
$b = array('a', 'z', 'é', 'b', 'e');

setlocale(LC_COLLATE, 'fr_FR.UTF-8');
sort($b, SORT_LOCALE_STRING);

// ou

$collator = new Collator('fr_FR');
$collator->sort($b);
// voir aussi Collator::asort (mais pas de ksort)
TODO
comparer deux chaines UTF-8
setlocale(LC_COLLATE, 'fr_FR.UTF-8');
echo strcoll('élément', 'zéro');
// pas strcmp !
alert('élément'.localeCompare('zéro'));
max d'une liste
echo max($a);
alert(Math.max.apply(null, a));
retirer un élément en tête
echo array_shift($a); # 1
alert(a.shift());
en fin de liste
echo array_pop($a); # 4 alert(a.pop());
ajouter en tête
array_unshift($a, 5);
a.unshift(5);
ou ailleurs
array_splice($a,2,0,9);
a.splice(2,0,9);
concaténer deux listes ou hashes
$c = array_merge($a, $b);
// $b écrase $a si clés communes
// ou
$c = $a + $b;
// $a écrase $b si clés communes
c = a.concat(b);

# hashes avec jQuery
c = $.extend({}, a, b);
# ou étend a avec b
$.extend(a, b)
modifier une liste
$a = array_map(function($v) { return $v * 2; }, $a);

// ou
array_walk($a, function(&$v) { $v *= 2; }); // 5.3+

// ou avant PHP 5.3 :
function modif(&$v) {
    $v *= 2;
}
array_walk($a, "modif");
// à partir de IE9
a = a.map(function(x) { return x * 2; })

// avec ES6 et les fonctions fléchées
a = a.map(x => x * 2);

// (tester Array.prototype.map)
avec un paramètre supplémentaire
array_walk($a, function(&$v, $k, $p) {
    $v *= $p;
}, 3);

filtrer une liste (garde les éléments pairs) $a = array(1,2,3,4);
$b = array_filter($a, function($e) {
    return $e % 2 == 0;
});
a = [1,2,3,4];
b = a.filter(function(e) {
    return e % 2 == 0;
});
trouver le premier élément supérieur à 2 dans liste foreach ($a as $v) {
    if ($v > 2) {
        echo $v;
        break;
    }
}
a.find(v => v > 2);

// c'est super compact grâce à la fonction flèche
// mais ça peut s'écrire plus verbeusement :
a.find(function(v) {
  return v > 2;
});

MDN Array.prototype.find()
trier un hash par valeur (et non par clé)
$a = array("tom" => 5, "jerry" => 2, "alfonso" => 3);

asort($a);

// ou

array_multisort(array_values($a), $a);
a = { "tom" : 5, "jerry" : 2, "alfonso" : 3 };
// a est un objet, il n'y a pas d'ordre

// mais on peut créer un array d'arrays
// qui est ordonné, lui...
b = [];
for (k in a) {
    b.push([k, a[k]]); // [clé, valeur]
}
b.sort(function(x,y) { return x[1] - y[1]; });

console.log(b);
   

trier un hash par clé
ksort($a);

// voir aussi uksort


$aref = &$a;


# sans équivalent ?


echo $aref[1]; # affiche 2


$a = array('foo', 'bar', 123);
foreach ($a as $i => $v) {
    echo "index $i : valeur $v\n";
}
TODO
fonction avec un nombre d'arguments variable function f() {
    echo "nbe d'args : ".func_num_args()."\n";
    print_r(func_get_args());
}

// à partir de PHP 5.6 :
function f(...$params) {
    echo "nbe d'args : ".count($params)."\n";
    print_r($params);
}

f(4, 3, 2, 1);
function f() {
    console.log("Nbe d'args : " + arguments.length);
    for (var i=0; i < arguments.length; i++) {
        console.log(arguments[i]);
    }
}

f(4, 3, 2, 1);
passer une liste d'arguments à une fonction
("unpacking", déballer les arguments)
function f($a, $b, $c) {
    echo $a + $b + $c;
}

$a = array(5, 6, 7);

// avec PHP 5.6 :
f(...$a);

// avant 5.6, obligé de faire :
f($a[0], $a[1], $a[2]);
function f(a, b, c) {
    console.log(a + b + c);
}

a = [5, 6, 7];

f.apply(null, a);
ne pas respecter le nombre d'arguments passés à une fonction ? f(1, 2, 3, 4); // ça passe

f(1, 2); // PHP Warning: Uncaught ArgumentCountError

// dans une surcharge de fonction :
// PHP Warning: Declaration of B::f($a, $b)
//   should be compatible with A::f($a)
// le nombre d'arguments doit être le même
f(1, 2, 3, 4); // ça passe

f(1, 2); // ça passe… mais ça affiche NaN !
fonction lambda (anonyme)
$f = function($a, $b) { return $a + $b; };
// avant PHP 5.3 :
// $f = create_function('$a,$b', 'return $a + $b;');

echo $f(1, 2);
f = function(a, b) { return a + b; }

alert(f(1,2));
particularité PHP 5.3+
$a = array(0,1,2,3,4,5,6,7,8,9);

foreach (array(2,3,4) as $d) {
    $b = array_filter($a, function($v) use($d) {
        return !($v % $d);
    });
    print_r($b);
}

particularité Javascript
// exécution immédiate d'une fonction anonyme
(function() {
    var a = 'coucou';
    alert(a);
})();

// ou (moins explicite)
!function() {
    var a = 'bonjour';
    alert(a);
}();
// le ! provoque l'évaluation de ce qui suit
modifier une liste dans une fonction (dans cet exemple, remplacer tout le contenu de la liste, pour que ce soit plus parlant)
function change(&$a) {
    $a = array(5, 6);
}

change($a);
print_r($a);


même chose en ajout
function change(&$a) {
    $a[] = 5;
    $a[] = 6; // ou :
    array_push($a, 7);
}

change($a);
print_r($a);


eval('print join("+", $a);');
# ne pas oublier le point-virgule

variable globale
$a = 1;
function b() {
    global $a;
    echo $a;    # OK
    $a = 2;
}
function c() {
    echo $a;    # "Undefined variable"
}

b();    # affiche 1
echo $a;    # affiche 2
a = 1;
// ou var a = 1;
function b() {
    alert(a);
    a = 2;
}

b();    // affiche 1
alert(a);    // affiche 2

// ici, a est en fait window.a

// et si on ne l'avait pas créée par a = 1
// on l'aurait créée globale dans la fonction !
// (dangereux, interdit en mode strict)
variable locale
$a = 1;
function b() {
    $a = 2;
    echo $a;
}
function c($a) {
    echo $a;
}

c(3); # affiche 3
b(); # affiche 2
echo $a; # affiche 1
a = 1;
// ou var a = 1;
function b() {
    var a = 2;
    alert(a);
}
function c(a) {
    alert(a);
}

c(3);    // affiche 3
b();    // affiche 2
alert(a);    // affiche 1
déréférencer une liste en retour d'une fonction (exemple)
$a = "foo-bar";
// à partir de PHP 5.4 :
echo explode('-', $a)[0];

// PHP 5.3
echo current(explode('-', $a)); // foo
a = "foo-bar";
alert(a.split('-')[0]);
constante
define("FOO", 42);
echo FOO;
// ou
echo constant("FOO");

// dans une classe A
const FOO = 42;
echo self::FOO; // dans la classe
echo A::FOO; // ailleurs
# n'existe pas
vérifier si une fonction existe if (function_exists('a')) {
    a();
}
if (this.window['a'] && typeof(this.window['a'] === 'function')) {
    a();
}

// ou, par exemple, pour savoir si la
// fonction indexOf existe pour les tableaux :
if ('indexOf' in Array.prototype) {
    alert("foobar".indexOf("b"));
}
// ou encore :
if (Array.prototype.indexOf) {
    alert("foobar".indexOf("b"));
}
appeler une fonction par son nom
function a($a) {
    echo "ici ".__FUNCTION__."($a)\n";
}

$b = 'a';
call_user_func($b, 'foo');
call_user_func_array($b, array('foo'));
$b('foo');
function a() {
    alert('ici ' + arguments.callee.name);
}

b = 'a';
window[b]();
// car appeler a() revient à appeler window['a']()
type des paramètres (type hinting)
function a(UneClasse $x) // PHP 5

function b(array $x) // PHP 5.1

function c(callable $x) // PHP 5.4
    // et dans ce cas on peut faire :
    $x("foo");


function a() {
    echo "ici ".__FUNCTION__."\n";
    echo "ligne ".__LINE__."\n";
    echo "fichier ".__FILE__."\n";
    echo "répertoire ".__DIR__."\n";
}

# avant PHP 5.3 __DIR__ n'existait pas
# => dirname(__FILE__)
function a() {
    alert('ici ' + arguments.callee.name);
    // ou afficher la déclaration de a :
    alert('ici ' + arguments.callee);
}
nom de la fonction appelante function a() {
    list (,$a) = debug_backtrace();
    echo "appel par ".$a['function'];
    if (isset($a['class']))
        echo " dans ".$a['class'];
}

function b() {
    a();
}

b(); // affiche "appel par b"
function a() {
    alert('appel par ' + arguments.callee.caller.name);
    // ou la déclaration de l'appelant :
    alert('appel par ' + arguments.callee.caller);
}

function b() {
    a();
}

b(); // affiche "appel par b"
debug (débuguer) pas à pas // j'utilise Xdebug + Vdebug mais il en existe d'autres // dans le navigateur : F12 puis onglet Débogueur
// (Maj Ctrl Z ne fonctionne pas chez moi, pas grave)

// dans Node.js : node inspect myscript.js
mysql try {
    $dbh = new PDO('mysql:host=localhost;dbname=test', 'u', 'p');

    $sth = $dbh->query("create table if not ...");

    # ...

    # non ! $a = $dbh->quote($a);
    $sth = $dbh->prepare("select...where a=?");
    $sth->execute(array($a));

    echo $sth->rowCount()."\n";

    while($row = $sth->fetch()) {
        echo $row[0];
    }
    # ou :
    # while($row = $sth->fetch(PDO::FETCH_ASSOC)) {
    #        echo $row["a"];
    # }
    # ou $rows = $sth->fetchAll();
} catch (PDOException $e) {
    echo "Erreur : ".$e->getMessage();
}

objet
class A {
    function __construct($a1, $a2, $a3, $a4) {
        $this->a1 = $a1;
        $this->a2 = $a2;
        $this->a3 = $a3;
        $this->a4 = $a4;
    }

    function somme() {
        return $this->a1
            + $this->a2
            + $this->a3
            + $this->a4;
    }
}

$a = new A(1, 2, "foo", "bar");

echo $a->somme();

// 3
function A(a1,a2,a3,a4) {
    this.a1 = a1;
    this.a2 = a2;
    this.a3 = a3;
    this.a4 = a4;
    // cette méthode serait dupliquée
    // dans chaque instance :
    /* this.somme = function() {
        return this.a1
            + this.a2
            + this.a3
            + this.a4;
    }; */

}

// mieux :
A.prototype.somme = function() {
    return this.a1
        + this.a2
        + this.a3
        + this.a4;
};

a = new A(1,2,"foo","bar");

console.log(a.somme());

// 3foobar

echo $a->a4;
alert(a.a4);
alert(a["a4"]);
chaînage optionnel (optional chaining) // depuis PHP 8.0 il y l'opérateur nullsafe ?->
// mais je ne l'ai jamais utilisé donc cf. PHP 8 Released
console.log(a.foo?.bar);

// comme a n'a pas de propriété foo,
// affiche undefined au lieu de planter
// comme le ferait console.log(a.foo.bar)
// cf. MDN

echo get_class($a);
alert(a.constructor.name);

if (is_a($a, 'A')) {
    echo '$a est un A';
}
// ou
if ($a instanceof A) {
    echo '$a est un A';
}
if (a instanceof A) {
    alert("a est un A");
}

print_r(get_object_vars($a));
// ou
$r = new ReflectionObject($a);
print_r($r->getProperties());

accès à une variable privée
// class A { private $a1; ...

$p = $r->getProperties();
$p[0]->setAccessible(true);
print $p[0]->getValue($a);

accès par le nom de l'attribut
if (property_exists($a, "a1")) {
    $attr = "a1";
    $a->$attr = "blah";
    echo $a->$attr;
}
if (a.hasOwnProperty('a1')) {
    a['a1'] = 'blah';
    alert(a['a1']);
}
// normalement supporté par tout navigateur.
// vérifier que le navigateur a cette méthode :
// if (Object.prototype.hasOwnProperty) { ...
surcharge
class A {
    function __construct($a1, $a2, $a3, $a4) {
        $this->a1 = $a1;
        $this->a2 = $a2;
        $this->a3 = $a3;
        $this->a4 = $a4;
    }

    function __toString() {
        return(join(" + ", array($this->a1, $this->a2, $this->a3, $this->a4)));
    }
}

$a = new A(1, 2, "foo", "bar");

echo $a;
function A(a1,a2,a3,a4) {
    this.a1 = a1;
    this.a2 = a2;
    this.a3 = a3;
    this.a4 = a4;
}

A.prototype.toString = function() {
    return [this.a1, this.a2, this.a3, this.a4].join(" + ");
}

a = new A(1,2,"foo","bar");

alert(a);


héritage
class B extends A {
    function __construct($a1, $a2, $a3, $a4) {
        parent::__construct($a1, $a2, $a3, $a4);
    }

    function bonjour() {
        return("bonjour".$this->a1);
    }
}

$b = new B(1,2,3,4);
echo $b->bonjour();
echo $b; // appelle __toString() de A
function B() {
    A.apply(this, arguments);
}
B.prototype = new A();
B.prototype.constructor = B;

B.prototype.bonjour = function() {
    return "bonjour" + this.a1;
}

b = new B(1,2,3,4);
alert(b.bonjour());
alert(b);
trier une liste d'objets $l = array(
     new A(3,4,'c','d'),
     new A(1,2,'a','b'),
);

// sur le membre a1 numérique :
usort($l, function ($x, $y) {
    return $x->a1 <=> $y->a1;
});

// sur le membre a4 alphanumérique :
usort($l, function ($x, $y) {
    return strcmp($x->a4, $y->a4);
});

// en utilisant une fonction de la classe de cet objet
// par exemple si la fonction s'appelle compare() :
usort($l, array('A', 'compare'));
TODO
idem sur chaîne UTF-8
$l = array(
     new A(3,4,'z','z'),
     new A(1,2,'é','é'),
);

setlocale(LC_COLLATE, 'fr_FR.UTF-8');
usort($l, function($a, $b) {
    return strcoll($a->a3, $b->a3);
});
TODO
accès par le nom de la méthode
if (method_exists($b, "bonjour")) {
    $meth = "bonjour";
    echo $b->$meth();
}
TODO
introspection
$r = new ReflectionClass('B');
foreach ($r->getMethods() as $m) {
    echo $m->getName()."\n";
}
TODO
trait

(réutilise du code horizontal, ici la méthode coucou)

(ou contourne l'asbence d'héritage multiple)
// à partir de PHP 5.4
trait A {
    function coucou() {
        echo "coucou ".$this->z;
    }
}

class B {
    use A;
    private $z = 1;
}

class C {
    use A;
    private $z = 2;
}

$b = new B();
$b->coucou();

$c = new C();
$c->coucou();

idem sans trait, par héritage
// PHP < 5.4
class A {
    protected $a;
    function coucou() {
        echo "coucou ".$this->a;
    }
}

class B extends A {
    function __construct() {
        $this->a = 1;
    }
}

class C extends A {
    function __construct() {
        $this->a = 2;
    }
}

$b = new B();
$b->coucou();

$c = new C();
$c->coucou();

idem sans trait, par une classe utilitaire
class A {
    static function coucou($a) {
        echo "coucou $a";
    }
}

class B {
    function coucou() {
        A::coucou(1);
    }
}

class C {
    function coucou() {
        A::coucou(2);
    }
}

$b = new B();
$b->coucou();

$c = new C();
$c->coucou();

objet anonyme $a = new stdClass;
$a->truc = 'valeur';

// ou par conversion de tableau en objet :
$a = (object) array('truc' => 'valeur');
a = { "truc": "valeur" };
interface
TODO

espaces de noms
# à partir de PHP 5.3

# dans ma_lib.php :
namespace ma\librairie\salutations;
function coucou() {
    echo "coucou !\n";
}

# utilisation :
require 'ma_lib.php';
ma\librairie\salutations\coucou();

alias
require 'ma_lib.php';
use ma\librairie\salutations as a;
a\coucou();

conversion objet en array
$a = new A(1,2,3,4);
$aa = (array) $a;
// ou json_decode(json_encode($a), true);
// inutile : on peut écrire a["a1"] ou a.a1
for (x in a) {
    if (typeof(a[x] != "function") {
        alert(a[x]);
    }
}
et l'inverse
$o = (object) array('foo' => 123, 'bar' => 456);
echo $o->foo;

l'heure courante
echo date("H:i:s");
a = new Date();
alert(a.toLocaleTimeString());
secondes depuis le 01/01/1970 echo time(); a = new Date();

alert(parseInt(a / 1000));

alert(Math.round(a / 1000));
timestamp
horodatage
AAAA-MM-JJ HH:MM:SS
// date locale :
echo date("Y-m-d H:i:s");

// GMT (UTC) sans timezone :
echo gmdate("Y-m-d H:i:s");
a = new Date();

// date locale :
alert(
a.getFullYear() + '-' +
('00' + (a.getMonth()+1)).slice(-2) + '-' +
('00' + a.getDate()).slice(-2) + ' ' +
('00' + a.getHours()).slice(-2) + ':' +
('00' + a.getMinutes()).slice(-2) + ':' +
('00' + a.getSeconds()).slice(-2)
);

// GMT (UTC) sans timezone :
alert(
a.getUTCFullYear() + '-' +
('00' + (a.getUTCMonth()+1)).slice(-2) + '-' +
('00' + a.getUTCDate()).slice(-2) + ' ' +
('00' + a.getUTCHours()).slice(-2) + ':' +
('00' + a.getUTCMinutes()).slice(-2) + ':' +
('00' + a.getUTCSeconds()).slice(-2)
);

// plus simple avec Moment.js
a = moment();
alert(a.format('YYYY-MM-DD HH:mm:ss'));
convertir une date dans une autre zone $utc = new DateTimeZone("UTC");
$paris = new DateTimeZone("Europe/Paris");
$a = new DateTime("2013-08-07 12:34:56", $utc);
$a->setTimezone($paris);
echo $a->format('Y-m-d H:i:s');
// utiliser Moment.js
a = moment.tz("2013-08-07 12:34:56", "UTC");
a.tz("Europe/Paris");
alert(a.format('YYYY-MM-DD HH:mm:ss'));
date locale "lundi 21 juillet 1969"
setlocale(LC_TIME, "fr_FR.UTF-8");
$a = mktime(0,0,0,7,21,1969);
echo strftime("%A %e %B %Y", $a);
// le plus approchant
a = new Date(1969,6,21,0,0,0);
alert(a.toLocaleString());
// ou utiliser une librairie qui émule strftime
retrouver le jour de la semaine echo date('N', $a);
// 1 = lundi (ISO-8601)
alert(a.getDay());
// 1 = lundi
ajouter 14 jours à cette date = lundi 4 août 1969
echo strftime("%A %e %B %Y", strtotime('+14 days', $a));

// notes sur DateTime :
$b = new DateTime(strftime("%F",$a));
$b->add(new DateInterval('P14D'));
echo $b->format('l j F Y'); // KO pas de locale !
// donc obligé de faire :
echo strftime("%A %e %B %Y", $b->getTimestamp());
a.setDate(a.getDate() + 14);
nombre de jours entre deux dates : 24 et 31 octobre 2013 (changement d'heure)
$a = mktime(0,0,0,10,24,2013);
$b = mktime(0,0,0,10,31,2013);
echo round(($a - $b)/86400);
a = new Date(2013,9,24,0,0,0);
b = new Date(2013,9,31,0,0,0);
alert(Math.round((a - b)/86400000));
// attention, milli-secondes !
comparer deux dates
if ($a < $b)
if (a < b)
convertir une chaine de date en timestamp
echo strtotime('2012-12-20'); // ok

echo strtotime('20/12/2012'); // ko, rien !

// avec DateTime :
$a = DateTime::createFromFormat(
    'd/m/Y H:i:s',
    '20/12/2012 00:00:00'
);
echo $a->format('U');

// avec le fuseau horaire de l'Alaska :
$a = DateTime::createFromFormat(
    'd/m/Y H:i:s',
    '20/12/2012 00:00:00',
    new DateTimeZone('America/Anchorage')
);
echo $a->format('U');
alert(Date.parse("Dec 20, 2012"));
// attention, milli-secondes !

// avec le fuseau horaire de l'Alaska :
alert(Date.parse("2012-12-20T00:00:00.000-09:00"));

// avec le datepicker de jQuery :
alert($.datepicker
    .parseDate("dd/mm/yy", "20/12/2012")
    .getTime());

// ou avec Moment.js :
a = moment("20/12/2012", "DD/MM/YYYY");
alert(a.format('X'));
// millisecondes :
alert(a.format('x'));
"découper" une date
print_r(strptime("31/10/2013", "%d/%m/%Y"));

cloner un objet Date

b = new Date(a);
lancer un sous-processus
print shell_exec("whois linux.com");

limiter le temps d'excécution d'une opération, par exemple la connexion à un port caché par un firewall (22 = SSH)
// ne fonctionne qu'en ligne de commande
declare(ticks=1);

function signal_handler($signal) {
    print "timeout atteint\n";
    pcntl_alarm(1);
}

pcntl_signal(SIGALRM, "signal_handler", true);
pcntl_alarm(1);

$f = fsockopen("herverenault.fr", 22, $errno, $errstr, 30);
if ($f) {
    echo "réponse du serveur : "; echo fgets($f, 4096);
} else {
    echo "connexion impossible en moins de 3 s\n";
}

résolution DNS (DNS lookup)
echo gethostbyname("herverenault.fr");

résolution DNS inverse (DNS reverse lookup)
echo gethostbyaddr("92.243.27.61");

récupérer un document par http(s)
$html = file_get_contents('https://market.android.com/details?id=fr.herverenault.directdictaphone');


print urlencode("hé"); alert(encodeURIComponent("hé"));
// pas escape() obsolète !
// encodeURI() pour une URL complète
encoder du texte en entités html
echo htmlentities("hé -> &'", null, "UTF-8");
// encode aussi les accents

// ou
echo mb_convert_encoding("hé -> &'", "HTML-ENTITIES", "UTF-8");
// mais ça n'encode pas &
// n'existe pas en JS pur
// mais avec jQuery :
alert($('<p/>').text("hé -> &'").html());
vérifier qu'une adresse e-mail est valide if (filter_var('toto@exemple.fr',FILTER_VALIDATE_EMAIL)) {
    echo "valide";
}
// utiliser une regex
envoyer un mail "old school"
mail('you@you.com', 'test', 'ok...', 'From: me@me.com');

# ou carrément :

$h = popen("/usr/lib/sendmail -t", 'w');
fwrite($h, "From: me@me.com
To: you@you.com
Subject: test
     
ok...");
pclose($h);

envoyer un mail "moderne" avec

une partie HTML avec un charset UTF-8, encodée en Quoted-Printable

et une partie image encodée en Base64
# avec PEAR, sur Ubuntu :
# sudo apt-get install php-mail php-mail-mime

include "Mail.php";
include "Mail/mime.php";

$mime = new Mail_mime();
$mime->setHTMLBody("<b>hé !</b>");
$mime->addAttachment("image.jpg", "image/jpeg");
$body = $mime->get(array("html_charset" => "UTF-8"));
$body = $mime->get();

$headers = $mime->headers(array(
"From" => "Moi-même <me@me.com>",
"To" => "you@you.com",
"Subject" => "Hé, test php !"));

$mail = Mail::factory("smtp", array("host" => "localhost"));
$mail->send("you@you.com", $headers, $body);


# ou mieux, avec SwiftMailer :
# ============================
# composer require swiftmailer/swiftmailer

require_once 'lib/swift_required.php';

$t = Swift_SmtpTransport::newInstance('localhost', 25);

$mailer = Swift_Mailer::newInstance($t);

$message = Swift_Message::newInstance('Hé, test php !')
  ->setFrom(array('me@me.com' => 'Moi-même'))
  ->setTo('you@you.com')
  ->setBody('<b>hé !</b> en HTML', 'text/html')
  ->addPart('hé ! en texte', 'text/plain')
  ->attach(Swift_Attachment::fromPath('image.jpg'));

$result = $mailer->send($message);

attention à l'accent ! echo base64_encode("Hé ho !");
echo base64_decode("SMOpIGhvICE=");
alert(btoa("Hé ho !"));
alert(atob("SOkgaG8gIQ=="));
dernière erreur print_r(error_get_last()); // utiliser window.onerror
gestion des erreurs (principe général) try {
    foobar(3);
    foobar(0);
    foobar(4);
} catch (Exception $e) {
    echo 'Erreur ',  $e->getMessage(), "\n";
}

// si foobar n'existe pas :
// PHP Fatal error:  Call to undefined function foobar()
// en PHP, une erreur fatale n'est pas une exception

// exemple de foobar :
function foobar($a) {
    if ($a == 0) {
        throw new Exception('division par zéro');
    }
    echo (12 / $a)."\n";
}
// affiche :
4
Erreur division par zéro
try {
    foobar(3);
    foobar(0);
    foobar(4);
} catch (e) {
    alert('Erreur ' + e.message);
}

// si foobar n'existe pas :
// Erreur foobar is not defined

// exemple de foobar :
function foobar(a) {
    if (a == 0) {
        throw Error('division par zéro');
    }
    alert(12 / a);
}
// affiche :
4
Erreur division par zéro
loguer
error_log("ceci, celà");

# ou pour loguer dans un fichier particulier
ini_set('log_errors', 1);
ini_set('error_log', '/error.log');

# ou avec log4php
# http://logging.apache.org/log4php/

include('log4php/Logger.php');

Logger::configure('log4php.xml');
$log = Logger::getLogger("main");
$log->info("ceci, celà");

# + fichier log4php.xml
<configuration xmlns="http://logging.apache.org/log4php/">
    <appender name="fichier" class="LoggerAppenderFile">
        <param name="file" value="test.log" />
        <layout class="LoggerLayoutPattern">
            <param name="conversionPattern" value="%d{Y-m-d H:i:s.u} %-5p [%c] %F:%L - %m%n" />
        </layout>
    </appender>
    <root>
        <level value="INFO" />
        <appender_ref ref="fichier" />
    </root>
</configuration>

particularité PHP # afficher les erreurs d'un script
# directement dans le navigateur
# (en environnement de développement)
ini_set('display_errors', 'on');
# ou
ini_set('display_errors', 1);
# ou modifier la valeur dans php.ini

manipulation de XML avec le DOM
$doc = new DOMDocument();
$doc->load('fichier.xhtml');
foreach ($doc->getElementsByTagName("a") as $e) {
    echo $e->textContent."\n";
    // voir aussi $e->nodeValue
    foreach ($e->attributes as $a) {
        echo $a->name." = ".$a->value."\n";
    }
    if ($e->hasAttribute('onclick')) {
        echo "avant ".$e->C14N()."\n";
        $e->removeAttribute('onclick');
        echo "apres ".$e->C14N()."\n";
    }
}
echo $doc->saveXML();
var anchors = document.getElementsByTagName('a');
for (i = 0; i < anchors.length ; i++) {
    console.log(anchors[i].textContent);
    var attr = anchors[i].attributes;
    for (j = 0; j < attr.length; j++) {
        console.log(attr[j].nodeName + ' = '
          + attr[j].nodeValue);
    }
    if (anchors[i].hasAttribute('onclick')) {
        console.log('avant ' + anchors[i].outerHTML);
        anchors[i].removeAttribute('onclick');
        console.log('après ' + anchors[i].outerHTML);
    }
}

console.log(document.documentElement.outerHTML);
avec XPath
$doc = new DOMDocument();
$doc->load('fichier.xhtml');
$xp = new DOMXPath($doc);
$xp->registerNamespace('x', 'http://www.w3.org/1999/xhtml');
echo $xp->query('//x:title')->item(0)->nodeValue;
foreach ($xp->query('//x:td[@style]') as $e) {
    echo $e->nodeName." ".$e->nodeValue."\n";
}

var iterateur = document.evaluate('//span[@style]',
  document, null,
  XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null);
try {
  var noeud = iterateur.iterateNext();
  while (noeud) {
    console.log(noeud.nodeName + ' '
      + noeud.textContent);
    noeud = iterateur.iterateNext();
  }
}
catch (e) {
  alert("Document modifié pendant l'itération" + e);
}

// exemple adapté compacté de MDN Introduction to using XPath

// pendant que j'y suis :

var octobre = document.evaluate(
  "count(//a[starts-with(., '2021-10')])",
  document, null, XPathResult.ANY_TYPE, null);
console.log(octobre.numberValue);

// voir MDN pour plein d'autres détails
autres versions
$xml = simplexml_load_file('fichier.xhtml');
foreach ($xml->body->table->tbody->tr as $tr) {
    echo "1ere cellule : ".$tr->td[0]."\n";
    foreach ($tr->children() as $e) {
        foreach ($e->attributes() as $a => $b) {
            echo "$a => $b\n";
        }
        if (isset($e['style'])) {
            echo $e->getName()." ".$e['style']."\n";
            unset($e['style']);
        }
    }
}
echo $xml->asXML();
// querySelector prend un sélecteur CSS en paramètre

var titre = document.querySelector('title');
console.log(titre.textContent);

var noeuds = document.querySelectorAll('span[style]');
for (i = 0; i < noeuds.length; i++) {
  console.log(noeuds[i].textContent);
  noeuds[i].removeAttribute('style');
}

// pas possible de chercher dans le contenu comme XPath
// mais querySelectorAll retourne une NodeList et,
// en ES6, possible de convertir en n2 = Array.from(noeuds)
// pour faire n2.filter(el => el.substr(0,7) == '2021-10')
interfaces DOM et SimpleXML sur le même XML
$xml = simplexml_load_file('fichier.xhtml');
echo $xml->head->title; // affiche le titre
$doc = dom_import_simplexml($xml)->ownerDocument;
$doc->getElementsByTagName('title')->item(0)
         ->nodeValue = 'foo';
echo $xml->head->title; // affiche foo

idem en mode "stream" (gros fichier)


manipulation XSLT
$xml = new DOMDocument;
$xml->load('donnees.xml');
$xslt = new DOMDocument;
$xslt->load('transfo.xsl');
$proc = new XSLTProcessor;
$proc->importStyleSheet($xslt);
echo $proc->transformToXML($xml);

manipulation de YAML
$a = yaml_emit(array(
"nom"      => "Renault",
"prénom"   => "Hervé",
"langages" => array(
"PHP", "Perl", "Python", "Java"
)));

$b = yaml_parse($a);

print_r($b);
print $b["nom"];

manipulation de JSON
$a = json_encode(array(
"nom"      => "Renault",
"prénom"   => "Hervé",
"langages" => array(
"PHP", "Perl", "Python", "JavaScript"
)));

$b = (array) json_decode($a);

print_r($b);
print $b["nom"];

manipulation de fichier
$f = fopen('fichier.html', 'w');
fwrite($f, $html);
fclose($f);

// raccourci :
file_put_contents('fichier.html', $html);

// plus moderne :
try {
    $f = new \SplFileObject('fichier.html', 'w');
    $f->fwrite($f, $html);
    unset($f);
} catch (\Exception $e) {
    echo $e->getMessage();
}
// dans Node.js

// synchrone
const fs = require('fs');
try {
    fs.writeFileSync('fichier.html', html);
} catch(e) {
    console.log(e);
}

// asynchrone (avec promesse ES6 mieux que callback)
const fsp = require('fs').promises;
fsp.writeFile('fichier.html', html).then(() => {
    console.log('réussi');
}).catch(e => {
    console.error(e);
});
en ajout (append)
$f = fopen('fichier.html', 'a');
fichier temporaire
tempnam('/chemin', 'préfixe');
// renvoie le nom du fichier créé

lire tout le contenu d'un fichier dans une variable
$txt = file_get_contents("fichier.txt");
renommer un fichier
rename('fichier.html', 'fichier.txt');

$a = 'fichier.txt';
if (file_exists($a)) {
    unlink($a);
}


$f = fopen($a, 'r') or die("impossible de lire le fichier '$a'\n");
# et le motif de l'erreur est dans /var/log/... ou sur stderr

lire le contenu d'un fichier ligne par ligne
$f = fopen($a, 'r');
while (($line = fgets($f)) != null) {
    echo "j'ai lu $line";
}
fclose($f);

fichier gzipé $f = gzopen("fichier.gz", "r");
while (($line = fgets($f)) != null) {
    echo "j'ai lu $line";
}
gzclose($f);

extraire les fichiers d'un zip (unzip) $zip = new ZipArchive;
if ($zip->open('fichier.zip') === true) {
    $zip->extractTo('/un/répertoire/cible/');
    $zip->close();
} else {
    echo 'Erreur';
}
TODO

$a = stat("fichier.txt");
echo "Fichier modifié le : ".
    date("r", $a["mtime"]);

// ou filemtime() dans ce cas


chmod("fichier.txt", 0755);
// renvoie un booléen

on est dans quel répertoire ? echo getcwd(); // dans Node.js
console.log(process.cwd());
lecture de répertoire
foreach (scandir('repertoire') as $a) {
    if (! in_array($a, array('.','..'))) {
        echo "$a\n";
    }
}

// avant PHP 5 :
if ($dh = opendir('repertoire')) {
    while (($a = readdir($dh)) !== false) {
        if (! in_array($a, array('.','..'))) {
            echo "$a\n";
        }
    }
}
restreindre à certains fichiers
foreach (glob("*.txt") as $a) {
    echo "$a\n";
}


echo basename('/foo/bar/fichier.txt');
1er paramètre d'éxecution en ligne de commande echo $_SERVER["argv"][1];
// ou
echo $argv[1];
// dans Node.js
console.log(process.argv[1]);
nombre de paramètres echo $argc; // dans Node.js
console.log(process.argv.length);
environnement système
echo getenv("TERM");
variables pour http://... /test?foo=
bar%20baz
echo $_GET["foo"]; // bar baz
echo $_POST["foo"];
echo $_REQUEST["foo"];
echo $_COOKIE["foo"];
echo $_SERVER['QUERY_STRING']; // foo=bar%20baz
echo $_SERVER['REQUEST_URI']; // /test
echo $_SERVER["HTTP_REFERER"];
// etc...
- (utiliser un plugin jQuery)
-
-
alert(document.cookie); // tous les cookies
alert(document.location.search); // ?foo=bar%20baz
alert(document.URL); // http...baz
alert(document.referrer);
// etc...
"foo bar"
echo urldecode("foo%20bar");
decodeURIComponent("foo%20bar");
opérateur ternaire
echo ($a == "A" ? "oui" : "non");
alert(a == "A" ? "oui" : "non");
// mais attention, priorité de +
alert("donc " + (a == "A" ? "oui" : "non"));
variante : si a est non-vide, affiche-la, sinon affiche "non" echo $a ?: "non";
// attention, piège !
// empty($a) ?: "non" affiche 1
// si $a est vide ou vaut 0
// PHP affiche ce qui est à gauche de ?:
?
variante PHP 7 pour isset($a) ? $a : "non" echo $a ?? "non";

temporisation en secondes
sleep(3);
// pas exactement la même chose
t = setTimeout('alert("fini !")',3000);
temporisation
inférieure à 1 seconde
usleep(500000);
setTimeout('alert("fini !")',500);
hachage MD5
echo md5("ceci est un test");
http://pajhome.org.uk/crypt/md5/
106 (un million)
echo pow(10, 6);

random (0 à 1)
// Fonctions pas sûres pour le chiffrement :
echo rand(0, 1000) / 1000;
// mt_rand() est plus performante :
echo mt_rand(0, 1000) / 1000;

// Fonction sûre pour le chiffrement :
echo random_int(0, 1000) / 1000;
// (depuis PHP 7)
alert(Math.random());
remplir de zéros à gauche str_pad($a, 8, "0", STR_PAD_LEFT); TODO
arrondir
2.5 à 3
echo round(2.5);
alert(Math.round(2.5));
arrondir
2.55 à 2.6
echo round(2.55, 1);
alert(Math.floor((2.55*10)+0.5)/10);
conversion chaîne vers nombre (avec ou sans décimale)
$a = "123.45";

echo $a + 1;
echo floatval($a) + 1; // plus sûr

echo intval($a) + 1;
echo (int)$a + 1; // idem
a = "23.45678";
alert(parseFloat(a) +1 );
alert(parseInt(a) +1 );
séparateur de décimales , au lieu de .
echo floatval(str_replace(",", ".", "123,45")) + 1;
TODO
conversion héxa <-> décimal
echo hexdec('cc');
echo intval('cc', 16);
echo 0xcc;

echo dechex('204');
alert(parseInt('cc', 16));

a = 204;
alert(a.toString(16));

cosinus de 60°
echo cos(60 / 180 * pi());
echo cos(pi() / 3);

désaccentuer
$a = "Éluard";
setlocale(LC_ALL, 'fr_FR.UTF-8');
echo iconv('UTF-8', 'ASCII//TRANSLIT', $a);