Comparatif : de PHP à JavaScript

Ce guide présente une comparaison de la syntaxe entre PHP (5.6 minimum) et JavaScript (ES2020 minimum).

Vous trouverez d’autres guides et une explication plus générale ici.

Déclarations des données

En JavaScript, les variables doivent être déclarées. Depuis l’ES6, utilisez seulement l’instruction let.


<?php
$myData = 'php';

view raw

variable.php

hosted with ❤ by GitHub


let myData = 'js';

view raw

variable.js

hosted with ❤ by GitHub

L’ES6 a introduit les constantes en JavaScript. Des valeurs complexes peuvent être utilisées et donc manipulées.


<?php
const MY_DATA = 'php';
const MY_USER = new User(); // Error

view raw

constant.php

hosted with ❤ by GitHub


const MY_DATA = 'js';
const MY_USER = new User(); // OK
MY_USER.name = 'New name';

view raw

constant.js

hosted with ❤ by GitHub

Types de données simples


<?php
$userMan = true;
$userAge = 81;
$userAverage = 10.5;
$userName = 'Henri Bergson';

view raw

types.php

hosted with ❤ by GitHub


let userMan = true;
let userAge = 81;
let userAverage = 10.5;
let userName = 'Henri Bergson';

view raw

types.js

hosted with ❤ by GitHub

En plus de null, JavaScript contient le type undefined, et NaN (Not a Number). Ce sont des erreurs, ne les utilisez donc pas.

Détails sur les chaînes de caractères

En JavaScript, les sauts de ligne ne sont pas autorisés avec les guillemets simples ou doubles.

L’ES6 a introduit les template literals : de nouveaux guillemets, les backticks, pour l’interpolation des variables et dans lesquels les sauts de ligne sont autorisés (les mêmes qu’on utilise en PHP dans les requêtes MySQL). Soyez vigilants avec la position des accolades et leur rôle : en PHP, elles permettent d’isoler les variables pour éviter les confusions, en JavaScript, elles permettent d’insérer une expression.


<?php
$userFullName = "{$userFirstName} {$userLastName}";

view raw

string.php

hosted with ❤ by GitHub


let userFullName = `${userFirstName} ${userLastName}`;

view raw

string.js

hosted with ❤ by GitHub

C’est aussi pratique pour gérer les guillemets simples et doubles dans une même chaîne.


let HTMLTemplate = `<p class="content">My name's Henri !</p>`;

En JavaScript, privilégiez les backticks plutôt que la concaténation, qui porte à confusion avec les additions et peut conduire à des erreurs.

Listes de données

En JavaScript, les tableaux sont seulement des listes indexées numériquement. Ils sont passés par référence.


<?php
$userBooks = ['Book 1', 'Book 2'];
$userBooks[0];
count($userBooks);
$userBooks[] = 'Book 3';

view raw

array.php

hosted with ❤ by GitHub


let userBooks = [`Book 1`, `Book 2`];
userBooks[0];
userBooks.length;
userBooks.push(`Book 3`);

view raw

array.js

hosted with ❤ by GitHub

L’équivalent des tableaux associatifs en PHP sont appelés des objets en JavaScript.


<?php
$user = [
'firstName' => 'Henri',
'lastName' => 'Bergson'
];
$user['firstName'];

view raw

array.php

hosted with ❤ by GitHub


let user = {
firstName: `Henri`,
lastName: `Bergson`
};
user.firstName;

view raw

object.js

hosted with ❤ by GitHub

Décomposition

L’ES6 permet de déstructurer les tableaux, c’est-à-dire extraire les valeurs dans différentes variables.


<?php
$myList = [1, 2, 3];
/* PHP 5+ */
list($data1, $data2, $data3) = $myList;
/* PHP 7.1+ */
[$data1, $data2, $data3] = $myList;


let myList = [1, 2, 3];
let [data1, data2, data3] = myList;

Lié à cette façon de faire, l’opérateur spread permet de diffuser les valeurs d’un tableau en plusieurs valeurs successives, comme c’est aussi possible depuis PHP 5.6.


<?php
$myOptions = [1, 2];
function test($option1, $option2) {}
test(…$myOptions);
$defaultConfig = ['data1', 'data2'];
$userConfig = ['data3', 'data4'];
$finalConfig = [
$defaultConfig,
$userConfig
];

view raw

spread.php

hosted with ❤ by GitHub


let myOptions = [1, 2];
function test(option1, option2) {}
test(myOptions);
let defaultConfig = ['data1', 'data2'];
let userConfig = ['data3', 'data4'];
let finalConfig = [
defaultConfig,
userConfig
];

view raw

spread.js

hosted with ❤ by GitHub

On peut aussi décomposer des objets de façon similaire, nouveauté qui est également apparue en PHP 7.1.


<?php
$user = [
'firstName' => 'Henri',
'lastName' => 'Bergson'
];
/* PHP 7.1+ */
['firstName' => $myName] = $user; // ou list('firstName' => $myName) = $user;
$myName; // `Henri`


let user = {
firstName: `Henri`,
lastName: `Bergson`
};
let { firstName: myName } = user;
myName; // `Henri`

Souvent, vous voudrez créer une variable portant le même nom que la propriété. Auquel cas vous pouvez raccourcir à :


let user = {
firstName: `Henri`,
lastName: `Bergson`
};
let { firstName } = user;
firstName; // `Henri`

Et si la propriété n’existe pas dans l’objet ? Vous pouvez prévoir une valeur par défaut.


let user = {
firstName: `Henri`,
lastName: `Bergson`
};
let { firstName = `default`, age = 0 } = user;
firstName; // `Henri`
age; // 0

Blocs

En JavaScript, l’espace est obligatoire dans l’instruction else if.


<?php
if ($userAge > 18) {}
elseif ($userAge > 21) {}

view raw

condition.php

hosted with ❤ by GitHub


if (userAge > 18) {}
else if (userAge > 21) {}

view raw

condition.js

hosted with ❤ by GitHub

Comme en PHP, faites attention aux valeurs équivalentes à false.


<?php
$myData = $myData ?: 'default';

view raw

ternary.php

hosted with ❤ by GitHub


let myData = myData ?? 'default';

view raw

pipe.js

hosted with ❤ by GitHub

En JavaScript, l’instruction switch fait des comparaisons strictes.

Depuis l’ES6, grâce à let, la portée des variables se limite au bloc en cours.


<?php
for ($i = 0; $i < 10; $i++) {}
$i; // 10, error prone

view raw

scope.php

hosted with ❤ by GitHub


for (let i = 0; i < 10; i++) {}
i; // undefined

view raw

scope.js

hosted with ❤ by GitHub

Les itérations sont simplifiées depuis l’ES6.


<?php
foreach ($userBooks as $value) {}

view raw

iteration.php

hosted with ❤ by GitHub


for (let value of userBooks) {}

view raw

iteration.js

hosted with ❤ by GitHub

Une autre possibilité pour les itérations complexes (avec les valeurs et les index, seulement pour les tableaux).


<?php
foreach ($userBooks as $key => $value) {}

view raw

iteration.php

hosted with ❤ by GitHub


userBooks.forEach((value, index) => {});

view raw

iteration.js

hosted with ❤ by GitHub

Fonctions

En JavaScript, vous pouvez accéder aux portées parentes directement.


<?php
$myData = 'php';
function myMethod() {
$myData; // null
}

view raw

scope.php

hosted with ❤ by GitHub


let myData = 'js';
function myMethod() {
myData; // 'js'
}

view raw

scope.js

hosted with ❤ by GitHub

En JavaScript, les paramètres sont toujours facultatifs. L’ES6 a introduit la possibilité de préciser des valeurs par défaut.


<?php
function myMethod($required, $optional = 'default') {}
myMethod(); // Error

view raw

params.php

hosted with ❤ by GitHub


function myMethod(optional1, optional2 = 'default') {}
myMethod(); // OK

view raw

params.js

hosted with ❤ by GitHub

Ce problème est réglé en TypeScript :

Vous pouvez aussi avoir un nombre indéfini de paramètres.


<?php
function myArrayPush(…$values) {
foreach ($values as $value) {}
}
myArrayPush(1, 2, 3);

view raw

rest.php

hosted with ❤ by GitHub


function myArrayPush(values) {
for (let value of values) {}
}
myArrayPush(1, 2, 3);

view raw

rest.js

hosted with ❤ by GitHub

Arrow functions

L’ES6 a introduit une syntaxe raccourcie pour les fonctions anonymes, appelée arrow functions. Utilisez-la systématiquement, car elle règle aussi un problème de contexte spécifique à JavaScript.


<?php
array_map(function ($value) {
return $value * 2;
}, $numbersList);

view raw

anonymous.php

hosted with ❤ by GitHub


numbersList.map((value) => value * 2);

view raw

arrow.js

hosted with ❤ by GitHub

Fonctions natives

Toutes les fonctions sont des méthodes en JavaScript, et sont donc appelées depuis un objet.


<?php
mb_strpos($myEmail, '@');
str_replace('@', '[at]', $myEmail);
mb_substr($myEmail, 0, 5);
mb_strlen($myEmail);
(int) '5';
array_key_exists('name', $user);
in_array('Book 1', $userBooks);
time();
var_dump($varToDebug);
json_encode($user);
json_decode('{}');

view raw

functions.php

hosted with ❤ by GitHub


myEmail.indexOf('@');
myEmail.replace('@', '[at]');
myEmail.substr(0, 5);
myEmail.length;
Number.parseInt('5', 10);
'name' in user;
userBooks.includes(`Book 1`);
Date.now();
console.log(varToDebug);
JSON.stringify(user);
try {
JSON.parse('{}');
} catch (error) {}

view raw

functions.js

hosted with ❤ by GitHub

Quand une fonction semble être appelée directement, comme setTimeout(), c’est parce que l’objet global est implicite : window.setTimeout().

Classes

L’ES6 a introduit la syntaxe des classes, pour simplifier la programmation orienté objet en JavaScript. Les propriétés sont déclarées directement dans le constructeur. Les propriétés pré-déclarées apparaîtront dans une prochaine version de JavaScript.


<?php
class User {
public $firstName;
public function __construct($firstName) {
$this->firstName = $firstName;
}
public function sayHello() {}
}
$myUser = new User('Henri');
$myUser->firstName;
$myUser->sayHello();

view raw

class.php

hosted with ❤ by GitHub


class User {
constructor(firstName) {
this.firstName = firstName;
}
sayHello() {}
}
let myUser = new User(`Henri`);
myUser.firstName;
myUser.sayHello();

view raw

class.js

hosted with ❤ by GitHub

Lors d’un héritage en JavaScript, l’appel au constructeur parent est obligatoire dans le constructeur fils.


<?php
class Editor extends User {
public function __construct($firstName) {
parent::__construct($firstName);
}
public function sayHello() {
parent::sayHello();
}
}

view raw

inheritance.php

hosted with ❤ by GitHub


class Editor extends User {
constructor(firstName) {
super(firstName);
}
sayHello() {
super.sayHello();
}
}

view raw

inheritance.js

hosted with ❤ by GitHub

Les getters et setters ont une syntaxe spéciale en JavaScript (mais vous pouvez aussi faire des accesseurs classiques). Ne pré-déclarez pas la propriété, JavaScript le fait automatiquement.


<?php
class User {
private $firstName;
public function getFirstName() {
return $this->firstName;
}
public function setFirstName($newFirstName) {
$this->firstName = $newFirstName;
}
}
$myUser = new User('Henri');
$myUser->getFirstName();
$myUser->setFirstName('New name');

view raw

accessors.php

hosted with ❤ by GitHub


class User {
get firstName() {
return this._firstName;
}
set firstName(newFirstName) {
this._firstName = newFirstName;
}
}
myUser = new User('Henri');
myUser.firstName;
myUser.firstName = 'New name';

view raw

accessors.js

hosted with ❤ by GitHub

Contrairement à PHP, JavaScript n’a pas une syntaxe distincte pour l’accès aux méthodes statiques.


<?php
class Utilities {
public static function filter() {}
}
Utilities::filter();

view raw

static.php

hosted with ❤ by GitHub


class Utilities {
static filter() {}
}
Utilities.filter();

view raw

static.js

hosted with ❤ by GitHub

Pour l’instant, il n’y a pas de modificateurs de visibilité, ni d’interfaces et de classes abstraites. Ils apparaîtront sans doute dans une prochaine version de JavaScript, mais TypeScript permet de les utiliser dès maintenant (voir notre guide de PHP 7 à TypeScript).

Namespaces

L’encapsulation est gérée directement par le système de chargement depuis l’ES6 : s’il y a l’instruction export ou l’instruction import, alors vous n’êtes plus en portée globale.


<?php
// module.php
namespace Symfony\Accounts;
class User {}
// script.php
use Symfony\User\User;
$myUser = new User();

view raw

namespace.php

hosted with ❤ by GitHub


// module.js
export class User {}
// script.js
import { User } from './module.js';
let myUser = new User();

view raw

namespace.js

hosted with ❤ by GitHub

Poursuivre avec le guide de PHP 7 à TypeScript