Skip to content

PHP Developer Interview Questions & Answers

40 questions for PHP Developer interviews — 3 easy, 32 medium, 5 hard.

About the PHP Developer role

A PHP developer builds server-side features such as login systems, admin panels, forms, payment flows and REST APIs using core PHP or Laravel. They design MySQL tables, write efficient queries and integrate third-party services. Agencies, e-commerce firms and product companies in India hire PHP developers to build new modules and maintain long-running applications.

PHP 8 and OOP Laravel MySQL queries REST APIs Secure coding
Solved for this roleStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
3 questions free Unlock the rest in seconds
01

What is the difference between InnoDB and MyISAM?

Save to ▾
Show answer
InnoDB is the default MySQL storage engine. It supports transactions, row-level locking, foreign keys and crash recovery, making it suitable for almost all applications. MyISAM uses table-level locking, has no transactions or foreign keys, and can corrupt on crashes. MyISAM was once faster for read-only workloads, but modern InnoDB matches or beats it. Old tables still on MyISAM should usually be converted.
02

Use the PHP 8 match expression instead of a switch.

Save to ▾
Show answer
match returns a value, uses strict comparison and needs no break: $status = 'shipped'; $label = match ($status) { 'pending' => 'Order received', 'shipped', 'in_transit' => 'On the way', 'delivered' => 'Delivered', default => 'Unknown status', }; echo $label; Unlike switch, match throws an UnhandledMatchError if no arm matches and there is no default, which surfaces missing cases early.
03

How do you back up and restore a MySQL database from the command line?

Save to ▾
Show answer
mysqldump creates a logical SQL backup: mysqldump -u root -p --single-transaction --routines school > school_2026_11_12.sql mysql -u root -p school < school_2026_11_12.sql --single-transaction takes a consistent InnoDB snapshot without locking tables. For large databases, physical backup tools or managed cloud snapshots are faster. Backups should be automated, stored off-server, and restored on a test server regularly to prove they work.
04

Users get logged out immediately after login when redirected. What could be wrong?

Save to ▾
Show answer
Likely causes are session_start() missing on the next page, output sent before session_start so headers fail, or the session cookie being dropped. Cookie issues include a Secure flag on an HTTP site, a domain mismatch between www and non-www, or SameSite settings during cross-site redirects. I would check the Set-Cookie header in DevTools, verify session.save_path is writable, and redirect to a single canonical domain.
05

Name important features added in PHP 8.x.

Save to ▾
Show answer
PHP 8.0 added the JIT compiler, named arguments, union types, the match expression, the nullsafe operator ?-> and constructor property promotion. PHP 8.1 added enums, readonly properties, fibers and never return type. PHP 8.2 added readonly classes, 8.3 added typed class constants and json_validate, and 8.4 added property hooks and asymmetric visibility. Together they make PHP code safer, shorter and more strongly typed.
06

Tell me about a time a website went down and how you handled it.

Save to ▾
Show answer
Situation: our e-commerce site went down at 11 PM during a sale. Task: as the on-call developer, I had to restore it fast. Action: I checked logs, found PHP-FPM workers exhausted by a slow query, restarted the service, added an index to fix the query, and kept the team updated every 15 minutes. Result: the site was back in 20 minutes, and I wrote a postmortem with monitoring alerts to catch it earlier.
07

When would you choose Flexbox and when CSS Grid?

Save to ▾
Show answer
Flexbox is one-dimensional: it arranges items in a row or a column and is great for navbars, button groups and centering. Grid is two-dimensional: it controls rows and columns together, which suits page layouts, dashboards and card galleries. A common pattern is Grid for the overall page structure and Flexbox inside each component. Both are fully supported in all modern browsers.
08

Validate and sanitise different types of input in PHP.

Save to ▾
Show answer
Use filter functions and allow-lists: $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL); $age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT, ['options' => ['min_range' => 18, 'max_range' => 60]]); $sort = in_array($_GET['sort'] ?? '', ['name', 'price'], true) ? $_GET['sort'] : 'name'; if ($email === false || $age === false) { $errors[] = 'Please enter a valid email and age.'; } Allow-lists are essential for values like column names that cannot be bound as prepared statement parameters.
09

A client insists on a major deployment on Friday evening. How do you respond?

Save to ▾
Show answer
Situation: a client wanted a big redesign live before a weekend campaign. Task: I had to respect their goal but reduce risk. Action: I explained that weekend issues would have fewer people to fix them, proposed deploying Thursday morning on staging-tested code, and arranged a rollback plan and someone on call. Result: the client agreed, we deployed Thursday, fixed two small issues the same day, and the campaign ran smoothly.
10

What is SQL injection and how do prepared statements stop it?

Save to ▾
Show answer
SQL injection happens when user input is concatenated into a query, so input like ' OR '1'='1 changes the query's logic and can dump or delete data. Prepared statements send the SQL structure and the data separately, so the database always treats input as a value, never as code. Escaping functions are not a full substitute. Least-privilege database users limit the damage if a flaw slips through.
11

Show monthly revenue for the current year from an orders table.

Save to ▾
Show answer
Group by month and sum the amounts: SELECT DATE_FORMAT(created_at, '%Y-%m') AS month, COUNT(*) AS orders, SUM(amount) AS revenue FROM orders WHERE created_at >= '2026-01-01' AND created_at < '2027-01-01' AND status = 'paid' GROUP BY month ORDER BY month; Using a date range instead of YEAR(created_at) = 2026 lets MySQL use an index on created_at.
12

What is Composer and how does PSR-4 autoloading work?

Save to ▾
Show answer
Composer is PHP's dependency manager. composer.json lists packages, composer.lock pins exact versions, and the vendor folder holds installed code. PSR-4 maps a namespace prefix to a folder, for example App\ to src/, so App\Models\User loads from src/Models/User.php automatically after you require vendor/autoload.php. This removes manual require statements. composer.lock should be committed so every environment installs identical versions.
13

Create students, courses and enrollments tables with proper keys.

Save to ▾
Show answer
A many-to-many relationship needs a junction table: CREATE TABLE students ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, email VARCHAR(150) NOT NULL UNIQUE ); CREATE TABLE courses ( id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(150) NOT NULL ); CREATE TABLE enrollments ( student_id INT, course_id INT, enrolled_on DATE NOT NULL, PRIMARY KEY (student_id, course_id), FOREIGN KEY (student_id) REFERENCES students(id) ON DELETE CASCADE, FOREIGN KEY (course_id) REFERENCES courses(id) );
14

What are CSS custom properties and how are they different from Sass variables?

Save to ▾
Show answer
Custom properties like --brand: #2563eb are defined in CSS and read with var(--brand). They cascade, can be changed per element or media query, and can be updated at runtime with JavaScript, which makes themes and dark mode easy. Sass variables are replaced at compile time and do not exist in the browser. Many teams use both: Sass for build-time logic and custom properties for runtime theming.
15

How should passwords be stored in PHP?

Save to ▾
Show answer
Never store plain text or use md5 or sha1, which are fast and easily cracked. Use password_hash($password, PASSWORD_DEFAULT), which currently uses bcrypt with an automatic random salt, or PASSWORD_ARGON2ID where available. At login use password_verify($input, $hash). password_needs_rehash lets you upgrade old hashes when the default algorithm or cost changes. The hash column should be VARCHAR(255) to allow future algorithms.
16

Add security headers through Nginx configuration.

Save to ▾
Show answer
Place these in the server block: add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains' always; add_header X-Content-Type-Options 'nosniff' always; add_header Referrer-Policy 'strict-origin-when-cross-origin' always; add_header Content-Security-Policy "default-src 'self'; img-src 'self' data:; frame-ancestors 'none'" always; add_header Permissions-Policy 'camera=(), microphone=()' always; Start CSP in Content-Security-Policy-Report-Only mode to find what breaks before enforcing it.
17

A PHP page takes 8 seconds to load. How do you find the bottleneck?

Save to ▾
Show answer
I would measure before guessing, using a profiler like Xdebug or Blackfire, or simple microtime logs around sections. Usually the cause is database queries, such as an N+1 pattern running a query inside a loop, missing indexes, or slow external API calls. Fixes include joining or eager loading, adding indexes, caching results in Redis, making API calls async with a queue, and enabling OPcache.
18

Explain database normalization up to third normal form.

Save to ▾
Show answer
Normalization reduces duplicate data and update problems. 1NF requires atomic values, no repeating groups like phone1, phone2. 2NF requires every non-key column to depend on the whole primary key, not part of a composite key. 3NF removes transitive dependencies, so a column depends only on the key, for example moving city details out of an orders table. Read-heavy reports sometimes denormalise deliberately for speed.
19

What are transactions and ACID properties?

Save to ▾
Show answer
A transaction groups several SQL statements so they succeed or fail together. ACID means Atomicity, all or nothing; Consistency, rules and constraints stay valid; Isolation, concurrent transactions do not see each other's partial changes; and Durability, committed data survives crashes. For example, transferring wallet balance debits one row and credits another inside START TRANSACTION and COMMIT, with ROLLBACK if anything fails.
20

Write a PHP login script using password_verify and sessions.

Save to ▾
Show answer
Fetch the user, verify the hash and regenerate the session id: session_start(); $stmt = $pdo->prepare('SELECT id, password_hash FROM users WHERE email = ?'); $stmt->execute([$_POST['email']]); $user = $stmt->fetch(); if ($user && password_verify($_POST['password'], $user['password_hash'])) { session_regenerate_id(true); $_SESSION['user_id'] = $user['id']; header('Location: /dashboard.php'); exit; } $error = 'Invalid email or password'; Regenerating the id prevents session fixation attacks.
21

The database server is overloaded by read traffic. What architecture changes would you suggest?

Save to ▾
Show answer
I would first add caching for frequent reads with Redis or application-level caching. Then I would set up one or more read replicas and route SELECT queries to them while writes go to the primary, keeping replication lag in mind for read-after-write cases. Optimising slow queries and indexes often gives the cheapest wins. Managed services like Amazon RDS make adding replicas straightforward.
22

Add CSRF protection to a plain PHP form.

Save to ▾
Show answer
Generate a token per session and compare it safely: session_start(); if (empty($_SESSION['csrf'])) { $_SESSION['csrf'] = bin2hex(random_bytes(32)); } // in the form echo "<input type='hidden' name='csrf' value='" . $_SESSION['csrf'] . "'>"; // on submit if (!hash_equals($_SESSION['csrf'], $_POST['csrf'] ?? '')) { http_response_code(403); exit('Invalid request'); } hash_equals compares in constant time, which avoids timing attacks.
23

Write a query to find duplicate email addresses in a users table.

Save to ▾
Show answer
Group by the column and keep groups with more than one row: SELECT email, COUNT(*) AS total FROM users GROUP BY email HAVING COUNT(*) > 1; To delete duplicates but keep the lowest id: DELETE u1 FROM users u1 JOIN users u2 ON u1.email = u2.email AND u1.id > u2.id; Afterwards add a UNIQUE index on email so duplicates cannot come back.
24

What are traits in PHP?

Save to ▾
Show answer
Traits allow code reuse across unrelated classes, since PHP supports only single inheritance. You define a trait with methods, such as a Loggable trait with a log() method, and add it to any class using use Loggable;. Conflicts between traits are resolved with insteadof and as. Traits are handy for cross-cutting behaviour like timestamps or soft deletes, but overusing them hides dependencies and makes classes harder to understand.
25

Users report being redirected to a gambling site from your pages. What do you check?

Save to ▾
Show answer
This often comes from injected JavaScript or a compromised third-party script. I would check the page source and Network tab for unfamiliar scripts, inspect .htaccess for malicious rewrite rules, search the database and theme files for obfuscated code like base64_decode or eval, and review recently changed files on the server. A strict CSP and Subresource Integrity on CDN scripts help prevent repeat incidents.
26

What is the difference between px, em and rem units?

Save to ▾
Show answer
px is a fixed unit. em is relative to the font size of the current element, so nested em values compound and can grow unexpectedly. rem is relative to the root html font size, usually 16 pixels, so 1.5rem is always 24 pixels unless the user changes browser settings. Using rem for font sizes and spacing respects user preferences and keeps scaling consistent across the site.
27

What is the difference between DELETE, TRUNCATE and DROP?

Save to ▾
Show answer
DELETE removes selected rows using a WHERE clause, can be rolled back inside a transaction and fires triggers, but is slow on large tables. TRUNCATE removes all rows quickly by recreating the table, resets AUTO_INCREMENT and cannot be rolled back in MySQL. DROP removes the table structure and data completely. Always take a backup and double-check the WHERE clause before running DELETE on production.
28

Tell me about a time you disagreed with a designer about a layout.

Save to ▾
Show answer
Situation: a designer wanted a five-column pricing table on mobile. Task: I had to deliver the design while keeping it usable on small screens. Action: I built a quick prototype on a real phone, showed that text became unreadable, and proposed a swipeable card version that kept the same visual style. Result: the designer agreed, we updated the Figma file together, and mobile conversions on that page improved after launch.
29

A client's WordPress site has been hacked and shows spam links. What steps do you take?

Save to ▾
Show answer
I would take a full backup for evidence, put the site in maintenance mode and change all passwords, including hosting, database, FTP and admin users. Then I would compare core files with fresh copies, scan themes, plugins and uploads for injected PHP, remove unknown admin users and check the database for spam content. After cleaning I would update everything, remove unused plugins, add a firewall and request a Google review.
30

Your frontend on one domain gets a CORS error calling your API on another. How do you resolve it?

Save to ▾
Show answer
The fix belongs on the API server, not the frontend. I would configure it to return Access-Control-Allow-Origin with the exact frontend origin, handle OPTIONS preflight requests with the allowed methods and headers, and add Access-Control-Allow-Credentials: true if cookies are needed. Alternatively, serving the API under the same domain through a reverse proxy, like /api, removes cross-origin calls altogether.
31

Database credentials were accidentally pushed to a public GitHub repository. What now?

Save to ▾
Show answer
Deleting the commit is not enough, because bots scan GitHub within minutes. I would immediately rotate the password and any other exposed keys, check database logs for suspicious access, and then purge the secret from history using git filter-repo. Going forward, secrets belong in environment variables or a secrets manager, .env files go in .gitignore, and secret-scanning tools run in CI.
32

Find the top 3 highest-paid employees in each department.

Save to ▾
Show answer
Use a window function in MySQL 8: WITH ranked AS ( SELECT name, department_id, salary, DENSE_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rnk FROM employees ) SELECT name, department_id, salary FROM ranked WHERE rnk <= 3; PARTITION BY restarts ranking per department. DENSE_RANK keeps ties together, while ROW_NUMBER would return exactly three rows even if salaries tie.
33

Limit failed login attempts to stop brute-force attacks.

Save to ▾
Show answer
Track failures per account and IP, then block temporarily: $stmt = $pdo->prepare('SELECT COUNT(*) FROM login_attempts WHERE ip = ? AND attempted_at > NOW() - INTERVAL 15 MINUTE'); $stmt->execute([$_SERVER['REMOTE_ADDR']]); if ($stmt->fetchColumn() >= 5) { http_response_code(429); exit('Too many attempts. Try again in 15 minutes.'); } // on failure $pdo->prepare('INSERT INTO login_attempts (ip, attempted_at) VALUES (?, NOW())') ->execute([$_SERVER['REMOTE_ADDR']]); Add CAPTCHA after a few failures and offer two-factor authentication.
34

What is CORS and why does the browser block some API calls?

Save to ▾
Show answer
The same-origin policy stops scripts on one origin from reading responses from another origin. CORS is how a server opts in: it returns headers like Access-Control-Allow-Origin naming allowed origins. For non-simple requests, such as JSON with custom headers, the browser first sends an OPTIONS preflight. CORS is enforced only by browsers, so it is not a security control for the server itself, and Allow-Origin * should never be combined with credentials.
35

Configure secure session cookie settings in PHP.

Save to ▾
Show answer
Set cookie parameters before session_start: session_set_cookie_params([ 'lifetime' => 0, 'path' => '/', 'secure' => true, 'httponly' => true, 'samesite' => 'Lax' ]); ini_set('session.use_strict_mode', '1'); session_start(); secure sends the cookie only over HTTPS, httponly hides it from JavaScript so XSS cannot steal it, and SameSite reduces CSRF. Strict mode rejects session ids the server never created.
36

Pagination becomes very slow on later pages. Why, and how do you fix it?

Save to ▾
Show answer
LIMIT 20 OFFSET 100000 forces MySQL to read and discard 100,000 rows before returning 20, so deep pages get slower. Keyset or cursor pagination fixes this: remember the last seen id and query WHERE id < :last_id ORDER BY id DESC LIMIT 20, which uses the index directly. It suits infinite scroll and APIs. For numbered pages, limiting maximum depth or caching counts also helps.
37

Write a function that groups an array of students by city.

Save to ▾
Show answer
Object.groupBy is available in modern browsers and Node 21+, with reduce as a fallback: const students = [ { name: 'Asha', city: 'Delhi' }, { name: 'Ravi', city: 'Pune' }, { name: 'Neha', city: 'Delhi' } ]; const byCity = Object.groupBy(students, s => s.city); const byCity2 = students.reduce((acc, s) => { (acc[s.city] ||= []).push(s); return acc; }, {}); Both return { Delhi: [...], Pune: [...] }.
38

How do you handle pressure to skip security work to meet a deadline?

Save to ▾
Show answer
Situation: a manager wanted to launch a form without server-side validation to save a day. Task: I needed to protect the product without blocking the launch. Action: I explained the risk in business terms, data leaks and spam, and proposed shipping core validation and rate limiting now, with less critical hardening in the next sprint. Result: we launched on time with essential protections and completed the rest within a week.
39

What is CSRF and how do you prevent it?

Save to ▾
Show answer
Cross-site request forgery tricks a logged-in user's browser into sending an unwanted request, such as changing their email, because cookies are attached automatically. Prevention includes a unique CSRF token in every state-changing form that the server verifies, SameSite=Lax or Strict cookies, and checking the Origin header. GET requests should never change data. Frameworks like Laravel add CSRF tokens to forms by default.
40

Build a simple PHP endpoint that returns JSON.

Save to ▾
Show answer
Set the header, encode the data and use proper status codes: header('Content-Type: application/json'); $id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT); if (!$id) { http_response_code(400); echo json_encode(['error' => 'Invalid id']); exit; } $stmt = $pdo->prepare('SELECT id, name, price FROM courses WHERE id = ?'); $stmt->execute([$id]); $course = $stmt->fetch(PDO::FETCH_ASSOC); http_response_code($course ? 200 : 404); echo json_encode($course ?: ['error' => 'Not found']);

Frequently asked questions

What does a PHP Developer do?

A PHP developer builds server-side features such as login systems, admin panels, forms, payment flows and REST APIs using core PHP or Laravel. They design MySQL tables, write efficient queries and integrate third-party services. Agencies, e-commerce firms and product companies in India hire PHP developers to build new modules and maintain long-running applications.

Which skills are tested in a PHP Developer interview?

Expect questions on PHP 8 and OOP, Laravel, MySQL queries, REST APIs, Secure coding. Most rounds also ask you to explain a project and solve one practical problem live.

How do I prepare for a PHP Developer interview?

Revise PHP Programming, MySQL Database, Web Security first using the topic sheets, practise the questions on this page aloud, then do one full mock interview to practise timing.