What PHP is
TipIt is an open source, server-side scripting language. The same code runs on Linux, Windows and macOS.
Asked in interviews
AskedWhat is PHP and what does it stand for?=== and strict types to stop it.TipIt is an open source, server-side scripting language. The same code runs on Linux, Windows and macOS.
Asked in interviews
AskedWhat is PHP and what does it stand for?<?= $name ?>echo "a", "b";print "a"TipLeave ?> out of a PHP-only file, so no stray newline gets sent.
TrapShort tags <? ?> need short_open_tag, so avoid them. PHP 7.0 removed ASP tags <% %>.
'Hi $name'"Hi {$u['name']}"<<<EOT<<<'EOT'const MAX = 10;define('MAX', 10);TipHeredoc expands and nowdoc doesn't. const is compile time, so only define() works inside an if.
TrapIn single quotes, only \' and \\ are special. So '\n' is a backslash and the letter n.
$a === $b$a == $b"10" + 5; // 15TipScalar bool, int, float, string. Compound array, object, callable. Special null, resource.
TrapSince PHP 8, 0 == "foo" is false, and "abc" + 5 throws a TypeError. "1" == "01" is still true.
$a['k'] ?? 'x'$a['k'] ??= 30$a <=> $bTip?? treats null as missing and raises no warning. <=> is what usort() callbacks return.
break;continue;match($v) { 1 => 'a' };Tipmatch returns a value, uses === and never falls through. No matching arm throws Unhandled.
TrapIn a switch, a bare continue acts like break. Use continue 2 to reach the loop.
declare(strict_types=1); public int $id;int|float?stringTipA typed property with no default starts uninitialized, not null. Reading it first throws an Error.
TrapStrict mode for arguments follows the calling file, not the file that defines the function.
$func();function f(int ...$n)func_get_args()function f($x)function f(&$x)TipObjects don't pass by reference. PHP copies the identifier, so only & lets a new object reach the caller.
TrapCheck a name from user input against an allowlist, or a user could run any function.
function () use ($p)function () use (&$p)fn (7.4+)fn($x) => $x * $fglobal $count;static $n = 0;TrapUnlike C, a function can't see globals by default. Only superglobals are visible everywhere.
array_key_exists($k, $a)isset($a[$k])empty($a[$k])TipAn array is one type, an ordered map. It can mix integer and string keys, and it keeps insertion order.
TrapPHP converts keys. "8" becomes 8 and true becomes 1, but "08" stays a string.
array_merge($a, $b)array_combine($k, $v)A size mismatch throws a ValueError since 8.0.array_map($fn, $a)array_filter($a, $fn)array_reduce($a, $fn, 0)Tiparray_merge renumbers numeric keys, and a later string key wins. $a + $b keeps the first array's values.
Traparray_filter() keeps the original keys. Wrap it in array_values() for a clean list.
return $this;self::who()static::who()new static()TipB::test() runs A's method. There self::who() means A and static::who() means B, so it prints AB.
Trapparent:: and self:: forward the called class. A direct A::foo() resets it.
class A implements B, Cabstract class Repouse Timestampable;TipA class extends one parent but implements many interfaces. Traits share code beyond that parent.
TrapTwo traits with the same method are a fatal error until you pick one with insteadof.
__get()__set()__call()__toString()__invoke()__serialize()TrapEvery magic method except __construct(), __destruct() and __clone() must be public, or PHP warns.
Asked in interviews
AskedWhat are magic methods in PHP?__construct(private $x)readonly int $id;clone($o, ['a' => 1])enum Status: stringStatus::from('a')Status::tryFrom('a') Tipfrom throws a ValueError on an unknown value, and tryFrom returns null. Each case is a single object.
Trapclone is shallow, so the copy shares objects in properties. Hold Date, not DateTime.
#[Route('/users')] #[\Override]new ReflectionClass($c) TipA custom attribute does nothing until code reads it with getAttributes(). DI containers and ORMs do this.
Trapset has had no effect since 8.1 and is deprecated as of 8.5.
E_ERRORE_PARSEE_WARNINGE_NOTICEset_error_handler($f); catch (Throwable $e)TipError, such as TypeError, and Exception both implement Throwable. Custom classes extend Exception.
Traptry and catch can't catch warnings or notices. They go to the error handler.
extends Exceptionnew E($m, 0, $prev)catch (A | B $e)finally { ... }TipgetPrevious() reads the cause back. PHP tries catch blocks in order, so put specific types first.
Trapexit() or a fatal error skips finally. A return in finally replaces the earlier return value.
error_log(print_r($d, true));TipRead the error log first. In production, keep display_errors off.
Asked in interviews
AskedHow do you debug PHP applications effectively?TestCase$this->assertEquals(4, $n);TipPCOV reports line coverage. Xdebug also reports branches. Aim for 70-80%.
TrapCoverage shows which code never ran, not what is tested well.
$this->createStub(Repo::class) $this->createMock(Mail::class) TrapToo many mocks tie tests to implementation details, so a refactor breaks them.
Asked in interviews
AskedExplain mocking and stubbing in PHP testing.$pdo->prepare('... id = ?')$s->execute([$id]);TipChoose PDO for portability across 11 drivers, and MySQLi for MySQL-only features. Their speed is about the same.
TrapPlaceholders stand only for values. Check table names and ASC against an allowlist.
try$pdo->beginTransaction() $pdo->commit();$pdo->rollBack(); EXPLAIN SELECT ...OFFSETWHERE id > ? LIMIT 20TipIndex the WHERE, JOIN and ORDER BY columns. PHP has no built-in connection pool, so use PgBouncer or ProxySQL.
TrapMyISAM has no transactions. In MySQL, DDL such as CREATE TABLE commits the open one.
WHERE id IN (...)Book::with('author')->get()TipLazy loading suits optional data, and Eloquent is lazy unless you ask. PHP 8.4 added native lazy objects.
TrapOne query per list item is N+1. 25 books and their authors cost 26 queries, not 2.
$_SESSION['id'] = 7;setcookie('a', 'b');session.cookie_httponly session.cookie_secure session.use_strict_mode session_regenerate_id(true); gc_maxlifetime isn't a timeout.TipA cookie holds about 4KB, and the user can change it. Use a session for what the user must not change.
TrapIn session fixation, the victim logs in on an ID the attacker planted. A new ID at login defeats it.
htmlspecialchars($s)TipLeast privilege limits an injection's damage. Content-Security-Policy limits script sources.
TrapHTML encoding doesn't protect data inside JavaScript or a URL. Encode for that context.
random_bytes(32) hash_equals($a, $b)TipAdd SameSite=Lax as a layer, not a replacement.
TrapCross-site scripting (XSS) defeats every CSRF defense, so prevent it too.
Asked in interviews
AskedWhat is CSRF and how do you protect against it?password_hash($p, PASSWORD_DEFAULT) password_verify($p, $h)password_needs_rehash() TipMake the column 255 wide. PASSWORD_ is bcrypt today, and 8.4 raised its cost from 10 to 12.
TrapNever use MD5 or SHA-256. They are fast, so attackers test guesses at high speed.
Asked in interviews
AskedHow do you properly hash passwords in PHP?move_uploaded_file() TrapThe browser supplies the name and MIME type in $_FILES. Check the real content.
Asked in interviews
AskedWhat are the security implications of file uploads?$_GET['q']$_POST['q']$_FILES$_COOKIE$_SERVERphp://inputTipGET reads, with data in the URL, and is safe and idempotent. POST changes data, in the body.
TrapNeither encrypts. Send passwords with POST over HTTPS, because URLs end up in logs.
TrapFix the JWT algorithm, and check expiry, issuer and audience. A JWT stays valid until it expires.
Access-Control-Allow-OriginOPTIONS preflightexit();TipThe browser enforces CORS. It isn't authentication.
Trap* can't be used with cookies. Echo one origin from an allowlist, and send Vary: Origin.
Asked in interviews
AskedWhat is CORS and how do you handle it in PHP?$redis->incr($key);TipReject with status 429. A sliding window stops a client sending twice the limit across a window boundary.
TrapIf the process dies between incr() and expire(), the key never expires. A Lua script does both at once.
Asked in interviews
AskedHow do you implement rate limiting in PHP APIs?include 'a.php';require 'a.php';require_once 'a.php';spl_autoload_register() namespace App\Models;use App\Models\User;TipWrite \Exception for a global class. Functions and constants fall back to global, so strlen() works.
TrapA use statement only imports a name. The file loads on first use, such as new User().
composer require a/bcomposer installcomposer updatephpcs srcphp-cs-fixer fix srcTip^2.0 means at least 2.0, below 3.0. --no-dev skips development packages on servers.
TrapCommit composer.lock, so every developer and server installs the same versions.
getenv('DB_HOST') TipKeep the code the same, and put what differs between environments in environment variables.
TrapThe production php.ini can leave $_ENV empty, so check getenv() too. Keep .env out of git.
Asked in interviews
AskedHow do you handle configuration in PHP applications?private function __construct()Db::getInstance() __construct(Db $db)TipWith injection, a test can pass a mock. Type-hint an interface, not a concrete class.
TrapSingleton is global state and hides dependencies, so many call it an anti-pattern.
$users->find($id);TrapKeep controllers thin. Move business logic into models or service classes.
TrapOver-applying SOLID adds an interface for every class. Apply it where code is expected to change.
Asked in interviews
AskedWhat are SOLID principles and how do they apply to PHP?pm.max_childrenpm.max_requestsopcache.preloadopcache.jitopcache.validate_timestamps=0 TipOPcache keeps opcodes in shared memory, so requests skip compiling. The JIT mostly helps CPU-heavy work.
TrapWith file checks off, every deploy must reset OPcache or restart PHP.
unset($big);gc_collect_cycles(); yield $line;TipReference counting frees a value at zero, and a cycle collector handles cycles. Arrays use copy-on-write.
TrapA generator runs forward only, so you can't rewind it once it has started.
Cache-ControlTipCache-aside reads the cache first. On a miss, it loads from the database and stores the result with a time to live.
TrapWhen a busy key expires, many requests hit the database. A rebuild lock stops this cache stampede.
Asked in interviews
AskedHow do you implement caching in PHP applications?Fiber::suspend();TipOnly one fiber runs at a time, so fibers give concurrency, not parallelism.
TrapBlocking libraries stall the event loop, and long-running processes must not leak.
Asked in interviews
AskedWhat is the difference between synchronous and asynchronous PHP?Nothing matches. Try a shorter word, or clear the search.
With Pro, you can:
Already have Pro? Sign in