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>`;

view raw
templatestring.js
hosted with ❤ by GitHub

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;

view raw
destructuring.php
hosted with ❤ by GitHub

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

view raw
destructuring.js
hosted with ❤ by GitHub

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`

view raw
destructuring.php
hosted with ❤ by GitHub

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

view raw
destructuring.js
hosted with ❤ by GitHub

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`

view raw
destructuring.js
hosted with ❤ by GitHub

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

view raw
destructuring.js
hosted with ❤ by GitHub

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