Real Migration Problems When Moving from PHP to Node.js
Most PHP-to-Node.js migration guides are either too abstract or too obvious. Here's what actually bites you — and how to avoid it.
1. Legacy Hashes Won’t Validate
PHP’s password_hash() produces bcrypt hashes prefixed with $2y$. Most Node.js bcrypt libraries expect $2a$ or $2b$.
If you don’t normalize it, valid logins will fail silently.
// Fix prefix mismatch
storedHash = storedHash.replace('$2y$', '$2b$');
const isValid = await bcrypt.compare(password, storedHash);
2. $_SESSION Doesn’t Exist Anymore
PHP's session system is built-in and works out of the box. In Node.js, you must explicitly choose and configure a session or token strategy (cookies, JWTs, etc.).
Cookie-based JWT login example:
res.cookie('token', jwt.sign(user, JWT_SECRET), {
httpOnly: true,
secure: true,
sameSite: 'Lax',
maxAge: 1000 * 60 * 60 * 24
});
res.status(200).json({ message: 'Logged in' });
In frontend fetch requests, don’t forget:
fetch('/api/user', {
credentials: 'include'
});
3. PHP’s Automatic $_POST and $_GET Parsing = Manual Parsing in Node
PHP automatically populates $_POST and $_GET. In Node.js, you need middleware like express.json() and express.urlencoded() — or your routes won’t work.
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.post('/form', (req, res) => {
console.log(req.body); // not available without middleware
});
4. No Native Email or File Upload
PHP makes email sending and file uploads simple. In Node.js, you have to choose the right libraries (like nodemailer, multer) and configure them.
- Emails: use
nodemailerand SMTP or transactional APIs - Uploads: use
multeror upload to S3/cloud storage
5. Routing Isn’t Global
In PHP, every file is basically a route. Node.js needs explicit routing (e.g. Express or Hapi). Forgetting to define routes or middleware is a common cause of 404s.
6. Database Layers Are Different
In PHP, you might be used to raw SQL or ORMs like Eloquent. Node.js has no standard ORM. Choices include:
Prisma: good for devs new to SQLSequelize: more traditional ORMKnex: query builder with control
Whichever you pick, don't blindly reuse SQL — test all assumptions around NULL handling, casing, joins, and timezones.
Final Tip
PHP hides a lot of complexity. Node.js gives you power but expects you to wire everything yourself. If something "just worked" in PHP, assume you’ll need to explicitly implement it in Node.
