💡 TL;DR
PHP interviews in 2026 aren't about reciting syntax anymore — they're testing whether you know PHP 8's newer features (enums, readonly properties, match), whether you can secure a query against SQL injection, and whether you actually understand why PHP behaves the way it does. Below are 15 questions, fresher round first, senior round after, with runnable code for each.
Why PHP interviews changed
If you last studied PHP a few years back, you learned PHP 5/7 habits that no longer hold up. PHP 8.x shipped enums, readonly properties, and the match expression, and interviewers use these specifically to weed out people who never updated their mental model. On top of that, most "PHP jobs" today are really Laravel jobs, so don't be surprised if dependency injection sneaks into a "pure PHP" interview.
Fresher-round questions
1. What are superglobals?
Built-in arrays available in every scope without needing global. The ones you'll actually touch: $_GET, $_POST, $_SESSION, $_SERVER, $_COOKIE.
$username = $_POST['username'] ?? 'guest'; // null coalescing avoids warnings
$method = $_SERVER['REQUEST_METHOD'];
2. echo vs print
echo takes multiple comma-separated arguments and returns nothing. print takes exactly one argument and returns 1, so it can be used inside an expression.
echo "Hello", " ", "World";
$result = print "Logging in..."; // $result === 1
3. == vs ===
== type-juggles before comparing. === compares value and type. This single distinction causes more PHP bugs than anything else in the language.
var_dump(0 == "abc"); // false in PHP 8+ (was true in PHP 7!)
var_dump("1" == 1); // true
var_dump("1" === 1); // false
The 0 == "abc" flip between PHP 7 and 8 trips up a lot of people who learned the language a while ago — worth knowing before someone asks you to explain it live.
4. Removing duplicates from an array
$ids = [101, 102, 101, 103, 102];
$unique = array_values(array_unique($ids)); // [101, 102, 103]
array_unique() filters, array_values() re-indexes so you don't end up with gaps in the keys.
5. include vs require
Both pull in another file's code. include throws a warning and keeps going if the file's missing; require throws a fatal error and stops execution. Use require for anything the app can't function without (DB config), include for optional stuff (footers).
6. Sessions vs cookies
Sessions store data server-side and hand the client a session ID. Cookies store data client-side. That's why sessions are the safer choice for anything sensitive.
session_start();
$_SESSION['user_id'] = 42; // lives on the server
setcookie('theme', 'dark', time() + 3600, '/'); // lives in the browser
7. The four pillars of OOP
Encapsulation, inheritance, polymorphism, abstraction — expect a follow-up where you have to extend the example with a second subclass.
abstract class Payment {
abstract public function process(float $amount): string;
}
class CardPayment extends Payment {
private string $cardNumber;
public function __construct(string $cardNumber) { $this->cardNumber = $cardNumber; }
public function process(float $amount): string {
return "Charged $amount to card ending in " . substr($this->cardNumber, -4);
}
}
8. Magic methods
Methods prefixed with __ that PHP calls automatically: __construct(), __get()/__set() for intercepting undefined property access, __toString() when an object is coerced to a string.
9. self:: vs static::
self:: always points to the class where the method is defined. static:: follows late static binding — it resolves to whichever class was actually called.
class Base {
public static function create(): static { return new static(); }
}
class Child extends Base {}
echo get_class(Child::create()); // "Child", not "Base"
Senior-round questions
10. What's actually new in PHP 8
Enums, readonly properties, and match come up constantly.
enum OrderStatus: string {
case Pending = 'pending';
case Shipped = 'shipped';
}
class Order {
public function __construct(
public readonly string $orderId,
public OrderStatus $status
) {}
}
$order = new Order('ORD-1001', OrderStatus::Pending);
$message = match ($order->status) {
OrderStatus::Pending => 'Waiting for shipment',
OrderStatus::Shipped => 'On its way',
};
Try mutating $order->orderId after construction — PHP throws, because that's the entire point of readonly.
11. Preventing SQL injection
The classic failure mode is concatenating user input straight into a query string.
// Bad
$query = "SELECT * FROM users WHERE username = '$username'";
// Good — bound, not concatenated
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username");
$stmt->execute(['username' => $username]);
Prepared statements keep the query structure and the data separate, so user input can never rewrite the query's logic — this matters for internal admin tools too, not just public-facing forms.
12. Common design patterns
Singleton and Factory show up most often. Singleton guarantees one instance (often a DB connection); Factory centralizes creation logic. Note the trade-off: singletons carry global state, which makes unit testing harder — many modern codebases prefer dependency injection instead.
13. Performance optimization
Interviewers want specifics, not "make it faster":
- Turn on OPcache so PHP doesn't recompile scripts every request.
- Kill N+1 queries — fetch related rows with one query instead of looping and querying per item.
// Bad: one query per order
foreach ($orders as $order) {
$pdo->query("SELECT * FROM items WHERE order_id = {$order['id']}");
}
// Good: one query total
$stmt = $pdo->query("SELECT * FROM items WHERE order_id IN (" . implode(',', $orderIds) . ")");
14. Dependency injection in Laravel
A class receives its dependencies from outside instead of instantiating them itself; Laravel's service container wires this up automatically.
class OrderController extends Controller {
public function __construct(private OrderService $orderService) {}
}
15. Abstract classes vs interfaces
An abstract class can mix implemented and unimplemented methods, and a class can only extend one. An interface declares signatures only, and a class can implement several.
Where people lose points
Two recurring mistakes: using loose in_array() comparisons (fix it with the third true argument for strict mode), and creating a fresh PDO connection inside a loop instead of reusing one connection across iterations.
The takeaway
None of this is really about memorization — it's about understanding why PHP does what it does. Pick a few questions above you weren't fully sure about, open a local PHP file, and actually run the code instead of just reading it.
Found this helpful? Check out more at CodePractice Blogs
Top comments (0)