skip to content

PHP

1 roadmap434 questionsupdated

PHP 8 is a gradually typed language with enums, readonly properties, attributes and fibers, run per request under a share-nothing model. Interviewers test whether your PHP is post-8.0.

on this pageshow

guide

overview

~2 min

PHP interviews open by finding out which PHP you write. Someone who learned the language before 8.0 answers questions on equality, types and failure in ways that are now wrong or only half right, so expect the first minutes on loose versus strict comparison, how a declared scalar parameter treats a value of the wrong type, and why an `Error` is not an `Exception`. The object model comes next — constructor promotion, readonly and hooked properties, traits, late static binding, enums — because that is the part the 8.x releases reshaped most. Almost every PHP program answers HTTP requests, so interviewers then move to the request itself and to the habits that keep it safe: escaping output, binding query parameters, hashing passwords. Senior rounds ask where the code actually runs: what the per-request lifecycle means for state, what OPcache and the JIT change, and what breaks when an application moves into a long-running worker. The hub follows those seams. The language core is [Statements & Expressions](/topics/lang-php-syntax), [Scalar & Compound Types](/topics/lang-php-types-syntax), [Array Operations](/topics/lang-php-arrays-strings), [Text Processing](/topics/lang-php-text), [Functions & Callables](/topics/lang-php-functions) and [Object-Oriented PHP](/topics/lang-php-oop), with [Errors & Exceptions](/topics/lang-php-error-handling), [Code Organization](/topics/lang-php-namespaces) and [Code Metadata & Introspection](/topics/lang-php-metaprogramming) beside it. The web layer is [Serving HTTP Requests](/topics/lang-php-request-handling), [Secure Coding](/topics/lang-php-security) and [Database Access](/topics/lang-php-database). Reaching outside the process is [Files & Streams](/topics/lang-php-files), [Data Formats](/topics/lang-php-formats), [Outbound HTTP](/topics/lang-php-http-clients) and [Host OS Interaction](/topics/lang-php-system). The runtime layer is [Engine & Runtime Setup](/topics/lang-php-runtime), [Concurrency Options](/topics/lang-php-concurrency), [Speed & Footprint](/topics/lang-php-performance) and the [Standard Library Extras](/topics/lang-php-stdlib), and [PHP-FIG Standards](/topics/lang-php-standards) covers the shared interfaces that let libraries from different authors fit together. Learn it roughly in that order. Syntax and types come first, since comparison and coercion rules decide many questions that look as if they are about something else. Arrays next: they carry nearly all PHP data, and their key handling surprises anyone used to separate list and map types. Then functions and objects, the bulk of framework code. Read the runtime section early rather than last — the lifecycle explains sessions, caching and every worker-mode question. Security, databases and the standards weigh most in backend roles, which is where most PHP work is.

primer

### Each request is a whole program run Under PHP-FPM or an Apache module, every HTTP request starts from empty application state: the script is loaded, runs, answers, and everything it built is discarded. Much of the language's behaviour follows from that. Anything that must outlive a request belongs in a session store, a database or a cache; a request that leaks memory or leaves state half-built rarely affects the next one; and OPcache matters because without it the compile step would repeat on every hit. Worker runtimes give up this model on purpose to save the bootstrap cost, and senior questions test whether you know what they give up with it. ### Two regimes in one type system PHP is dynamically typed, with declarations layered on top. In the default coercive mode a declared scalar parameter converts a compatible value; `declare(strict_types=1)` in the calling file turns that conversion off. Comparison has the same split: `==` converts before it compares, `===` does not. PHP 8.0 made string-to-number comparison far less surprising, but it did not remove loose comparison, and several constructs still use it by default. Knowing which rule a given construct applies is half of many answers. ### One array type does every job List, dictionary, set, stack and record are all the same ordered map, keyed by integers or strings. Some helpers keep keys and some renumber them, and that choice sits behind most array bugs. Arrays and strings are values that copy lazily when written; objects are handles, so two variables can refer to one object and `clone` is needed for a separate one. ### Strings are bytes A PHP string carries no encoding. The classic string functions work on bytes, which is correct for ASCII and wrong for most of the world's text; the multibyte extension and the Unicode mode of PCRE work on characters. ### Failure has two histories Older PHP reported problems as warnings and notices, or by returning `false`; PHP 7 introduced the `Throwable` tree and PHP 8 moved many more engine and internal-function failures onto it. Both models are still live: some functions throw, some return a sentinel, a few set a last-error value. Answers are judged on whether you check failure the way that particular API reports it. ### Modern PHP says in syntax what it once said in convention Enums, readonly properties, constructor promotion, attributes and property hooks replaced class constants, docblock annotations, magic methods and hand-written boilerplate with constructs the engine checks. First-class callables did the same for callbacks written as strings and arrays. Interviewers use them to date your knowledge, and a design answer built on `__get` or on `@annotations` in comments reads as pre-8. ### The ecosystem is held together by interfaces Composer installs packages and generates the autoloader; namespaces map onto directories by the PSR-4 convention; PHP-FIG publishes the interfaces for HTTP messages, logging, caching and containers that frameworks agree on. Much of professional PHP is choosing the interface to depend on rather than the library behind it.

Type juggling
PHP's automatic conversion of a value to the type an operator or context expects, such as a numeric string used in arithmetic or any value tested in an if.
Strict types
A per-file declare directive that makes scalar type declarations reject values of the wrong type instead of converting them; for arguments, the calling file's mode decides.
DNF type
Disjunctive normal form: a type declaration that combines unions of intersection types, such as an intersection in parentheses joined to null with a vertical bar.
Copy-on-write
The engine's lazy copying of arrays and strings: an assignment shares the underlying value, and a real copy is made only when one side is modified.
Superglobal
One of PHP's built-in arrays, such as $_GET, $_POST, $_SERVER or $_SESSION, visible in every scope without a global statement.
SAPI
Server API: the layer that connects the engine to its host, such as PHP-FPM, the Apache module, the CLI or the built-in development server.
OPcache
The bundled extension that keeps compiled opcodes in shared memory so later requests skip parsing and compiling; it is also where the JIT lives.
Constructor promotion
PHP 8.0 syntax that declares and assigns a property directly from a constructor parameter marked with a visibility, removing the repeated field-and-assignment boilerplate.
Readonly property
A typed property that can be initialised once and never changed afterwards; a readonly class applies it to every property it declares.
Property hook
PHP 8.4 get and set logic attached to a property declaration itself, replacing hand-written accessor methods and many uses of magic methods.
Backed enum
An enumeration whose cases each carry a unique int or string value, with from and tryFrom to map stored values back to cases.
Trait
A reusable block of methods and properties copied into a class at compile time; PHP's answer to sharing code across single-inheritance hierarchies.
Late static binding
Resolving static:: to the class a call was made on at run time, rather than to the class where the method was written.
Attribute
Structured metadata written with #[...] on a class, method, property, parameter or constant, readable through Reflection; frameworks use it for routing, validation and wiring.
Autoloader
A callback registered with the engine that loads a class's file the first time an undefined class name is used; Composer generates one from namespace-to-directory rules.
Throwable
The interface at the root of everything PHP can throw, with two branches: Error for engine-detected faults and Exception for failures code reports.
Fiber
A PHP 8.1 primitive for pausing a call stack and resuming it later, on the same thread; the building block event-loop libraries use for asynchronous code.
PSR
PHP Standard Recommendation: an interface or convention published by PHP-FIG, such as autoloading, HTTP messages or logging, that independent libraries implement.

The sections stack. Syntax, types and arrays define what a value is and how two values compare; almost every later answer leans on them. Functions and objects build on that core — closures decide what they capture, classes decide what is mutable and what is inherited — and [Code Organization](/topics/lang-php-namespaces) with [Code Metadata & Introspection](/topics/lang-php-metaprogramming) explains how a framework finds, loads and wires those classes without being told about each one. Errors cut across all of it, because each layer reports failure in its own dialect. The web layer then applies the core to one HTTP exchange. [Serving HTTP Requests](/topics/lang-php-request-handling) is where untrusted data enters, [Secure Coding](/topics/lang-php-security) is where it is checked on the way in and escaped on the way out, and [Database Access](/topics/lang-php-database) is where it must never become query text. [Data Formats](/topics/lang-php-formats), [Files & Streams](/topics/lang-php-files), [Outbound HTTP](/topics/lang-php-http-clients) and [Host OS Interaction](/topics/lang-php-system) are the same concern at other boundaries: input you did not write, failures you did not cause, and memory that grows with the size of what you read. Underneath sits the runtime. [Engine & Runtime Setup](/topics/lang-php-runtime) explains the lifecycle every other section silently assumes; [Speed & Footprint](/topics/lang-php-performance) explains what that lifecycle costs; [Concurrency Options](/topics/lang-php-concurrency) is what you reach for when one request at a time on one thread is not enough. The standards section closes the loop: its interfaces are how frameworks agree on requests, responses, logs and containers, so they sit on top of everything else. A small example where several core ideas meet: ```php <?php declare(strict_types=1); enum Status: string { case Draft = 'draft'; case Paid = 'paid'; } final class Invoice { public function __construct( public readonly int $cents, public readonly Status $status = Status::Draft, ) {} } function label(Invoice $i): string { return match ($i->status) { Status::Draft => 'draft', Status::Paid => sprintf('paid %.2f', $i->cents / 100), }; } ``` Promotion declares both properties in the constructor signature; `readonly` means an invoice cannot be edited after it is built, only replaced; the backed enum maps cleanly to a database column; and `match` compares strictly and fails loudly on a case it does not handle, where a `switch` compares loosely and quietly does nothing. With strict types on, passing `'1999'` for the amount from this file throws instead of converting.

  1. Statements & Expressions →

    Tags, scope, operators and control flow; the loose-versus-strict comparison rules introduced here reappear in nearly every later section.

  2. Scalar & Compound Types →

    Coercive and strict modes, union and nullable declarations, and float precision: the rules that decide what a function actually receives.

  3. Array Operations →

    The ordered map behind every array, the helpers that keep or renumber keys, and sorting; most PHP data passes through it.

  4. Functions & Callables →

    Parameters, named arguments, closure capture and generators: how values move into and out of the code you write.

  5. Object-Oriented PHP →

    The largest section and the one that dates your PHP: promotion, readonly, traits, late static binding, enums and property hooks.

  6. Engine & Runtime Setup →

    With the language in hand, learn where it runs: the per-request lifecycle, SAPIs and php.ini explain state, caching and deployment answers.

  • Answering with pre-8.0 behaviour: string-to-number comparison, internal-function errors and several warnings changed in 8.0, and interviewers notice an answer that is out of date.

  • Testing the result of a search or validation function with a plain if: a valid 0 or empty string is falsy, so compare against false with !== or ===.

  • Assuming declare(strict_types=1) applies globally: argument checks follow the mode of the calling file, so a strict library still coerces when called from non-strict code.

  • Expecting array helpers to preserve keys, or to renumber them, without checking: the behaviour differs between functions and between integer and string keys.

  • Measuring or slicing user text with byte functions: anything beyond ASCII needs the multibyte functions, or lengths and cuts land mid-character.

  • Catching Exception and believing every failure is covered: engine faults such as type errors sit on the Error branch and pass straight through.

  • Escaping input on the way in instead of output on the way out: escaping belongs to the context the value is written into, HTML, SQL or shell.

  • Keeping request data in a static property or singleton and then moving to a long-running worker: the next request on that process inherits it.

  • Calling unserialize() on data a client can control: it can instantiate arbitrary classes and trigger their magic methods, so untrusted input should travel as JSON.

  • Reaching for Fibers to make CPU-bound work faster: they interleave on one thread, so they help only when an event loop overlaps time spent waiting on I/O.

This guide assumes PHP 8.4 or 8.5; answers that depend on a newer release say so. PHP's history matters in interviews because code written for 5.x and 7.x is still in production and the idioms differ sharply: - **7.0** — scalar parameter and return declarations with the `strict_types` directive, and the `Throwable` hierarchy with `Error` alongside `Exception`. - **7.4** — typed properties and arrow functions. - **8.0** — constructor promotion, `match`, the nullsafe operator, union types, attributes, named arguments and the JIT; saner string-to-number comparison. - **8.1** — enums, readonly properties, Fibers, first-class callable syntax. - **8.2** — readonly classes and DNF types; dynamic properties deprecated. - **8.3** — type declarations on class constants, and the `#[\Override]` attribute. - **8.4** — property hooks and asymmetric visibility. - **8.5** — the pipe operator and clone-with. The shift interviewers probe most is what a class looks like before and after 8.0: ```php // 7.x class Money { private $cents; public function __construct($cents) { $this->cents = $cents; } public function getCents() { return $this->cents; } } // 8.1 onward final class Money { public function __construct(public readonly int $cents) {} } ``` The same idea in a fraction of the code, and the engine now enforces the type and the immutability that the older version only promised in its method names.

PHP is maintained by its open-source community, and the language is steered through a public RFC vote. In practice a candidate is expected to place it in four settings. **Frameworks.** Most application work happens inside Laravel or Symfony, both built on Composer packages and PHP-FIG interfaces; WordPress and other content systems account for a large share of PHP running on the web, with their own older conventions. **Package management.** Composer is the standard: it resolves dependencies and generates the autoloader, so a question about loading classes usually expects a Composer answer. **Serving.** The classic deployment is nginx in front of PHP-FPM; FrankenPHP, RoadRunner and Swoole instead keep the application booted in long-running workers, trading the per-request clean slate for speed. **Quality tooling.** PHPUnit for tests, and static analysers such as PHPStan and Psalm that check types the engine only enforces at run time. The comparison that comes up most is with Node.js, Python and Ruby for web backends. A fair answer names what separates PHP: request isolation by default instead of one long-lived process, a standard library aimed squarely at the web, and deep roots in hosting and content platforms. The trade-off is that concurrency and long-running work need a different runtime model from the one PHP starts with.

explore

report an issue with this guide →

questions

434 · 21 sections

In PHP, how do you find which php.ini file is actually loaded, and why might editing php.ini seem to change nothing?

level: juniorimportance: must knowfreq 58%
basics
~20 s

Run php --ini for the CLI, or call php_ini_loaded_file() or phpinfo() from a web page, since each SAPI may load a different file. php.ini is read at startup, so PHP-FPM or Apache must be restarted after an edit.

open as a page

In PHP, why does a page-view counter kept in a static variable reset on every request to a website?

level: juniorimportance: must knowfreq 72%
basics
~20 s

PHP runs every web request share-nothing: variables, statics, globals and objects are created for that request and freed when it ends. A static counter starts from its initial value on each page view, so real counts need an external store.

open as a page

On a PHP photo-contest site on a shared host, why does ini_set('upload_max_filesize', '20M') fail to raise the upload limit?

level: middleimportance: must knowfreq 52%
basics
~20 s

upload_max_filesize is changeable only at INI_PERDIR or INI_SYSTEM level, so ini_set() from a script refuses it and returns false. The upload is also parsed before the script runs. Set it in php.ini, .user.ini or .htaccess instead.

open as a page

Which headline language features did each PHP release from 8.0 to 8.5 introduce?

level: middleimportance: must knowfreq 62%
basics
~20 s

8.0: named arguments, attributes, union types, match, nullsafe, promotion, JIT. 8.1: enums, readonly, fibers, first-class callables. 8.2: readonly classes, DNF types. 8.3: typed class constants, #[\Override]. 8.4: property hooks, asymmetric visibility. 8.5: pipe operator, clone-with.

open as a page

When upgrading a ten-year-old PHP 7.4 invoicing application to PHP 8.5, which changes are most likely to break it, and how do you sequence the work?

level: seniorimportance: must knowfreq 55%
basics
~20 s

Most breakage comes from 8.0: 0 == "" is false, many warnings became TypeError, count(null) throws, PDO throws by default. Then come later deprecations. Add tests, fix on 7.4, run 8.x in CI, walk the migration guides, then switch.

open as a page

In PHP 8, what are the differences between a switch statement and a match expression?

level: juniorimportance: must knowfreq 74%
basics
~20 s

switch is a statement that compares loosely (==) and falls through until a break. match, since PHP 8.0, is an expression that compares strictly (===), never falls through, returns a value and throws UnhandledMatchError when nothing matches.

open as a page

In PHP 8, what is the difference between the == and === operators, and why do most codebases default to ===?

level: juniorimportance: must knowfreq 88%
basics
~20 s

== compares values after type juggling, so an int and a string can be equal; === is true only when type and value both match. Loose rules still surprise after PHP 8.0, so === is the safe default.

open as a page

In PHP, what are the differences between echo and print, and why is neither of them a function?

level: juniorimportance: must knowfreq 62%
basics
~10 s

Both output strings and are language constructs, not functions. echo accepts several comma-separated arguments and returns nothing; print accepts one argument and always returns 1, so it can appear inside an expression.

open as a page

Why do PHP style guides say to omit the closing ?> tag in files that contain only PHP code?

level: juniorimportance: must knowfreq 55%
basics
~20 s

Anything after a closing ?> is output, and PHP swallows only the one newline right after the tag. A stray blank line in an included class file then corrupts responses or blocks later headers; omitting ?> removes the risk.

open as a page

In PHP, why can't a helper function read a config variable defined at the top of the script, and how should it get the value?

level: juniorimportance: must knowfreq 58%
basics
~20 s

PHP has function scope and global scope, and a function sees only its own variables, so an outer $config is undefined inside it. Pass the value as a parameter; global and $GLOBALS work but hide the dependency.

open as a page

In PHP, what does a nullable type such as ?Customer mean, and is it the same as Customer|null or an optional parameter?

level: juniorimportance: must knowfreq 62%
basics
~20 s

?Customer accepts a Customer object or null, and is exactly the same type as Customer|null. Nullable does not mean optional: the argument must still be passed unless the parameter also has a default, written ?Customer $c = null.

open as a page

In PHP, what does declare(strict_types=1) change about how scalar parameter and return type declarations are checked?

level: juniorimportance: must knowfreq 74%
basics
~20 s

By default PHP coerces a wrong-typed scalar into the declared type when it can, so "12" passed to an int parameter becomes 12. With declare(strict_types=1) the value must already match, or a TypeError is thrown; only int-to-float widening survives.

open as a page

In PHP, which values convert to false in a boolean context, and why does the string '0' cause bugs?

level: juniorimportance: must knowfreq 58%
basics
~20 s

false, 0, 0.0, -0.0, '', '0', an empty array and null are falsy; everything else is true. '0' is the trap: a real value such as a zero quantity or the name '0' fails an if check.

open as a page

In PHP, what does an (int) cast return for strings such as '42', ' 42 ', '42abc', '1e3', '0x1A' and 'abc'?

level: juniorimportance: must knowfreq 64%
basics
~20 s

(int) takes the leading numeric part of a string and never fails: '42', ' 42 ' and '42abc' give 42, '1e3' gives 1000, while '0x1A' and 'abc' give 0. No warning is raised for the leading-numeric or non-numeric cases.

open as a page

In PHP, why is 0.1 + 0.2 == 0.3 false, and how should you compare two floats?

level: juniorimportance: must knowfreq 64%
basics
~20 s

PHP floats are IEEE 754 binary doubles, and 0.1, 0.2 and 0.3 have no exact binary form, so the sum is 0.30000000000000004. Compare floats with a tolerance, abs($a - $b) < $epsilon, or avoid floats where exact decimals matter.

open as a page

In PHP 8.5, which values count as a callable, and which older callable forms are deprecated?

level: juniorimportance: must knowfreq 55%
basics
~20 s

A PHP callable is a function-name string, a 'Class::method' string, an [object or class, 'method'] array, a Closure, or an invokable object. Since PHP 8.2, relative forms such as 'self::method' or ['parent', 'method'] are deprecated.

open as a page

In PHP, how does an anonymous function reach variables of the enclosing scope through use, and what changes with use (&$x)?

level: juniorimportance: must knowfreq 66%
basics
~20 s

A function () closure sees no outer variables unless listed in use. use ($x) copies the value when the closure is created; use (&$x) binds the variable itself, so later changes flow both ways between closure and outer scope.

open as a page

In PHP, what does calling a function that contains yield return, and when does the code in its body actually run?

level: juniorimportance: must knowfreq 55%
basics
~20 s

A function containing yield returns a Generator object when called, without running its body. Each foreach pull runs the body to the next yield, which hands out a value and pauses with the locals intact.

open as a page

In PHP, how do default parameter values work, and what happens when an optional parameter is declared before a required one?

level: juniorimportance: must knowfreq 62%
basics
~20 s

A default applies only when the caller omits that argument; an explicit null is passed as null. Defaults must be constant expressions. An optional parameter declared before a required one is deprecated since PHP 8.0 and treated as required.

open as a page

In PHP, how do fn arrow functions capture outer variables compared with function () use (), and what can an arrow function not do?

level: middleimportance: must knowfreq 56%
basics
~20 s

An fn arrow function (PHP 7.4+) is a one-expression closure that captures every outer variable its body uses, automatically and by value. It has no use clause, so it cannot write to outer variables or contain statements.

open as a page

In PHP, how do you destructure an array into separate variables with [] or list(), both by position and by key?

level: juniorimportance: must knowfreq 55%
basics
~20 s

Put an array pattern on the left of =: [$lat, $lng] = $point copies the elements at keys 0 and 1, and ['lat' => $lat] = $point copies by key. list() is the older spelling of the same construct.

open as a page

In PHP, what is the difference between array_merge() and the + union operator when both arrays share keys?

level: juniorimportance: must knowfreq 68%
basics
~10 s

array_merge() lets later arrays overwrite earlier ones for string keys but appends and renumbers integer keys; $a + $b keeps every key of $a, adds only keys missing from $a, and never renumbers.

open as a page

In PHP, if you assign an array to another variable or pass it to a function and modify that copy, what happens to the original?

level: juniorimportance: must knowfreq 58%
basics
~20 s

Nothing: PHP arrays are values, so assignment and by-value parameters give an independent copy, and changing it leaves the original intact. Objects stored inside are handles, so both copies still point to the same objects.

open as a page

In PHP, what does it mean that an array is an ordered map, and how do indexed and associative arrays differ?

level: juniorimportance: must knowfreq 72%
basics
~20 s

A PHP array is one ordered map from int or string keys to values of any type. Indexed and associative arrays are the same type: an indexed array just has keys 0, 1, 2, and every array keeps insertion order.

open as a page

In PHP, what is the difference between sort(), asort() and ksort(), and which of them keep an array's keys?

level: juniorimportance: must knowfreq 70%
basics
~10 s

sort() orders the values and renumbers the keys 0, 1, 2; asort() orders the values but keeps each key with its value; ksort() orders by key. All three sort in place and return true.

open as a page

In PHP, how do explode(), implode() and trim() behave when you split a comma-separated list of invoice codes, and which edge cases bite?

level: juniorimportance: must knowfreq 62%
basics
~20 s

explode(',', $s) splits on a separator and returns an array, implode(',', $parts) joins it back, and trim() strips whitespace. Traps: an empty string explodes to [''], an empty separator throws ValueError, and trim's second argument is a set of characters.

open as a page

In PHP, why is if (strpos($code, 'INV')) a bug, and how should you test whether a string contains a substring?

level: juniorimportance: must knowfreq 80%
basics
~20 s

strpos() returns the byte offset of the first match or false, and a match at offset 0 is falsy, so a plain if treats it as not found. Compare with !== false, or call str_contains(), added in PHP 8.0.

open as a page

In PHP, why does strlen('日本語') return 9, and how do you count the characters of a UTF-8 string instead?

level: juniorimportance: must knowfreq 72%
basics
~20 s

A PHP string is a sequence of bytes with no encoding attached, and strlen() counts bytes; each of those three kanji takes three bytes in UTF-8. mb_strlen($s, 'UTF-8') decodes the bytes and counts characters, returning 3.

open as a page

In PHP, what is the difference between single-quoted and double-quoted strings?

level: juniorimportance: must knowfreq 75%
basics
~10 s

Single-quoted strings are literal: only ' and \ are escapes and variables are not expanded. Double-quoted strings interpret escape sequences such as \n, \t and \u{...} and interpolate variables like $name.

open as a page

In PHP, why does a preg_* pattern need delimiters such as /…/ or #…#, and what do the i, u, x and s modifiers change?

level: juniorimportance: must knowfreq 55%
basics
~20 s

Delimiters mark where a PHP pattern ends so modifiers can follow, as in '/ord-\d+/i'. i ignores case, u treats pattern and subject as UTF-8, x ignores pattern whitespace and allows comments, and s lets the dot match newlines.

open as a page

In PHP, what is __construct, when does it run, and what does PHP 8 no longer treat as a constructor?

level: juniorimportance: must knowfreq 65%
basics
~20 s

__construct is the method new calls on every freshly created object, receiving the arguments written after the class name. A class has at most one. Since PHP 8.0 a method named after the class is no longer a constructor.

open as a page

In PHP 8.1 and later, why use an enum instead of class constants for a fixed set of values such as order statuses?

level: juniorimportance: must knowfreq 62%
basics
~20 s

An enum is a real type with a closed set of cases, so a parameter typed OrderStatus accepts only those cases and rejects any string. Class constants are plain strings or ints that any typo or foreign value can impersonate.

open as a page

In PHP, what do the abstract and final modifiers mean on a class and on a method, and why can one member not be both?

level: juniorimportance: must knowfreq 62%
basics
~20 s

An abstract class cannot be instantiated and an abstract method has no body, so a concrete child must supply it. A final class cannot be extended and a final method or class constant cannot be overridden. Combining them is contradictory, so PHP rejects it.

open as a page

In PHP, how does a child class override an inherited method, and how does it still run the parent's version with parent::?

level: juniorimportance: must knowfreq 72%
basics
~20 s

A PHP class extends exactly one parent and overrides a method by declaring one with the same name and a compatible signature. Inside it, parent::name() runs the inherited body on the same object; a child constructor must call parent::__construct() itself.

open as a page

In PHP, are objects passed by reference, and what really happens when you assign an object or pass it to a function?

level: juniorimportance: must knowfreq 72%
basics
~20 s

No. A PHP object variable holds an object handle, and assignment, argument passing and return copy that handle, so both sides reach one instance. Rebinding a parameter never affects the caller; only & creates a true alias.

open as a page

In PHP, what does spl_autoload_register() do, and what happens when code uses a class that is not yet defined?

level: juniorimportance: must knowfreq 72%
basics
~20 s

spl_autoload_register() adds a callback to PHP's autoloader queue. When code uses an undefined class, PHP calls each callback in order with the class name until one defines the class; if none does, an Error "Class not found" is thrown.

open as a page

In a PHP file declaring namespace App\Billing, how do the class names Invoice, Tax\Rate and \Invoice each resolve?

level: juniorimportance: must knowfreq 68%
basics
~10 s

Invoice becomes App\Billing\Invoice unless a use statement imports that short name; Tax\Rate becomes App\Billing\Tax\Rate unless Tax is an imported alias; \Invoice is absolute and means the global class Invoice.

open as a page

In PHP 8.5, what happens when include versus require cannot open the file, and which should load a bootstrap file?

level: juniorimportance: must knowfreq 78%
basics
~20 s

When the file cannot be opened, include emits warnings, returns false and the script continues; require emits a warning and then throws an Error, which stops the script unless caught. Anything the program cannot run without should use require.

open as a page

Under PSR-4, with the prefix Acme\Blog\ mapped to src/, which file must hold Acme\Blog\Http\PostController, and what must match?

level: middleimportance: must knowfreq 62%
basics
~10 s

The file is src/Http/PostController.php: the prefix Acme\Blog\ is replaced by src/, remaining namespace segments become directories and the class name becomes the file name, all matching the class name's letter case.

open as a page

In namespaced PHP code, why does calling strlen() work without an import while new DateTime() fails with a class-not-found Error?

level: middleimportance: must knowfreq 62%
basics
~20 s

An unqualified function or constant name that is not imported falls back to the global one at run time if no namespaced version exists; class names never fall back, so DateTime inside App means App\DateTime.

open as a page

In PHP, how do you declare a custom attribute class such as #[Route] and read it back from controller methods at run time?

level: middleimportance: must knowfreq 45%
basics
~10 s

Write an ordinary class marked #[Attribute] whose constructor takes the attribute's arguments, put #[Route('/users')] on a method, then call getAttributes(Route::class) on its ReflectionMethod and newInstance() on each ReflectionAttribute returned.

open as a page

In PHP, how does a tiny dependency-injection container use ReflectionClass and getParameters() to autowire a class's constructor dependencies?

level: middleimportance: must knowfreq 45%
basics
~20 s

For a requested class it calls getConstructor(), walks getParameters(), and for each parameter whose type is a ReflectionNamedType naming a class, resolves that class recursively; scalars need a default or explicit config. It then calls newInstanceArgs() with the resolved list.

open as a page

In PHP 8, how do native attributes written as #[...] differ from docblock annotations such as @Route inside a /** */ comment?

level: juniorimportance: should knowfreq 45%
basics
~20 s

Attributes are real PHP syntax: the engine parses them, resolves their names like class names and returns them through Reflection's getAttributes(). Docblock annotations are comment text a userland library must fetch with getDocComment() and parse itself.

open as a page

In PHP, how do you create an object when its class name is only known at run time, and when is ReflectionClass::newInstanceArgs() actually needed?

level: juniorimportance: should knowfreq 30%
basics
~20 s

Plain new already accepts a variable: new $class(...$args), with string keys passed as named arguments. ReflectionClass::newInstanceArgs() does the same; reflection is needed when you must inspect the class first, or build it without its constructor or lazily.

open as a page

In PHP 8.2 and later, what does the #[\SensitiveParameter] attribute redact, and what does it leave exposed?

level: middleimportance: should knowfreq 22%
basics
~20 s

It replaces the marked argument with a SensitiveParameterValue object in every backtrace PHP builds, so exception traces and debug_backtrace() no longer print it. The function body, var_dump(), logging and callees without the attribute still see the real value.

open as a page

In PHP, how do try, catch and finally blocks work together, and in what order are multiple catch blocks tried?

level: juniorimportance: must knowfreq 74%
basics
~20 s

Code in try runs until something throws; PHP then tests catch blocks top to bottom and runs the first whose type matches the thrown object. finally runs afterwards, whether the try succeeded, was caught, or is still propagating.

open as a page

In PHP 8, what is the difference between the Error and Exception classes, and why does catch (Exception $e) miss a TypeError?

level: juniorimportance: must knowfreq 72%
basics
~20 s

Both implement the Throwable interface but sit on separate branches: Error covers faults PHP itself detects, like TypeError or DivisionByZeroError, while Exception covers failures application and library code reports. catch (Exception) never matches an Error subclass.

open as a page

In PHP, how do you wrap a failed payment-provider call in your own domain exception without losing the original cause?

level: middleimportance: must knowfreq 55%
basics
~20 s

Catch the provider client's exception narrowly and throw your own exception class, passing the caught object as the third constructor argument, $previous. Callers depend only on your type, while getPrevious() still returns the provider's original failure for logs and debugging.

open as a page

In PHP, what is the difference between the display_errors and log_errors settings, and how should each be set in production?

level: middleimportance: must knowfreq 62%
basics
~20 s

display_errors writes error messages into the script's output, where visitors see them; log_errors writes them to the error log. Production should run display_errors=Off and log_errors=On, the values php.ini-production ships, so errors are recorded but never shown.

open as a page

How do you turn PHP warnings and notices into exceptions with set_error_handler and ErrorException?

level: middleimportance: must knowfreq 50%
basics
~20 s

Register a callback with set_error_handler() that throws new ErrorException($errstr, 0, $errno, $errfile, $errline). Warnings and notices then become catchable exceptions; the callback should first skip levels excluded by error_reporting(), and fatal or compile-time errors never reach it.

open as a page

In PHP, how do HTML form field names become $_POST keys, and what do name[] and name[key] produce?

level: juniorimportance: must knowfreq 68%
basics
~20 s

Each submitted control's name attribute becomes a $_POST key holding a string. A name ending in [] appends to a list, name[key] sets that key, and a repeated plain name keeps only its last value, so multi-selects need name[].

open as a page

In PHP, what causes the "Cannot modify header information - headers already sent" warning, and how do you fix it?

level: juniorimportance: must knowfreq 72%
basics
~20 s

Headers are sent with the first byte of body output, so header() fails with that warning once anything has been output: an echo, whitespace outside the PHP tags, a BOM or a displayed warning. Send headers before any output.

open as a page

In PHP, why must header('Location: ...') be followed by exit, and which status code does the redirect send?

level: juniorimportance: must knowfreq 66%
basics
~20 s

header('Location: ...') only queues a header; the script keeps running, so code after it still executes and its output is sent. Call exit right after. PHP adds a 302 unless a code is given, so pass 303 or 301 explicitly.

open as a page

In PHP, what does session_start() actually do, and how does $_SESSION data survive from one request to the next?

level: juniorimportance: must knowfreq 80%
basics
~20 s

session_start() takes the session ID from the PHPSESSID cookie or creates a new one, loads that ID's stored data through the save handler into $_SESSION, and PHP writes $_SESSION back to storage when the request ends.

open as a page

In a plain PHP app, how do you protect a bank's change-email form with a CSRF token, from generating it to checking it on POST?

level: juniorimportance: must knowfreq 50%
basics
~20 s

Generate an unpredictable token (bin2hex(random_bytes(32))), store it in $_SESSION, and echo it in a hidden field of the change-email form. On POST, compare the submitted field against the session copy with hash_equals(); if it is missing or does not match, reject the request.

open as a page

In PHP, how do you safely echo a user's review into an HTML page with htmlspecialchars(), and which flags and charset should you pass?

level: juniorimportance: must knowfreq 78%
basics
~20 s

Wrap every untrusted value in htmlspecialchars() at the moment it is echoed. Pass ENT_QUOTES | ENT_SUBSTITUTE and 'UTF-8', the PHP 8.1+ defaults, so both quote types are encoded and malformed UTF-8 cannot turn the output into an empty string.

open as a page

In PHP, how do you validate an age field with filter_var() and FILTER_VALIDATE_INT, and how do you detect a failed check correctly?

level: juniorimportance: must knowfreq 66%
basics
~10 s

Call filter_var($value, FILTER_VALIDATE_INT, ['options' => ['min_range' => 16, 'max_range' => 99]]). It returns an int on success and false on failure, so test with === false, because a valid 0 is falsy.

open as a page

In PHP, what do password_hash() and password_verify() do, and what exactly should you store in the database?

level: juniorimportance: must knowfreq 62%
basics
~20 s

password_hash($plain, PASSWORD_DEFAULT) returns a self-describing string that embeds the algorithm, cost and a random salt; store that one string. password_verify($plain, $hash) rehashes the input the same way and returns a bool. Never generate the salt yourself or compare hashes manually.

open as a page

In PHP, which built-in calls turn attacker-controlled request data into executed code or instantiated objects, and why are they dangerous?

level: juniorimportance: must knowfreq 58%
basics
~10 s

eval() runs a string as PHP; include/require execute a file you supply; unserialize() rebuilds objects and calls their magic methods; extract() writes request keys into variables. Never feed request data to any of them.

open as a page

In PHP, what goes wrong with mkdir($dir, 755, true), and how do you create a directory tree with the permissions you intend?

level: juniorimportance: must knowfreq 45%
basics
~20 s

755 without a leading zero is a decimal number, octal 1363, so the directory gets scrambled permissions. Write 0755 (or 0o755 since PHP 8.1), pass true to create parents, expect the umask to trim the mode, and treat an existing directory as a false return.

open as a page

In PHP, when do you use file_get_contents() and file_put_contents() instead of fopen() with fgets() and fwrite(), and what does each approach cost?

level: juniorimportance: must knowfreq 65%
basics
~20 s

file_get_contents() and file_put_contents() read or write a whole file in one call, so the entire content sits in memory. fopen() returns a handle for fgets(), fread() and fwrite(), keeping memory flat for large or streamed files.

open as a page

In PHP, why can is_file() or filesize() keep returning an old result inside one script, and when is clearstatcache() actually needed?

level: middleimportance: must knowfreq 40%
basics
~20 s

PHP caches the last stat() result, and is_file(), filesize(), filemtime() and similar functions reuse it for the same path. If another process changes that file, repeated checks in one script can see old data until clearstatcache() is called.

open as a page

In PHP, what is the difference between php://memory and php://temp, and how would you use one to buffer a generated report before sending it?

level: middleimportance: must knowfreq 40%
basics
~20 s

php://memory keeps all data in RAM, limited only by memory_limit; php://temp keeps up to 2 MB in memory, then moves to a temporary file. Write the report into php://temp, rewind(), then stream it out with fpassthru() or stream_copy_to_stream().

open as a page

In PHP, how do you process a multi-gigabyte log file line by line without hitting memory_limit, and which loop mistakes still break it?

level: seniorimportance: must knowfreq 55%
basics
~20 s

Open the file with fopen() and loop while fgets() does not return false, or iterate an SplFileObject, so only one line is in memory. file() and file_get_contents() load everything, and collecting results in an array grows memory again.

open as a page

In PHP, what does json_decode() return for a JSON object when its associative argument is omitted, and what changes when it is true?

level: juniorimportance: must knowfreq 74%
basics
~10 s

By default json_decode() turns every JSON object into a stdClass object, read with ->; with the associative argument true, objects become associative arrays, read with []. JSON arrays become PHP arrays in both modes.

open as a page

In PHP, how do you read an element's text and an attribute with SimpleXML, and why do you cast the results to string?

level: juniorimportance: must knowfreq 50%
basics
~20 s

simplexml_load_string() returns a SimpleXMLElement: child elements are read as properties ($p->name) and attributes with array syntax ($p['sku']). Both return SimpleXMLElement objects, so cast with (string), (int) or (float) before comparing, storing or passing them on.

open as a page

In PHP, how do you read a multi-gigabyte CSV file with fgetcsv() without exhausting memory, and how do you detect the end of the file?

level: middleimportance: must knowfreq 52%
basics
~20 s

Open the file with fopen() and call fgetcsv() in a loop until it returns false; each call parses one record, so memory stays flat. A blank line returns [null], not false, so skip it explicitly.

open as a page

In PHP, why is comparing json_decode()'s result with null an unreliable error check, and what does JSON_THROW_ON_ERROR change?

level: middleimportance: must knowfreq 62%
basics
~10 s

json_decode() returns null both for invalid input and for the valid JSON text null, so a null check cannot tell them apart. JSON_THROW_ON_ERROR makes json_decode() and json_encode() throw JsonException instead of setting json_last_error().

open as a page

In PHP, when should you store a value with serialize() rather than json_encode(), and what does each round trip lose?

level: middleimportance: must knowfreq 58%
basics
~20 s

Use serialize() only for PHP-to-PHP storage you control, because it restores exact types, classes, private properties and shared references. Use json_encode() for anything another program or an untrusted party touches: portable and inert, but classes and non-public state are lost.

open as a page

In PHP, what are the practical differences between the mysqli extension and PDO, and when would you choose mysqli?

level: juniorimportance: must knowfreq 66%
basics
~20 s

mysqli works only with MySQL, offers procedural and object styles, positional ? placeholders and MySQL-specific features such as multi_query(). PDO is one object API across many databases with named placeholders. Choose mysqli for existing mysqli code or MySQL-only features.

open as a page

In PHP, how do you open a PDO connection to MySQL, and what should its options array set?

level: juniorimportance: must knowfreq 72%
basics
~10 s

Call new PDO($dsn, $user, $password, $options) with a DSN such as mysql:host=db;dbname=clinic;charset=utf8mb4. Set PDO::ATTR_ERRMODE to ERRMODE_EXCEPTION and PDO::ATTR_DEFAULT_FETCH_MODE to FETCH_ASSOC; a failed connection throws PDOException.

open as a page

In PHP, how do PDO::prepare() and execute() run a query with user input, and how do ? and :name placeholders differ?

level: juniorimportance: must knowfreq 76%
basics
~20 s

PDO::prepare() turns an SQL template with placeholders into a PDOStatement; execute() supplies the values, a list for ? markers or a keyed array for :name markers. The styles cannot be mixed, and a marker is one whole value.

open as a page

In PHP, what do PDO's ERRMODE_SILENT, ERRMODE_WARNING and ERRMODE_EXCEPTION do, and why did PHP 8.0's default change matter?

level: middleimportance: must knowfreq 60%
basics
~20 s

SILENT makes failing calls return false and leaves details in errorInfo(); WARNING also emits E_WARNING; EXCEPTION throws PDOException. PHP 8.0 made EXCEPTION the default, so a failed query no longer slips by as an unchecked false.

open as a page

In PHP's PDO, how does bindParam() differ from bindValue(), and when does the PDO::PARAM_* type argument change what the database receives?

level: middleimportance: must knowfreq 56%
basics
~20 s

bindValue() copies a value when called; bindParam() binds a variable by reference and reads it at execute(). The PARAM_* type, PARAM_STR by default, decides how the value is sent, which matters for LIMIT, booleans and binary data.

open as a page

In PHP's cURL extension, what does CURLOPT_RETURNTRANSFER change about curl_exec(), and how do you tell a failed transfer from an HTTP error?

level: juniorimportance: must knowfreq 62%
basics
~20 s

CURLOPT_RETURNTRANSFER makes curl_exec() return the body as a string instead of printing it. curl_exec() returns false only when the transfer itself fails (read curl_errno() and curl_error()); a 404 or 500 still succeeds, so check CURLINFO_RESPONSE_CODE.

open as a page

When you build a Guzzle Client with base_uri and default options, how are relative paths resolved, and what timeout applies if you set none?

level: juniorimportance: must knowfreq 58%
basics
~20 s

Guzzle resolves a request URI against base_uri by RFC 3986: 'rates' after 'https://api.test/v2/' gives /v2/rates, but '/rates' or a base without the trailing slash drops v2. The timeout option defaults to 0, which waits indefinitely.

open as a page

In PHP's cURL extension, how do CURLOPT_CONNECTTIMEOUT and CURLOPT_TIMEOUT differ, and what happens when neither is set?

level: middleimportance: must knowfreq 54%
basics
~20 s

CURLOPT_CONNECTTIMEOUT caps only connection setup (default 300 seconds); CURLOPT_TIMEOUT caps the whole transfer (default 0, meaning never). Without both, a hanging API can hold a PHP worker for minutes; set a short connect timeout and a total timeout.

open as a page

In Guzzle 7, what does the http_errors option control, and which exceptions do a 404, a 503 and a timed-out request raise?

level: middleimportance: must knowfreq 55%
basics
~20 s

With http_errors true (the default), a 404 throws ClientException and a 503 ServerException, both BadResponseExceptions carrying the response. A timeout or refused connection throws ConnectException, which since Guzzle 7 extends TransferException, not RequestException, and has no response.

open as a page

How do you unit-test code that uses a Guzzle client with MockHandler, and why wrap it in HandlerStack::create()?

level: middleimportance: should knowfreq 40%
basics
~20 s

Inject a Client whose handler is HandlerStack::create(new MockHandler([...])); queued responses and exceptions are returned in order without network access. The stack matters because http_errors and other options are middleware; a bare MockHandler never throws on 4xx or 5xx.

open as a page

In a PHP CLI script, what do $argv and $argc contain, and why can a function not see $argv directly?

level: juniorimportance: must knowfreq 50%
basics
~20 s

$argv is an array of the command-line arguments with the script name at index 0, and $argc is count($argv). Both are ordinary global variables, not superglobals, so inside a function use $_SERVER['argv'] or pass the array in.

open as a page

In PHP, how do getenv() and putenv() work, and what does getenv() return for a variable that is not set?

level: juniorimportance: must knowfreq 50%
basics
~20 s

getenv('NAME') returns the variable's value as a string, or false when it is not set; getenv() with no argument returns all of them as an array. putenv('NAME=value') sets a variable for the current process and its children until the request ends.

open as a page

In PHP, how do exec(), shell_exec(), system() and passthru() differ in what they return, what they print and how they report the exit code?

level: juniorimportance: must knowfreq 52%
basics
~20 s

exec() returns the last output line, appends every line to $output and sets $result_code. shell_exec() returns the whole output but no exit code. system() prints output and returns the last line; passthru() streams raw bytes.

open as a page

In PHP, how do escapeshellarg() and escapeshellcmd() differ, and which one should wrap a user-supplied filename passed to exec()?

level: middleimportance: must knowfreq 48%
basics
~20 s

escapeshellarg() wraps one value in single quotes so the shell sees exactly one literal argument; use it on every dynamic argument. escapeshellcmd() backslash-escapes metacharacters in a whole command but leaves spaces and paired quotes, so injected extra arguments survive.

open as a page

What do the PHP CLI options -r, -l and -a do, and how does a shebang line make a PHP script runnable as ./import?

level: juniorimportance: should knowfreq 35%
basics
~10 s

php -r runs inline code without <?php tags; php -l only checks syntax; php -a opens an interactive shell that needs readline. A first line #!/usr/bin/env php plus chmod +x makes ./import runnable.

open as a page

In PHP, if you start two Fibers that each run a CPU-heavy loop or call sleep(), do they run in parallel, and why?

level: middleimportance: must knowfreq 38%
basics
~20 s

No. All fibers in a PHP process share one thread and only one runs at a time; control moves only when code calls Fiber::suspend(), start(), resume() or throw(). A CPU loop or sleep() inside one fiber stalls all the others.

open as a page

After moving a PHP API to worker mode, some responses show another user's data; what state is leaking between requests, and how do you find and fix it?

level: seniorimportance: must knowfreq 35%
basics
~20 s

Request data, typically the authenticated user, was stored in something that outlives the request: a static property, a static function variable or a memoised singleton. The next request on that worker reuses it. Make such state request-scoped or reset it after each request.

open as a page

In PHP, what is a Fiber, and how do Fiber::start(), Fiber::suspend() and Fiber::resume() pass values between the fiber and its caller?

level: juniorimportance: should knowfreq 30%
basics
~20 s

A PHP Fiber (core since 8.1) runs a callable on its own call stack that can pause. start() runs it until Fiber::suspend($x), which makes start() return $x; resume($y) continues it and makes that suspend() call return $y.

open as a page

In PHP, which Fiber misuses throw FiberError, and what happens to an exception thrown inside a fiber or injected with Fiber::throw()?

level: middleimportance: should knowfreq 18%
basics
~10 s

FiberError, an Error subclass, marks wrong-state calls: starting twice, resuming a non-suspended fiber, Fiber::suspend() outside a fiber, an early getReturn(). Exceptions inside a fiber leave through the start(), resume() or throw() that entered it.

open as a page

In PHP, how does a Fiber differ from a Generator built with yield, and why can a Fiber pause from inside deeply nested function calls?

level: middleimportance: should knowfreq 28%
basics
~20 s

A Generator pauses only at a yield in its own body, so every caller in between must also yield and return a Generator. A Fiber has its own call stack, so Fiber::suspend() pauses from any depth with callers unchanged.

open as a page

In PHP, what is the difference between DateTime and DateTimeImmutable, and what bug does calling modify() on a shared DateTime cause?

level: juniorimportance: must knowfreq 55%
basics
~20 s

DateTime's modify(), add(), sub(), setDate() and setTimezone() change the object itself and return it; DateTimeImmutable's return a new object and leave the original alone. So $end = $start->modify('+7 days') on a DateTime silently moves $start too.

open as a page

In PHP, how do you make your own collection class usable in foreach, and when do you implement Iterator versus IteratorAggregate?

level: juniorimportance: must knowfreq 45%
basics
~20 s

Implement IteratorAggregate and return an iterator such as new ArrayIterator($this->items) from getIterator(), or implement Iterator's five cursor methods yourself when traversal needs custom logic. Both extend Traversable, which foreach recognises; one class cannot implement both.

open as a page

In PHP, how do the default time zone, DateTimeZone and setTimezone() decide what a date object shows, and how should apps store and display times?

level: middleimportance: must knowfreq 45%
basics
~20 s

Every PHP date object has a zone: the one passed in, else date_default_timezone_set(), else the date.timezone ini value, else UTC. setTimezone() keeps the instant and changes only the wall-clock view. Store UTC plus the user's zone ID.

open as a page

In PHP, how does DateTimeImmutable::createFromFormat() parse input, and why can a date like 2026-02-30 or a format without '!' give a surprising result?

level: middleimportance: should knowfreq 38%
basics
~20 s

createFromFormat() parses against an explicit format and returns false when it cannot. Fields the format omits take the current time unless it starts with ! or ends with |, and February 30 rolls into March with only a warning.

open as a page

In PHP, what does DateTimeImmutable::diff() return, why does $interval->format('%d') often give the wrong day count, and how does DatePeriod iterate a range?

level: middleimportance: should knowfreq 30%
basics
~20 s

diff() returns a DateInterval split into years, months, days and time, plus days, the total day count. %d prints only the days component; %a prints the total. DatePeriod steps from start to end, excluding the end unless INCLUDE_END_DATE is set.

open as a page

In PHP, what does the fatal error "Allowed memory size of 134217728 bytes exhausted" mean, and what does memory_limit control?

level: juniorimportance: must knowfreq 55%
basics
~20 s

The script asked PHP's memory manager for more than memory_limit allows (134217728 bytes is the default 128M), so PHP stopped with a fatal error that try/catch cannot catch. memory_limit caps one process's engine allocations; -1 removes it.

open as a page

In PHP, what does OPcache do for a web application, and what does it not cache?

level: juniorimportance: must knowfreq 70%
basics
~20 s

OPcache stores each script's compiled opcodes in shared memory, so later requests skip reading and compiling the PHP source and run the cached opcodes directly. It caches code only: not query results, not rendered pages, not application data.

open as a page

In PHP, when does caching a feature-flag list in APCu on each web server beat Redis, and when does it give wrong answers?

level: middleimportance: must knowfreq 42%
basics
~20 s

APCu wins for small, read-heavy, rarely changing data such as a flag list: a local memory read, no network hop. It gives wrong answers when servers must agree, because each server holds its own copy and cannot invalidate the others.

open as a page

In PHP, what do opcache.validate_timestamps and opcache.revalidate_freq control, and why do production servers often disable validation?

level: middleimportance: must knowfreq 50%
basics
~20 s

With opcache.validate_timestamps=1 (the default) OPcache checks a cached script's modification time at most every opcache.revalidate_freq seconds (default 2) and recompiles it if it changed. Production often sets 0: no file checks at all, so a deploy must reset OPcache.

open as a page

After a release, a PHP product page is 800 ms slower in production; how do you find the slow path instead of guessing at it?

level: seniorimportance: must knowfreq 45%
basics
~20 s

Confirm and scope the regression, split wall time from CPU time, narrow it with hrtime spans around each phase, then profile production traffic with a low-overhead sampling profiler on a small fraction of requests and compare against the previous release.

open as a page

In PSR-11, what do ContainerInterface::get() and has() promise, and what does get() throw for an unknown identifier?

level: juniorimportance: must knowfreq 45%
basics
~10 s

PSR-11's ContainerInterface has get($id), returning any entry, and has($id), returning a bool. If has() returns false, get() must throw Psr\Container\NotFoundExceptionInterface; other container errors implement ContainerExceptionInterface.

open as a page

In PSR-3, what are the eight log levels in Psr\Log\LogLevel, and how do you choose between them?

level: juniorimportance: must knowfreq 55%
basics
~20 s

PSR-3 defines eight RFC 5424 levels: emergency, alert, critical, error, warning, notice, info and debug, each with its own LoggerInterface method. Choose by urgency: from system unusable, through failures and oddities, down to routine events and diagnostics.

open as a page

In PHP, what are the PSR-1 and PSR-12 coding standards, and what kinds of rules does each one set?

level: juniorimportance: must knowfreq 55%
basics
~20 s

PSR-1 is PHP-FIG's basic coding standard: tags, UTF-8, naming, one class per autoloadable file, and no mixing of declarations with side effects. PSR-12 extends it with formatting: indentation, line endings, braces, spacing and file-header order, replacing PSR-2.

open as a page

In PSR-15, what do MiddlewareInterface::process() and RequestHandlerInterface::handle() declare, and how does a rate-limiting middleware reject or delegate a request?

level: middleimportance: must knowfreq 50%
basics
~10 s

PSR-15 declares handle(ServerRequestInterface $request): ResponseInterface and process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface. A rate limiter returns its own 429 response to reject, or calls $handler->handle($request) and returns that response.

open as a page

In PSR-7, why does calling $response->withHeader('X-Trace-Id', $id) without assigning the result leave the response unchanged?

level: middleimportance: must knowfreq 62%
basics
~10 s

PSR-7 messages are immutable: withHeader() returns an instance carrying the change and must leave the original untouched. Discarding the return value discards the change; write $response = $response->withHeader(...) or return the new instance.

open as a page