HireHireInterview Quizzes › PHP Developer

PHP Developer Interview Questions

Think you're ready? These are the questions that actually decide PHP Developer interviews. Warm up on Easy — then face the Hard round, where 95% of candidates crumble. 80 questions across 3 levels, instant score, completely free.

80Questions
3Difficulty levels
95%Fail the hard round
FreeInstant score
Easy
Warm-up · 20 Qs
Medium
Practical · 30 Qs
Hard
Brutal · 30 Qs
⚡ Take the PHP Developer quiz — get your score →

The PHP Developer interview questions

Below are the real questions, grouped by difficulty. Expand any one to reveal the correct answer and why — or take the timed quiz for a score you can share. Can you clear the Hard round?

Easy round 20 questions

In PHP 8, what does var_dump(0 == "hello") output?
  • A. bool(true)
  • B. bool(false) ✓
  • C. int(0)
  • D. NULL
Correct answer: B. In PHP 8 a non-numeric string is no longer cast to 0, so 0 == "hello" is false.
What is the result of the expression "5" + 3 in PHP?
  • A. "53" (string)
  • B. 8 (int) ✓
  • C. Error: cannot add string and int
  • D. "8" (string)
Correct answer: B. The + operator is arithmetic in PHP; the numeric string "5" is coerced to 5, giving the integer 8.
You need to safely insert user input into a MySQL query. Which approach prevents SQL injection?
  • A. Concatenating the input directly into the query string
  • B. Using PDO prepared statements with bound parameters ✓
  • C. Wrapping the input in single quotes manually
  • D. Using addslashes() on the whole query
Correct answer: B. Prepared statements with bound parameters separate data from SQL, preventing injection.
A page calls session_start() after already echoing HTML. What happens?
  • A. Sessions work normally
  • B. A 'headers already sent' warning and the session cookie fails ✓
  • C. The HTML is discarded
  • D. PHP restarts the request automatically
Correct answer: B. session_start() sends headers, so any prior output triggers a 'headers already sent' error and the cookie is not set.
Given $a = ['x' => 1]; what does isset($a['y']) return?
  • A. true
  • B. false ✓
  • C. NULL
  • D. A warning is thrown
Correct answer: B. isset() returns false for a key that does not exist, without emitting a warning.
What is the correct way to combine two strings in PHP: $full = $first ? $last?
  • A. $first + $last
  • B. $first . $last ✓
  • C. $first & $last
  • D. concat($first, $last)
Correct answer: B. The dot (.) is PHP's string concatenation operator; + is arithmetic.
$name = $_GET['name'] ?? 'guest'; What does this do if 'name' is not in the query string?
  • A. Throws an undefined index warning
  • B. Assigns the string 'guest' to $name ✓
  • C. Assigns NULL to $name
  • D. Assigns an empty string to $name
Correct answer: B. The null coalescing operator ?? returns the right operand when the left is null or unset, with no warning.
For storing user passwords, which is the correct choice?
  • A. md5($password)
  • B. password_hash($password, PASSWORD_DEFAULT) ✓
  • C. base64_encode($password)
  • D. sha1($password) with a static salt
Correct answer: B. password_hash() uses a strong, salted, slow algorithm designed for passwords; md5/sha1/base64 are unsuitable.
What does echo count([1, 2, [3, 4], 5]); output?
  • A. 5
  • B. 4 ✓
  • C. 3
  • D. 6
Correct answer: B. count() without COUNT_RECURSIVE counts top-level elements only; the nested array is one element, so the total is 4.
In a foreach loop written as foreach ($arr as &$v) { }, what is a common bug if you reuse $v afterward?
  • A. The loop runs one extra time
  • B. $v remains a reference to the last element and can corrupt the array ✓
  • C. The array is emptied
  • D. PHP throws a fatal error
Correct answer: B. After a reference foreach, $v still points to the last element, so later assignments to $v overwrite that element; unset($v) is the fix.
What is the difference between include and require when the file is missing?
  • A. Both stop the script with a fatal error
  • B. include gives a warning and continues; require gives a fatal error and stops ✓
  • C. include stops; require continues
  • D. Both silently continue
Correct answer: B. A missing include emits a warning and execution continues; a missing require raises a fatal error and halts.
echo json_encode(['a' => 1, 'b' => true]); produces what?
  • A. {"a":1,"b":true} ✓
  • B. ["a":1,"b":true]
  • C. {a:1,b:true}
  • D. {"a":"1","b":"true"}
Correct answer: A. An associative array encodes to a JSON object with quoted keys and native JSON types for the values.
$parts = explode(',', 'a,b,c'); What is $parts[1]?
  • A. 'a'
  • B. 'b' ✓
  • C. 'c'
  • D. ','
Correct answer: B. explode splits on the comma into ['a','b','c'], so index 1 is 'b'.
A class property declared 'private' can be accessed from where?
  • A. Anywhere the object is used
  • B. Only within the class that declares it ✓
  • C. Only from child classes
  • D. Only from the same namespace
Correct answer: B. private members are accessible solely inside the declaring class, not from subclasses or outside code.
How do you call a static method 'make' on class Widget?
  • A. $Widget->make()
  • B. Widget::make() ✓
  • C. Widget->make()
  • D. static Widget.make()
Correct answer: B. Static methods are called on the class using the scope resolution operator, Widget::make().
What does echo 17 % 5; output?
  • A. 3
  • B. 2 ✓
  • C. 3.4
  • D. 12
Correct answer: B. The modulo operator returns the remainder of 17 divided by 5, which is 2.
Which array is produced by array_merge(['a', 'b'], ['c', 'd'])?
  • A. ['a','b','c','d'] ✓
  • B. ['c','d']
  • C. ['a'=>'c','b'=>'d']
  • D. ['a','b',['c','d']]
Correct answer: A. For arrays with numeric keys, array_merge appends and re-indexes, yielding ['a','b','c','d'].
In an if condition, which of these values is treated as false by PHP?
  • A. '0' ✓
  • B. 'false'
  • C. '0.0'
  • D. ' ' (a space)
Correct answer: A. The string '0' is falsy, but any other non-empty string (including 'false', '0.0', and ' ') is truthy.
You want to send a redirect with header('Location: /home'). What must be true?
  • A. It can be called anywhere in the script
  • B. No output (HTML, echo, or whitespace) may be sent before it ✓
  • C. It must be the last line of the file
  • D. It only works inside a function
Correct answer: B. header() must run before any body output, since sending output flushes the HTTP headers first.
Data submitted from a form using method="post" is read in PHP via which superglobal?
  • A. $_GET
  • B. $_POST ✓
  • C. $_REQUEST only
  • D. $_SERVER
Correct answer: B. Form data sent with the POST method is available in the $_POST superglobal array.

Medium round 30 questions

Given `$a = '0'; $b = false;`, what does `var_dump($a == $b)` output, and why?
  • A. bool(true), because the string '0' is loosely equal to false ✓
  • B. bool(false), because a string and a boolean are never comparable
  • C. bool(true), because any non-empty string equals false
  • D. bool(false), because '0' is a truthy string
Correct answer: A. The string '0' is one of PHP's falsy values, so with loose comparison ('==') it equals false, yielding true.
Which PDO practice most effectively prevents SQL injection when inserting user-supplied data?
  • A. Escaping the input with addslashes() before concatenating it into the query
  • B. Using prepared statements with bound parameters via placeholders ✓
  • C. Wrapping the query inside a try/catch block
  • D. Setting PDO::ATTR_ERRMODE to PDO::ERRMODE_EXCEPTION
Correct answer: B. Prepared statements with bound parameters separate SQL code from data, which is the correct defense against SQL injection.
In PHP, what is the practical difference between `require` and `include`?
  • A. require caches the file, while include re-reads it on every call
  • B. require only works for classes, while include works for any file
  • C. On failure to find the file, require raises a fatal error and halts, while include only emits a warning and continues ✓
  • D. There is no difference; they are exact aliases
Correct answer: C. A failed require produces a fatal E_COMPILE_ERROR and stops the script, whereas a failed include emits an E_WARNING and execution continues.
You want to store a user's password in the database. Which approach is correct in modern PHP?
  • A. Hash it with md5() before storing
  • B. Encrypt it with a symmetric key using openssl_encrypt()
  • C. Use password_hash() to store and password_verify() to check ✓
  • D. Store it as-is but only over an HTTPS connection
Correct answer: C. password_hash() (bcrypt/argon2 by default) with password_verify() is the standard, salted, slow-hash approach for password storage.
What does the `===` operator do that `==` does not?
  • A. It compares both value and type without type juggling ✓
  • B. It compares object references instead of object contents
  • C. It performs a case-insensitive string comparison
  • D. It automatically casts both operands to strings first
Correct answer: A. The identity operator '===' requires both the value and the type to match, avoiding the type coercion that '==' performs.
In a Composer project, what is the primary purpose of the `composer.lock` file?
  • A. It lists the minimum PHP version required to run the project
  • B. It records the exact installed versions of dependencies so installs are reproducible ✓
  • C. It stores encrypted credentials for private package repositories
  • D. It defines PSR-4 autoloading namespace mappings
Correct answer: B. composer.lock pins the exact resolved dependency versions, so `composer install` reproduces an identical dependency set across environments.
A form is submitted with `method="post"`. In the PHP script, which superglobal reliably contains the submitted field values?
  • A. $_GET
  • B. $_REQUEST only
  • C. $_POST ✓
  • D. $_SERVER
Correct answer: C. Values sent via an HTTP POST body are populated into the $_POST superglobal.
What is the correct way to iterate over an associative array while accessing both keys and values?
  • A. for ($i = 0; $i < count($arr); $i++) { echo $arr[$i]; }
  • B. foreach ($arr as $key => $value) { echo "$key: $value"; } ✓
  • C. while (list($value) = each($arr)) { echo $value; }
  • D. foreach ($arr as $value => $key) { echo "$key: $value"; }
Correct answer: B. The `foreach ($arr as $key => $value)` syntax is the standard way to access both keys and values of an associative array.
Your PHP script returns a blank white page in production but works on your machine. What is the most appropriate first step to diagnose it?
  • A. Increase memory_limit in php.ini to the maximum
  • B. Restart the web server to clear the opcode cache
  • C. Check the PHP error log (or temporarily enable display_errors in dev) to find the fatal error ✓
  • D. Switch the database from MySQL to PostgreSQL
Correct answer: C. A blank page typically means a fatal error with display_errors off; the error log reveals the actual cause, which is the correct first diagnostic step.
What does the following return: `array_map(fn($n) => $n * 2, [1, 2, 3])`?
  • A. [2, 4, 6] ✓
  • B. 12
  • C. [1, 2, 3, 2, 4, 6]
  • D. 6
Correct answer: A. array_map applies the callback to each element, returning a new array [2, 4, 6].
What is the key difference between include and require?
  • A. require is always faster
  • B. On a missing file, require raises a fatal error while include emits a warning and continues ✓
  • C. include cannot be used twice
  • D. require ignores return values
Correct answer: B. require halts execution on failure; include only warns and proceeds.
In PHP 8, the expression 0 == "abc" evaluates to:
  • A. true
  • B. false ✓
  • C. null
  • D. a TypeError
Correct answer: B. PHP 8 compares a number and non-numeric string as strings, so this is false.
PDO prepared statements primarily protect against:
  • A. Cross-site scripting
  • B. SQL injection ✓
  • C. CSRF
  • D. Session fixation
Correct answer: B. Bound parameters separate SQL from data, neutralizing injection.
Which visibility allows a property to be used by the class and its subclasses but not from outside?
  • A. public
  • B. private
  • C. protected ✓
  • D. final
Correct answer: C. protected members are accessible within the class hierarchy but not externally.
Declaring a method as static means it:
  • A. Can only be called once
  • B. Belongs to the class and can be called without an instance ✓
  • C. Cannot return a value
  • D. Is automatically thread-safe
Correct answer: B. Static methods are invoked on the class itself, needing no object instance.
Which PSR standard defines the namespace-to-directory autoloading commonly used by Composer?
  • A. PSR-1
  • B. PSR-4 ✓
  • C. PSR-7
  • D. PSR-12
Correct answer: B. PSR-4 specifies autoloading by mapping namespaces to directory paths.
What does (int)"12abc" produce in PHP?
  • A. 0
  • B. 12 ✓
  • C. A TypeError
  • D. null
Correct answer: B. Casting parses leading numeric characters, yielding 12.
The spaceship operator <=> returns:
  • A. Only true or false
  • B. -1, 0, or 1 depending on the comparison ✓
  • C. The larger of the two values
  • D. A bitwise result
Correct answer: B. It returns a signed integer indicating less-than, equal, or greater-than.
Which statement about PHP sessions is correct?
  • A. session_start() must be called after output is sent
  • B. Session data is stored client-side in a cookie by default
  • C. session_start() must be called before any output is sent ✓
  • D. Sessions cannot store arrays
Correct answer: C. session_start() sends headers, so it must run before any output.
A PHP closure captures outer-scope variables using:
  • A. the global keyword automatically
  • B. the use keyword in its definition ✓
  • C. the static keyword only
  • D. import statements
Correct answer: B. Closures inherit variables from the parent scope via the use clause.
What is the key behavioral difference between require and include?
  • A. They are identical
  • B. include is always faster
  • C. require raises a fatal error if the file is missing, while include raises only a warning ✓
  • D. include caches the file but require does not
Correct answer: C. A failed require halts the script with a fatal error; a failed include only warns and continues.
Using PDO prepared statements primarily protects against which attack?
  • A. Cross-site scripting
  • B. SQL injection ✓
  • C. CSRF
  • D. Clickjacking
Correct answer: B. Bound parameters keep user input separate from SQL code, preventing injection.
In PHP 8, what does var_dump(0 == "a") output?
  • A. true
  • B. false ✓
  • C. null
  • D. a fatal error
Correct answer: B. PHP 8 compares a number to a non-numeric string as strings, so "0" == "a" is false (changed from PHP 7).
Which visibility keyword restricts a property to access only within its own class?
  • A. public
  • B. protected
  • C. private ✓
  • D. static
Correct answer: C. private members are inaccessible from subclasses or outside code; protected allows subclass access.
What does the spaceship operator <=> return?
  • A. Boolean true or false
  • B. -1, 0, or 1 depending on the comparison ✓
  • C. The larger of the two values
  • D. Null on type mismatch
Correct answer: B. <=> returns an integer -1, 0, or 1, useful for sort comparison callbacks.
What is the standard mechanism for handling a thrown exception in PHP?
  • A. error_reporting()
  • B. A try/catch block ✓
  • C. if/else on an error code
  • D. trigger_error()
Correct answer: B. Exceptions are caught by wrapping risky code in try and handling it in catch.
What does array_map($fn, $arr) return?
  • A. The original array modified in place
  • B. A single reduced value
  • C. A new array with the callback applied to each element ✓
  • D. A boolean
Correct answer: C. array_map applies the callback to every element and returns a new array of results.
In Composer, which file pins the exact resolved versions of dependencies?
  • A. packagist.json
  • B. composer.json
  • C. composer.lock ✓
  • D. vendor/autoload.php
Correct answer: C. composer.lock records the exact installed versions so installs are reproducible.
Why is password_hash() preferred over md5() for storing passwords?
  • A. It is faster to compute
  • B. It produces shorter output
  • C. It uses a salted, slow, adaptive algorithm like bcrypt or argon2 ✓
  • D. It is reversible for recovery
Correct answer: C. password_hash() auto-salts and uses a deliberately slow adaptive algorithm, resisting brute-force attacks.
What does the nullsafe operator $obj?->method() do?
  • A. Throws if $obj is null
  • B. Calls the method twice
  • C. Returns null instead of erroring when $obj is null ✓
  • D. Casts $obj to boolean
Correct answer: C. The nullsafe operator short-circuits to null if the left operand is null instead of raising an error.

Hard round 30 questions

A worker process ingests a 4 GB CSV row-by-row and its RSS climbs steadily even though each row is processed and discarded. The code builds an intermediate object graph where a parent node holds children and each child holds a `$parent` back-reference. `unset()` on the parent at the end of each loop does not reclaim memory. What is the most accurate explanation and fix?
  • A. The reference count never reaches zero because of the parent-child cycle, so only PHP's cyclic GC frees it; call gc_collect_cycles() periodically or break the back-reference before unset ✓
  • B. unset() is asynchronous in CLI SAPI, so memory is freed only at request shutdown; switch to FPM to force immediate release
  • C. The strings are interned in the Zend string table permanently; disable string interning via opcache to free them
  • D. Copy-on-write duplicated each row into a new zval that PHP cannot track; add & to the foreach to force a reference and avoid the copy
Correct answer: A. Circular references keep refcounts above zero so simple refcounting can't free them; only the cyclic collector (or manually breaking the cycle) reclaims the memory.
Given `$result = true and false; var_dump($result);` — what is printed and why?
  • A. bool(false), because 'and' evaluates both operands before assigning
  • B. bool(true), because '=' has higher precedence than 'and', so $result is assigned true first ✓
  • C. bool(true), because 'and' short-circuits on the truthy left operand
  • D. NULL, because mixing 'and' with '=' is a parse error that yields null
Correct answer: B. '=' binds tighter than the low-precedence 'and', so PHP parses it as `($result = true) and false`, assigning true to $result.
Two traits `A` and `B` both define `public function log()`. A class uses both: `use A, B;` with no conflict-resolution block. What happens?
  • A. A fatal error is raised at compile time due to the unresolved method collision unless you use insteadof/as ✓
  • B. B::log() silently wins because the later trait in the use list takes precedence
  • C. A::log() silently wins because traits are applied left-to-right and the first binding is kept
  • D. Both methods coexist and PHP dispatches based on the argument signature (overloading)
Correct answer: A. An unresolved trait method collision is a fatal error; you must disambiguate explicitly with `insteadof` and optionally alias with `as`.
A base class has `public static function create(): static { return new static(); }` and `self` is used elsewhere. A subclass `Admin extends User` calls `Admin::create()`. Which statement about late static binding is correct here?
  • A. Because `new static()` uses the runtime-resolved called class, it returns an Admin instance; `new self()` would have returned a User instance ✓
  • B. Both `static` and `self` resolve to Admin because static methods always bind to the calling class
  • C. `new static()` returns a User instance because static binding is resolved at compile time in the defining class
  • D. The call fails because `static` cannot be used as a return type in a factory method
Correct answer: A. Late static binding makes `new static()` use the runtime-called class (Admin), whereas `self` is bound at definition time to User.
You need to stream 10 million rows from a query result, transforming each, without loading them all into memory, AND you must be able to pause/resume the producer cooperatively from a scheduler that also drives network I/O. Which primitive combination is the best fit in PHP 8.1+?
  • A. A Generator for lazy row production, driven by a Fiber so the scheduler can suspend it during I/O waits ✓
  • B. A single Fiber that returns an array of all 10M transformed rows at the end
  • C. An ArrayObject wrapping the full result set with an SplHeap for ordering
  • D. pcntl_fork() one child per row and join them via SplQueue
Correct answer: A. Generators give lazy, memory-efficient iteration while Fibers add the cooperative suspend/resume needed for a scheduler juggling I/O, so combining them fits both constraints.
An API endpoint decrements stock: `SELECT qty FROM items WHERE id=?` then `UPDATE items SET qty=qty-1 WHERE id=?` in a transaction under READ COMMITTED. Under high concurrency stock occasionally goes negative. Which fix most directly eliminates the race with minimal contention?
  • A. Use `SELECT ... FOR UPDATE` on the row inside the transaction, or make the UPDATE conditional with `WHERE qty > 0` and check affected rows ✓
  • B. Switch the isolation level to READ UNCOMMITTED so readers see the latest uncommitted decrement
  • C. Wrap both statements in a PHP-level flock() on a lock file shared across web servers
  • D. Add an index on qty so the UPDATE locks fewer rows
Correct answer: A. Row-level pessimistic locking with FOR UPDATE (or an atomic conditional UPDATE guarded by affected-row count) closes the check-then-act gap that lets qty go negative.
After migrating a codebase to PHP 8, a previously reliable check `if (strpos($haystack, $needle))` starts treating some matches as misses and, in another spot, `"0" == "0.0"` changed behavior. Which pair of PHP 8 changes explains these?
  • A. strpos returning 0 for a front-of-string match was always falsy (a long-standing bug in the code), and in PHP 8 two numeric strings like "0" and "0.0" compare equal with == because both are numeric ✓
  • B. strpos now returns false instead of 0 for position 0, and "0"=="0.0" now compares as strings and is false
  • C. strpos now throws a TypeError on non-string needles, and numeric-string == comparison was removed in PHP 8
  • D. strpos now returns null on no match, and == now always does strict comparison
Correct answer: A. The strpos-at-0 falsy bug predates PHP 8, while PHP 8's comparison change makes number-vs-string use string context only when the string is non-numeric — "0" and "0.0" are both numeric so they compare numerically and are equal.
You pass an object into a function and also an array: `function f($obj, $arr){ $obj->x = 1; $arr[] = 9; }` called as `f($o, $a);`. After the call, what is true about `$o` and `$a`?
  • A. $o->x is 1 (the object handle was copied but points to the same instance), and $a is unchanged (arrays are passed by value) ✓
  • B. Both $o and $a reflect the mutations because everything in PHP is passed by reference
  • C. Neither reflects the mutation because objects and arrays are both copied on pass
  • D. $a gains element 9 but $o->x is unchanged because objects are deep-copied on call
Correct answer: A. PHP passes an object's handle by value so the same underlying instance is mutated, while arrays are true value types (copy-on-write) so appends inside the function don't affect the caller's array.
Under OPcache with `opcache.jit=tracing` enabled, a request-heavy JSON API sees almost no speedup after enabling JIT, while a Mandelbrot-style CPU loop got ~4x. What is the most accurate reason?
  • A. Typical web request workloads are dominated by I/O and short-lived function calls, so JIT (which mainly accelerates long CPU-bound arithmetic loops) yields little benefit; opcode caching already removed the compile cost ✓
  • B. JIT only activates when opcache.jit_buffer_size is 0, so the API's non-zero buffer disabled it
  • C. JIT cannot compile code that uses arrays, so the JSON API fell back to the interpreter
  • D. JIT requires preloading via opcache.preload; without it the tracing JIT never fires for any workload
Correct answer: A. JIT primarily helps CPU-bound numeric loops; I/O-bound request code gains little because opcode caching already eliminated recompilation and the hot path isn't arithmetic.
A Laravel endpoint renders 50 posts and their authors' names via `$posts = Post::all(); foreach($posts as $p){ echo $p->author->name; }`. The DB log shows 51 queries. Which change fixes the N+1 problem while keeping one query per relation?
  • A. Use eager loading: `Post::with('author')->get()`, which issues one query for posts and one WHERE IN query for all authors ✓
  • B. Add `->lazy()` to the query so relations are resolved in a single JOIN automatically
  • C. Wrap the loop in a transaction so the 50 author queries are batched into one round trip
  • D. Enable query result caching so the 50 author queries are served from cache on first request
Correct answer: A. Eager loading with `with('author')` collects the foreign keys and fetches all authors in one WHERE IN query, turning 51 queries into 2.
What does the yield keyword do inside a PHP function?
  • A. Immediately returns a full array
  • B. Turns the function into a generator that produces values lazily ✓
  • C. Pauses the entire script
  • D. Throws an exception
Correct answer: B. yield makes the function a generator, producing values one at a time on demand.
How are objects passed to functions in PHP?
  • A. By a full deep copy every time
  • B. By a handle/identifier, so the same instance is modified unless cloned ✓
  • C. Strictly by reference, including the variable binding itself
  • D. Objects cannot be passed to functions
Correct answer: B. PHP passes an object handle by value; both variables reference the same instance.
What is the effect of the __invoke() magic method?
  • A. It runs when an undefined method is accessed
  • B. It lets an object be called as if it were a function ✓
  • C. It executes during serialization
  • D. It intercepts property writes
Correct answer: B. __invoke() is triggered when an object is used with call syntax like $obj().
Regarding PHP's copy-on-write behavior for arrays:
  • A. Arrays are deep-copied immediately on assignment
  • B. An assigned array shares memory until one copy is modified, then it is duplicated ✓
  • C. Arrays are never copied, always referenced
  • D. Copy-on-write applies only to objects
Correct answer: B. PHP defers array duplication until a write actually diverges the copies.
What distinguishes __get() from __set()?
  • A. __get intercepts writes; __set intercepts reads
  • B. __get intercepts reads of inaccessible properties; __set intercepts writes to them ✓
  • C. Both intercept method calls
  • D. They only handle static properties
Correct answer: B. __get handles reads and __set handles writes of inaccessible/undefined properties.
In PHP 8, named arguments allow you to:
  • A. Pass arguments by parameter name, skipping optional ones by position ✓
  • B. Rename a function at call time
  • C. Declare variadic arguments
  • D. Type-hint arguments inline
Correct answer: A. Named arguments bind values to parameter names, letting you skip defaults.
What is the primary risk of comparing a user-supplied hash with a stored one using ==?
  • A. It is slightly slower than ===
  • B. Type juggling and non-constant-time comparison enable attacks; use hash_equals() ✓
  • C. It always returns true
  • D. It cannot compare strings
Correct answer: B. == can juggle types and leak timing, so hash_equals() is the safe choice.
Under OPcache, what is cached?
  • A. The rendered HTML output
  • B. Precompiled bytecode (opcodes) of PHP scripts ✓
  • C. Database query results
  • D. Session data
Correct answer: B. OPcache stores compiled opcodes in memory to skip recompilation on each request.
What does Late Static Binding (static::) resolve to?
  • A. The class where the method is defined
  • B. The class actually called at runtime ✓
  • C. Always the parent class
  • D. The first class declared in the file
Correct answer: B. static:: references the runtime-called class rather than the defining class.
When a trait method and a method defined in the class itself share a name:
  • A. A fatal conflict error is thrown
  • B. The class's own method overrides the trait method ✓
  • C. The trait method always wins
  • D. Both run in sequence
Correct answer: B. The class's own definition takes precedence over inherited trait methods.
How are objects passed to functions in PHP by default?
  • A. By a full deep copy
  • B. By a handle that references the same object instance ✓
  • C. By value with copy-on-write in every case
  • D. As serialized strings
Correct answer: B. PHP copies the object handle, so both variables point to the same instance and property changes are shared.
What does the yield keyword create in PHP?
  • A. A coroutine running in parallel
  • B. A generator that produces values lazily ✓
  • C. A cached array
  • D. A closure bound to $this
Correct answer: B. yield turns a function into a generator that yields values on demand without building the full array in memory.
What is the difference between the __get and __call magic methods?
  • A. They are aliases for each other
  • B. __get intercepts reads of inaccessible properties while __call intercepts calls to inaccessible methods ✓
  • C. __get is static-only and __call is instance-only
  • D. __get runs at object construction time
Correct answer: B. __get overloads property access and __call overloads method invocation for members that are missing or inaccessible.
In the Zend engine, what does copy-on-write optimize?
  • A. It delays copying a variable's value until it is actually modified ✓
  • B. It compiles opcodes to native machine code
  • C. It caches database query results
  • D. It reuses HTTP keep-alive connections
Correct answer: A. Copy-on-write lets multiple variables share one zval until a write occurs, saving memory and copies.
What is the effect of placing declare(strict_types=1) at the top of a file?
  • A. Enforces strict scalar type checks for that file's function calls ✓
  • B. Enables strict error reporting globally
  • C. Makes all variables immutable
  • D. Forces UTF-8 source encoding
Correct answer: A. In strict mode PHP rejects mismatched scalar argument/return types instead of silently coercing them, per file.
How do array_merge() and the + array-union operator differ on integer keys?
  • A. Both throw on duplicate keys
  • B. array_merge renumbers integer keys while + preserves the left array's keys ✓
  • C. + renumbers integer keys while array_merge preserves them
  • D. They behave identically
Correct answer: B. array_merge reindexes numeric keys sequentially, whereas + keeps the left operand's keys and ignores duplicate keys from the right.
What does late static binding (static::) provide?
  • A. It resolves the called class at runtime rather than the class where the method is defined ✓
  • B. It binds a static variable to global scope
  • C. It delays class autoloading until first use
  • D. It caches static method return values
Correct answer: A. static:: references the runtime-called class, unlike self:: which binds to the defining class.
In PHP-FPM, what does the pm = dynamic setting control?
  • A. Which PHP version executes
  • B. How child worker processes are spawned and scaled ✓
  • C. The OPcache memory size
  • D. The database connection pool size
Correct answer: B. The process manager mode governs how FPM creates and scales worker children under load.
What is the main function of OPcache?
  • A. Caching rendered HTTP responses
  • B. Pooling database connections
  • C. Storing precompiled script bytecode in shared memory to skip recompilation ✓
  • D. Minifying HTML output
Correct answer: C. OPcache keeps compiled opcodes in shared memory so scripts need not be re-parsed and re-compiled each request.
What is a named argument, introduced in PHP 8?
  • A. A variable variable such as $$x
  • B. Passing arguments by parameter name so that preceding defaults can be skipped ✓
  • C. A typed class constant
  • D. An attribute annotation
Correct answer: B. Named arguments let you pass values by parameter name in any order and omit optional parameters that have defaults.

Prep for another role

Questions are original, written and independently verified for HireHire's role interview quizzes. They reflect the kind of knowledge PHP Developer interviews test, not any specific company's questions. HireHire maps live tech & IT jobs across India, updated regularly. Last updated: August 2026.