Node.js et Express quand on vient de PHP : CRUD et login
Tu connais PHP ? Refais ton CRUD et ton login avec Node.js et Express : npm, MVC, mysql2, bcrypt, express-session. Les équivalences PHP → Node.
Aussi en : العربية

Si tu sais déjà faire un CRUD et un login en PHP, tu sais presque tout faire en Node.js : les idées restent les mêmes, seul le langage change. Dans le cours E14, on reprend le mini CRUD et le login de la série PHP, la même table users dans MySQL, et on les refait avec Express, rangés en MVC. Cet article résume le chemin, avec le tableau des équivalences PHP → Node.
Node.js, c'est quoi exactement ?
Dans Chrome, un moteur appelé V8 lit et exécute le JavaScript. En 2009, Ryan Dahl a eu l'idée de sortir ce moteur du navigateur pour le faire tourner sur le serveur : c'est Node.js.
La différence pratique :
- dans le navigateur, JavaScript contrôle la page (DOM, clics, affichage) mais ne peut pas lire les fichiers du serveur ;
- dans Node.js, le même langage peut lire des fichiers, parler à une base de données et répondre à des requêtes.
Un seul langage pour le front et le back : c'est l'idée derrière la pile MERN. Et Express est le framework le plus utilisé sur Node pour construire un site ou une API.
Premier essai, comme dans le cours : un fichier app.js qui contient un console.log, lancé depuis le terminal.
node app.jsComment démarrer le projet ?
npm, le Composer de Node
npm est le gestionnaire de paquets de Node, comme Composer en PHP. On commence par npm init, qui crée package.json, la carte d'identité du projet. Puis on installe les librairies utilisées dans le cours, chacune avec son rôle :
| Paquet | Rôle dans le projet |
|---|---|
express | le serveur et les routes |
ejs | les pages HTML |
mysql2 | parler à MySQL |
bcrypt | les mots de passe |
express-session | les sessions |
dotenv | lire le fichier .env |
npm init
npm install express ejs mysql2 bcrypt express-session dotenvLes librairies vont dans node_modules et sont enregistrées dans package.json.
La même organisation MVC
Le projet est rangé comme dans le cours MVC : models/ contient le SQL, controllers/ la logique, views/ les pages EJS, et routes/ relie chaque URL à un controller.
Le fichier .env ne va jamais sur GitHub
.env contient tout ce qui est secret : le mot de passe de la base, le secret de la session, les clés API. Ajoute-le dans .gitignore, avec node_modules.
.env
node_modulesConseil du cours : node --watch (ou nodemon) relance le serveur tout seul quand tu modifies le code.
Pourquoi la base MySQL ne change pas ?
Parce que MySQL n'est pas PHP. C'est un SGBD, un serveur à part, auquel PHP, Node, Python ou n'importe quel langage peut parler. On garde donc la même table users. Dans db.js, on crée un pool avec mysql2 en lisant les informations de connexion dans .env. Chaque requête renvoie un tableau rows qui contient les utilisateurs.
Le CRUD avec Express
Le chemin d'une demande reste celui du MVC : la route appelle une méthode du controller, qui interroge le model, puis rend une vue.
- Dans
app.js, on activeexpress.urlencodedpour lire les formulaires. - Dans
routes/users,GET /usersva à la méthodeindexdu controller. indexdemande au modelawait User.findAll(), puis appelleres.rendersur la pageusers/index.
Le code affiché dans le cours, en CommonJS (require, exports) :
// controllers/userController.js
const User = require('../models/userModel');
exports.index = async (req, res) => {
const users = await User.findAll();
res.render('users/index', { users });
};
// models/userModel.js
const pool = require('../db');
exports.findAll = async () => {
const [rows] = await pool.execute('SELECT * FROM users');
return rows;
};Pourquoi await ?
La base met un peu de temps à répondre. await attend la réponse avant de continuer. Et avec Express 5, si une erreur survient dans une fonction async, Express l'envoie tout seul au middleware d'erreurs.
Ajouter, modifier, supprimer
- Ajouter :
POST /users. La méthodestorelitreq.body(le nom et l'email), le model fait unINSERTavecexecute, puisres.redirect('/users'), l'équivalent deheader Location. - Modifier :
/users/:id/edit. L'id se lit avecreq.params.id. Le model faitUPDATE users SET nom = ?, email = ? WHERE id = ?, avec les valeurs dans un tableau, dans le même ordre que les points d'interrogation. - Supprimer : en
POST, pas enGET, et toujours avec unWHERE. SansWHERE, tu effaces tous les utilisateurs.
Les points d'interrogation font de chaque requête une requête préparée, comme prepare / execute avec PDO. Ne colle jamais le contenu du formulaire dans le SQL : c'est la porte ouverte à l'injection SQL.
Côté vue, EJS affiche avec <%= %>, qui protège du XSS comme htmlspecialchars.
Test de fin de chapitre : node app.js, puis localhost:3000/users. La liste s'affiche et le formulaire ajoute un utilisateur.
Inscription et login avec bcrypt
La règle numéro un ne change pas : un mot de passe n'est jamais stocké tel quel. Si la base est volée, les mots de passe en clair sont lisibles, et beaucoup de gens réutilisent le même partout.
// controllers/authController.js
const bcrypt = require('bcrypt');
const User = require('../models/userModel');
exports.register = async (req, res) => {
const { nom, email, password } = req.body;
const hash = await bcrypt.hash(password, 10);
await User.register(nom, email, hash);
res.redirect('/login');
};
exports.login = async (req, res) => {
const { email, password } = req.body;
const user = await User.findByEmail(email);
const ok = user && await bcrypt.compare(password, user.password);
if (!ok) return res.render('login', {
erreur: 'Email ou mot de passe incorrect' });
// la session : chapitre suivant
};10est le coût : le nombre de fois où bcrypt refait le calcul. Plus il est grand, plus c'est difficile pour un pirate.- Le hash contient un sel et il est à sens unique, comme
password_hash/password_verifyen PHP. - En cas d'échec, un seul message : « Email ou mot de passe incorrect ». Le
user &&évite de comparer quand l'email n'existe pas. Ne dis pas à un attaquant ce qui existe dans la base. - L'email est
UNIQUEdans la table, pour que deux comptes ne partagent pas la même adresse.
La session et le middleware requireAuth
Le cours reprend l'image du badge d'hôtel : tu montres ta carte une fois, on te donne un badge.
express-sessiondistribue le badge, commesession_start.- Le badge est un cookie appelé
connect.sid(en PHP, c'étaitPHPSESSID). - Le secret de session va dans
.env: c'est lui qui signe le badge. - Quand le mot de passe est bon :
req.session.regenerate()pour changer de badge (commesession_regenerate_id), puisreq.session.userId(comme$_SESSION['user_id']). - Logout :
req.session.destroy(), et l'ancien badge n'ouvre plus aucune porte.
Pour les pages protégées, un petit middleware :
// middleware/requireAuth.js
function requireAuth(req, res, next) {
if (!req.session.userId) return res.redirect('/login');
next();
}C'est le isset, header et exit de PHP, mais écrit une seule fois pour toutes les routes. Test : /dashboard sans être connecté renvoie au login ; après connexion, la page affiche « Mer7ba, Sara ! ».
Et les tokens JWT ?
Si le front est une application React ou une application mobile, on utilise souvent un token comme JWT. La différence avec la session : avec la session, le badge reste connu du serveur ; un JWT est une carte signée que le client garde avec lui. Au login, jwt.sign crée le token avec le secret du .env ; à chaque requête, il est envoyé dans le header Authorization: Bearer. Le middleware fait jwt.verify : token valide, next() ; sinon, erreur 401. Côté Laravel, l'idée équivalente s'appelle Sanctum. Le détail complet avec React est dans l'article React + API et login JWT.
Et le front ?
Aujourd'hui, EJS : le serveur construit le HTML et envoie une page toute prête, comme les vues PHP. Demain, React : le serveur ne renvoie que du JSON, et React construit la page dans le navigateur. L'API Express sert alors de back-end au front React.
Questions fréquentes
Faut-il réapprendre MySQL pour utiliser Node.js ?
Non. MySQL est un serveur à part ; Node lui parle avec le paquet mysql2. Le cours garde exactement la même table users que dans la série PHP.
Express ou EJS : qui fait quoi ?
Express gère le serveur et les routes ; EJS fabrique les pages HTML côté serveur, comme les vues PHP. Plus tard, React remplace EJS et Express renvoie du JSON.
Session ou JWT : lequel choisir ?
Le cours utilise la session pour un site rendu par le serveur (EJS). Pour un front React ou une application mobile, il présente le token JWT, envoyé dans le header Authorization: Bearer.
Pourquoi supprimer en POST et pas en GET ?
Parce qu'une suppression modifie les données : le cours la fait en POST, toujours avec un WHERE, pour ne jamais effacer toute la table.
À retenir
| PHP | Node.js / Express |
|---|---|
$_POST | req.body |
$_GET['id'] | req.params.id |
prepare / execute (PDO) | pool.execute(sql, [ ]) |
htmlspecialchars | <%= %> dans EJS |
password_hash / password_verify | bcrypt.hash / bcrypt.compare |
session_start, $_SESSION | express-session, req.session |
isset + header + exit | middleware requireAuth |
header Location | res.redirect |
PHP ou Node : les mêmes idées. Quand tu as compris l'idée, changer de langage ne fait plus peur.
Regarder le cours
Le cours complet (environ 8 min 50, en darija) est sur sa page : Lire un exemple Node.js et Express (E14).
- 0:00 Introduction : JavaScript, même sur le serveur ?
- 0:28 JavaScript partout : V8, Node.js et Express
- 1:30 Le projet : npm, MVC et le fichier .env
- 2:38 La base : MySQL, un SGBD accessible partout
- 3:09 Le CRUD avec Express (req.body, req.params, requêtes préparées, EJS)
- 5:12 Inscription et login avec bcrypt
- 5:57 La session : express-session et le middleware requireAuth
- 7:07 Et les tokens ? JWT (et Sanctum côté Laravel)
- 7:46 Et le front ? EJS aujourd'hui, React demain
- 8:09 Récap PHP / Node et le défi
Pour aller plus loin
- Avant : le MVC en PHP expliqué.
- Après : ton premier projet React, le panier, puis React consomme l'API Node : CRUD et login JWT.
- Pourquoi ton
localhost:3000n'est pas visible chez un ami : ce qui se passe quand tu tapes une URL. - Le parcours : Développement Web Full Stack.
- Les bases du réseau, de OSI à TCP/IP : réseau informatique, cours de révision.
Sources
Quiz : 3 questions pour vérifier
Rien n’est envoyé : tes réponses restent dans ton navigateur.
Rédigé à partir du cours vidéo et de sa transcription, avec l’aide d’outils d’IA, relu et vérifié par Mehdi Laraibi le 4 novembre 2026.



