Master these 31 carefully curated interview questions to ace your next Php interview.
PHP is a server-side scripting language primarily used for web development, powering WordPress, Laravel, and 77% of websites.
PHP: Hypertext Preprocessor. Embedded in HTML with <?php ?>. Powers WordPress (43% of web), Facebook (Hack), Wikipedia. Strengths: easy to learn, huge ecosystem, excellent hosting support. Modern PHP (8.x): typed properties, match expressions, enums, fibers, readonly classes.
PHP has scalar types (string, int, float, bool), compound types (array, object), and special types (null, resource).
PHP is dynamically typed but supports type declarations (PHP 7+). Type juggling: automatic conversion. Strict mode: declare(strict_types=1). Union types (PHP 8): int|string. Intersection types: A&B. Arrays are versatile: indexed, associative, multidimensional. Type coercion can cause subtle bugs.
Laravel is a PHP framework with Eloquent ORM, Blade templates, Artisan CLI, middleware, routing, and built-in auth.
Key features: (1) Eloquent ORM: ActiveRecord pattern. (2) Blade: template engine. (3) Artisan: CLI for scaffolding. (4) Middleware: request pipeline. (5) Laravel Sanctum/Passport: API auth. (6) Queues: background jobs. (7) Laravel Sail: Docker dev environment. (8) Livewire: full-stack reactive components.
Sessions store data server-side (identified by session ID cookie); cookies store small data client-side with expiry.
session_start() begins session. $_SESSION superglobal for read/write. Session ID in cookie (PHPSESSID). Cookies: setcookie(name, value, expire). $_COOKIE to read. Sessions: more secure (data server-side), larger storage. Cookies: persist across visits, limited to 4KB. Use sessions for auth state, cookies for preferences.
Composer is PHP's dependency manager, using composer.json for packages and autoloading via PSR-4.
composer require package: installs dependency. composer.lock: locks versions. Autoloading: PSR-4 standard. Packagist.org: default repository. Semantic versioning: ^2.0 (minor updates). Scripts: custom commands. Platform requirements: specify PHP/extension versions. composer update vs install (lock file).
Named arguments, match expressions, union types, attributes, enums, fibers, readonly properties, and JIT compilation.
PHP 8.0: union types, named arguments, match expression, nullsafe operator (?->), attributes (#[Route('/')]). PHP 8.1: enums, fibers, readonly properties, intersection types. PHP 8.2: readonly classes, standalone types (true, false, null). PHP 8.3: typed class constants, json_validate(). JIT compiler improves CPU-bound performance.
Use prepared statements, input validation, output escaping, CSRF tokens, password hashing, HTTPS, and up-to-date dependencies.
Security: (1) SQL injection: PDO prepared statements. (2) XSS: htmlspecialchars() output escaping. (3) CSRF: token-based protection. (4) Passwords: password_hash()/password_verify() with bcrypt. (5) File uploads: validate type/size. (6) Dependencies: composer audit. (7) Headers: Content-Security-Policy, X-Frame-Options. (8) HTTPS everywhere. (9) Session security: regenerate ID on login.
Profile with Laravel Debugbar, fix N+1 queries with eager loading, add caching (Redis), optimize routes and config.
Steps: (1) Laravel Debugbar: see queries and timing. (2) Eager loading: with() to fix N+1. (3) Redis caching for frequent queries. (4) Route caching: php artisan route:cache. (5) Config caching: php artisan config:cache. (6) Queue heavy operations. (7) Database indexes. (8) OPcache enabled. (9) Pagination for large results.
Facebook created Hack to add static typing, async/await, and generics to PHP for better performance and developer productivity.
Hack: gradually typed PHP superset. Added: static typing (annotations), async/await (non-blocking I/O), generics, collections (typed alternatives to arrays), XHP (type-safe HTML). Runs on HHVM (HipHop Virtual Machine) with JIT compilation. Facebook processes billions of requests daily. Key lesson: static typing at scale catches bugs earlier and enables better tooling.
echo outputs strings without return value and accepts multiple arguments; print outputs one string and returns 1.
echo: not a function (language construct), no return value, accepts multiple comma-separated arguments: echo 'a', 'b'. Slightly faster. print: language construct, returns 1 (can be used in expressions), accepts only one argument. Both output strings to stdout. printf/sprintf: formatted output. var_dump: debug output with types. print_r: readable array/object output. In practice: echo is preferred for performance and flexibility. Neither requires parentheses: echo 'hello' or echo('hello').
PHP has 10 types: int, float, string, bool, array, object, null, resource, callable, and enum (PHP 8.1+).
Scalar: int, float, string, bool. Compound: array (ordered map), object. Special: null, resource (external resource handle). Pseudo: callable, iterable, mixed, void, never. PHP is dynamically typed — type juggling converts automatically. Type declarations: function add(int $a, int $b): int. Strict types: declare(strict_types=1) disables type coercion. Union types (8.0): int|string. Intersection types (8.1): Countable&Iterator. Enums (8.1): enum Status: string { case Active = 'active'; }.
Namespaces organize code to avoid name collisions; autoloading via PSR-4/Composer loads classes automatically without manual require.
Namespace: namespace App\Models; at top of file. Use: use App\Models\User. Aliasing: use App\Models\User as UserModel. PSR-4 autoloading: maps namespace prefix to directory. Composer autoload: { 'psr-4': { 'App\\': 'src/' } }. spl_autoload_register: custom autoloader function. composer dump-autoload optimizes class map. Benefits: avoid class name collisions, organize large codebases, enable lazy loading (only load used classes). Every modern PHP framework uses PSR-4 autoloading via Composer.
Traits provide horizontal code reuse — shared methods injected into classes without inheritance, solving PHP's single inheritance limitation.
Syntax: trait Timestampable { public function getCreated(): DateTime { ... } }. Usage: class Post { use Timestampable; }. Conflict resolution: use A, B { A::method insteadof B; B::method as aliasMethod; }. Visibility: use Trait { method as private; }. Abstract methods in traits force implementing class to define them. vs Interfaces: interfaces define contracts; traits provide implementation. vs Inheritance: traits for shared behavior across unrelated classes. Laravel uses traits extensively: SoftDeletes, HasFactory, Notifiable. Avoid: complex trait dependencies, state in traits.
Sessions store data server-side with a session ID cookie; cookies store small data client-side sent with every request.
Sessions: session_start() creates/resumes session. $_SESSION['key'] = value. Session ID in cookie (PHPSESSID) or URL. Data stored on server (file, database, Redis). session_destroy() ends session. session_regenerate_id() prevents session fixation attacks. Cookies: setcookie('name', 'value', time()+3600, '/', '', true, true). $_COOKIE['name'] to read. Options: expires, path, domain, secure (HTTPS only), httponly (no JS access), samesite (CSRF protection). Security: use httponly + secure + samesite=Strict for auth cookies. Store sessions in Redis for horizontal scaling.
Laravel is PHP's most popular MVC framework offering Eloquent ORM, Blade templating, routing, middleware, and built-in auth.
Core features: (1) Eloquent ORM: ActiveRecord pattern, relationships (hasMany, belongsTo), scopes, accessors/mutators. (2) Blade templates: {{ $var }}, @if/@foreach directives, component-based with <x-layout>. (3) Routing: Route::get('/users', [UserController::class, 'index']). (4) Middleware: auth, throttle, CORS. (5) Artisan CLI: make:model, migrate, tinker. (6) Migrations: database version control. (7) Queue: background jobs (Redis, SQS). (8) Events/Listeners. (9) Testing: PHPUnit + factories. (10) Sanctum/Passport for API auth. Laravel follows convention over configuration.
Named arguments pass values by parameter name; match is a strict comparison expression replacing verbose switch statements.
Named arguments: htmlspecialchars(string: $str, double_encode: false) — skip optional params, self-documenting, order-independent. match expression: $result = match($status) { 'active' => 'green', 'inactive' => 'red', default => 'gray' }. match vs switch: (1) strict comparison (===). (2) returns a value. (3) no fall-through (no break needed). (4) UnhandledMatchError if no match. Combined: match(true) { $age >= 18 => 'adult', $age >= 13 => 'teen', default => 'child' }. Both introduced in PHP 8.0.
Fibers (PHP 8.1) are lightweight cooperative threads that can pause and resume execution, enabling async patterns.
Fiber::start(): begins execution. Fiber::suspend(): pauses, returns control to caller. Fiber::resume(): continues from suspension point. Unlike threads: cooperative (not preemptive), single-threaded, must explicitly yield. Used by frameworks: ReactPHP, Amphp, Swoole for async I/O. Before Fibers: Generator-based coroutines. Fibers enable: async HTTP requests, concurrent database queries, event loops. Fiber vs Generator: Fibers can suspend from any call depth (not just yield in generator function). Practically: most developers use framework abstractions built on Fibers.
PHP enums are first-class types representing a fixed set of values with optional backing types and interface implementation.
Basic enum: enum Status { case Active; case Inactive; }. Backed enum: enum Status: string { case Active = 'active'; case Inactive = 'inactive'; }. Methods: enum can have methods, implement interfaces, use traits. Status::from('active') creates from value (throws on invalid). Status::tryFrom('active') returns null on invalid. Status::cases() returns all cases. Cannot instantiate with new. Comparison: === works. Serialization via backed values. Use in function signatures: function setStatus(Status $status). Replaces class constants for fixed sets.
Enable OPcache, optimize database queries, use caching (Redis), profile with Xdebug/Blackfire, and implement queue processing.
Steps: (1) OPcache: precompiles PHP to bytecode (huge impact). (2) Profiling: Xdebug or Blackfire to find bottlenecks. (3) Database: Eloquent N+1 (use eager loading), add indexes, query caching. (4) Application caching: Redis/Memcached for computed data, full-page cache. (5) Queue: move slow operations (emails, image processing) to background jobs. (6) PHP-FPM tuning: pm.max_children based on RAM. (7) Preloading (PHP 7.4+): load framework files once at startup. (8) JIT (PHP 8.0+): better for CPU-intensive code. (9) CDN for static assets. (10) Horizontal scaling with load balancer.
Validate input, use prepared statements, escape output, implement CSRF tokens, use HTTPS, and follow OWASP guidelines.
Security measures: (1) SQL injection: prepared statements (PDO::prepare, Eloquent). (2) XSS: htmlspecialchars() on output, Content-Security-Policy header. (3) CSRF: token validation on forms. (4) File uploads: validate MIME type, rename files, store outside webroot. (5) Authentication: password_hash/password_verify (bcrypt). (6) Sessions: regenerate ID on login, httponly cookies, SameSite. (7) HTTPS: force with HSTS header. (8) Dependencies: composer audit for vulnerabilities. (9) Headers: X-Content-Type-Options, X-Frame-Options. (10) Rate limiting on login/API endpoints.
WordPress uses hooks (actions and filters) for extensibility — plugins register callbacks that WordPress calls at specific execution points.
Actions: add_action('init', 'my_function') — execute code at specific points. do_action('hook_name') triggers. Filters: add_filter('the_content', 'modify_content') — modify data passing through. apply_filters('hook_name', $value) triggers. Priority: third parameter controls execution order (default 10, lower = earlier). Plugin structure: main file with header comment, activation/deactivation hooks, uninstall.php. Best practices: prefix functions, use classes/namespaces, sanitize/validate/escape data, use nonces for security, follow WordPress coding standards.
Generators use yield to produce values lazily one at a time, drastically reducing memory usage for large datasets.
Syntax: function range(int $start, int $end): Generator { for ($i=$start; $i<=$end; $i++) yield $i; }. yield pauses function, saves state, resumes on next iteration. yield $key => $value for key-value pairs. yield from delegates to sub-generator or array. Memory: generating 1M items uses constant memory (vs array using ~100MB). Use with foreach: foreach (range(1, 1000000) as $num). send() injects values. return value accessible via getReturn(). Use for: file reading line by line, database cursor iteration, API pagination, data transformation pipelines.
Attributes (PHP 8.0) add structured metadata to classes, methods, and properties, replacing PHPDoc annotations with native syntax.
Syntax: #[Route('/users', methods: ['GET'])] or #[Deprecated('Use newMethod instead')]. Define: #[Attribute] class Route { public function __construct(public string $path) {} }. Read: ReflectionClass->getAttributes(). Targets: TARGET_CLASS, TARGET_METHOD, TARGET_PROPERTY, TARGET_PARAMETER, TARGET_FUNCTION. Built-in: #[Deprecated], #[ReturnTypeWillChange], #[SensitiveParameter] (PHP 8.2). Frameworks: Symfony routes/validation, Doctrine ORM mapping. Replace: PHPDoc annotations (@ syntax), less error-prone, IDE support, validated at parse time.
Use a framework (Laravel/Slim), proper HTTP methods and status codes, JSON responses, authentication, and versioning.
Laravel API: Route::apiResource('users', UserController::class). Controller: index (GET), store (POST), show (GET), update (PUT/PATCH), destroy (DELETE). Resources: JsonResource for response transformation. Validation: FormRequest classes. Auth: Sanctum (token-based) or Passport (OAuth2). Versioning: /api/v1/ prefix or Accept header. Pagination: ->paginate(15). Rate limiting: throttle middleware. Documentation: Scribe or L5-Swagger. Error handling: custom exception handler with consistent JSON errors. Testing: Feature tests with actingAs(), assertJson(), assertStatus().
DI provides dependencies externally rather than creating them internally, improving testability and loose coupling.
Constructor injection: class UserService { public function __construct(private UserRepository $repo) {} }. Laravel container: app()->bind(Interface::class, Implementation::class). Auto-resolution: type-hinted constructor params resolved automatically. Singleton: app()->singleton(Service::class). Contextual binding: different implementation per consumer. Service providers: register bindings in boot/register methods. Benefits: testable (mock dependencies), swappable implementations, single responsibility. PHP-DI, Symfony DI, Laravel container are popular implementations. PSR-11 defines container interface.
Composer is PHP's dependency manager — it resolves, downloads, and autoloads project libraries using composer.json.
composer.json: declares dependencies with version constraints (^8.0, ~2.1, >=1.0). composer.lock: locks exact versions for reproducibility. Commands: require (add package), install (from lock file), update (resolve new versions), dump-autoload. Version constraints: ^ (compatible), ~ (patch-level), exact (1.2.3). Repositories: Packagist (default), private via Satis. Autoloading: PSR-4 namespace→directory mapping. Scripts: post-install/update hooks. Stability: minimum-stability setting. Platform requirements: php version, extensions. Best practices: commit lock file, use composer audit for security.
PHP uses reference counting for memory management with a cycle-collecting garbage collector for circular references.
Reference counting: each value has refcount, freed when count reaches 0. Copy-on-write: assignment doesn't copy until modification. Circular references: A->B->A prevents refcount reaching 0. Cycle collector (gc_collect_cycles): detects and frees circular references. Memory limit: ini_set('memory_limit', '256M'). memory_get_usage() / memory_get_peak_usage() for monitoring. Optimizations: unset() large variables, generators for large datasets, streaming instead of loading entire files. PHP 8.1+: fibers each have their own stack. Objects and arrays are most memory-intensive.
Use PHPUnit for unit tests, Pest for BDD-style, mock dependencies, test database with transactions, and run in CI.
PHPUnit: class UserTest extends TestCase { public function test_create_user(): void { ... } }. Pest: test('creates user', function() { ... }); — more readable syntax. Mocking: $mock = $this->createMock(Service::class); $mock->method('find')->willReturn($user). Laravel: RefreshDatabase trait, factories for test data, actingAs() for auth, $this->postJson('/api/users', $data)->assertStatus(201). Coverage: phpunit --coverage-html. Static analysis: PHPStan/Psalm (type safety without running code). Integration: test full HTTP requests. E2E: Laravel Dusk (browser testing). CI: run tests, static analysis, code style (PHP CS Fixer) on every PR.
Common: Repository, Service Layer, Factory, Observer (Events), Strategy, Decorator patterns — often facilitated by frameworks.
Repository: abstract database access behind interface (UserRepository). Service Layer: business logic in service classes (OrderService). Factory: Laravel model factories for test data, abstract object creation. Observer: Laravel events/listeners, model observers. Strategy: payment processors (StripeStrategy, PayPalStrategy). Decorator: middleware chain wrapping request handlers. Singleton: application container. Builder: query builder (DB::table()->where()->get()). Adapter: wrapping third-party APIs with consistent interface. MVC: controller → service → repository pattern is standard in modern PHP.
Use migration tools (Laravel Artisan, Doctrine) to version-control schema changes with up/down methods and run them in sequence.
Laravel: php artisan make:migration create_users_table. Migration class: up() method applies changes, down() reverses. Schema builder: Schema::create('users', function(Blueprint $table) { $table->id(); $table->string('email')->unique(); $table->timestamps(); }). Commands: migrate (apply), migrate:rollback (undo last), migrate:fresh (drop all + re-run). Production: never use migrate:fresh, always test down() method, avoid destructive changes without data migration. Seeder: DatabaseSeeder for initial/test data. Squash old migrations: php artisan schema:dump.
Ready to master Php?
Start learning with our comprehensive course and practice these questions.