PHP Interview Questions

44 questions with detailed answers

Question:
Who is father of PHP?
Answer:

The father of PHP is Rasmus Lerdorf.

Background:

  • Created PHP in 1994 as "Personal Home Page"
  • Originally a set of Common Gateway Interface (CGI) binaries written in C
  • Later evolved into "PHP: Hypertext Preprocessor" (recursive acronym)

Evolution Timeline:

1994: PHP/FI (Personal Home Page/Forms Interpreter)
1997: PHP/FI 2.0 - Zeev Suraski and Andi Gutmans joined
1998: PHP 3.0 - Complete rewrite
2000: PHP 4.0 - Zend Engine
2004: PHP 5.0 - Zend Engine II, OOP support
2015: PHP 7.0 - Major performance improvements
2020: PHP 8.0 - JIT compiler, union types
2023: PHP 8.3 - Latest stable version

Current Status: PHP powers over 70% of websites worldwide, including Facebook, Wikipedia, and WordPress.

Question:
what is session?
Answer:

A session is a server-side storage mechanism that maintains user data across multiple HTTP requests.

How Sessions Work:

// Start a session
session_start();

// Store data in session
$_SESSION["username"] = "john_doe";
$_SESSION["user_id"] = 123;
$_SESSION["role"] = "admin";

// Access session data
echo "Welcome " . $_SESSION["username"];

// Check if session variable exists
if (isset($_SESSION["user_id"])) {
    echo "User is logged in";
}

// Destroy session
session_destroy();

Session Configuration:

// Set session parameters
ini_set("session.cookie_lifetime", 3600); // 1 hour
ini_set("session.gc_maxlifetime", 3600);
ini_set("session.cookie_secure", 1); // HTTPS only
ini_set("session.cookie_httponly", 1); // No JavaScript access

// Custom session handler
session_set_save_handler(
    "session_open",
    "session_close", 
    "session_read",
    "session_write",
    "session_destroy",
    "session_gc"
);

Benefits: Server-side security, larger storage capacity, automatic cleanup, cross-page data persistence.

Question:
In PHP, what is PEAR?
Answer:

PEAR (PHP Extension and Application Repository) is a framework and distribution system for reusable PHP components.

Installation and Usage:

// Install PEAR package
pear install Mail
pear install DB

// Using PEAR Mail package
require_once "Mail.php";

$recipients = "user@example.com";
$headers["From"] = "sender@example.com";
$headers["Subject"] = "Test Email";
$body = "This is a test email";

$mail = Mail::factory("smtp", [
    "host" => "smtp.gmail.com",
    "port" => 587,
    "auth" => true,
    "username" => "your_email@gmail.com",
    "password" => "your_password"
]);

$result = $mail->send($recipients, $headers, $body);

PEAR Database Example:

require_once "DB.php";

$dsn = "mysql://username:password@localhost/database";
$db = DB::connect($dsn);

if (PEAR::isError($db)) {
    die("Connection failed: " . $db->getMessage());
}

// Execute query
$result = $db->query("SELECT * FROM users WHERE active = 1");
while ($row = $result->fetchRow()) {
    echo $row[0] . " - " . $row[1] . "\n";
}

Modern Alternative: Composer has largely replaced PEAR for dependency management in modern PHP development.

Question:
Describe different errors in PHP?
Answer:

Fatal errors:
These are critical errors. Example: instantiating an object of a class which does not exist or a non-existent function is called. These errors results in termination of the script immediately and default behavior of PHP is shown to them when they take place. Twelve different error types are used to represent these variations internally.

Warnings:
These are serious errors. Example: attempting to include () file which is not available. These errors are showed to the user by default but they will not result in ending the script.

Notices:
These errors are non-critical and trivial errors that come across while executing the script in PHP. Example: trying to gain access the variable which is not defined. These errors are not showed to the users by default even if the default behavior is changed.

Question:
How a cookie is destroyed?
Answer:

A cookie is destroyed by setting its expiration time to a past date.

Methods to Destroy Cookies:

// Method 1: Set expiration to past time
setcookie("username", "", time() - 3600); // 1 hour ago
setcookie("user_id", "", time() - 1); // 1 second ago

// Method 2: Set expiration to Unix epoch
setcookie("session_token", "", 1);

// Method 3: Using current time minus any value
setcookie("preferences", "", time() - 86400); // 24 hours ago

Complete Cookie Management:

// Create cookie with expiration
setcookie("user_data", "john_doe", [
    "expires" => time() + 3600, // 1 hour
    "path" => "/",
    "domain" => ".example.com",
    "secure" => true, // HTTPS only
    "httponly" => true, // No JavaScript access
    "samesite" => "Strict" // CSRF protection
]);

// Check if cookie exists
if (isset($_COOKIE["user_data"])) {
    echo "Cookie value: " . $_COOKIE["user_data"];
}

// Destroy specific cookie
function destroyCookie($name, $path = "/", $domain = "") {
    setcookie($name, "", [
        "expires" => time() - 3600,
        "path" => $path,
        "domain" => $domain
    ]);
    unset($_COOKIE[$name]);
}

// Destroy all cookies
foreach($_COOKIE as $name => $value) {
    destroyCookie($name);
}

Important: The path and domain must match the original cookie settings for successful deletion.

Question:
Differentiate require and include?
Answer:

Both require and include are used for file inclusion, but they handle errors differently.

Key Differences:

Featureincluderequire
Error HandlingWarning (E_WARNING)Fatal Error (E_COMPILE_ERROR)
Script ExecutionContinues after errorStops after error
Use CaseOptional filesCritical files

Practical Examples:

// include - script continues even if file not found
include "optional_config.php";
echo "This will execute even if file missing";

// require - script stops if file not found  
require "database_config.php";
echo "This won't execute if file missing";

// include_once - includes file only once
include_once "functions.php";
include_once "functions.php"; // Won't include again

// require_once - requires file only once
require_once "constants.php";
require_once "constants.php"; // Won't require again

Best Practices:

// Use require for critical files
require_once "config/database.php";
require_once "classes/User.php";

// Use include for optional files
include "templates/header.php";
include "widgets/sidebar.php";

// Error handling with include
if (!include "optional_module.php") {
    echo "Module not available, using default";
}

Performance: require_once and include_once are slightly slower due to file tracking overhead.

Question:
In PHP, header () function is used for what?
Answer:

The header() function sends raw HTTP headers to the client browser.

Common Use Cases:

// 1. Page Redirection
header("Location: https://example.com/dashboard");
exit(); // Always use exit after redirect

// 2. Set Content Type
header("Content-Type: application/json");
echo json_encode(["status" => "success"]);

// 3. Force File Download
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"report.pdf\"");
header("Content-Length: " . filesize("report.pdf"));
readfile("report.pdf");

// 4. Cache Control
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");

// 5. HTTP Status Codes
header("HTTP/1.1 404 Not Found");
header("HTTP/1.1 500 Internal Server Error");

Security Headers:

// CORS headers
header("Access-Control-Allow-Origin: https://trusted-site.com");
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization");

// Security headers
header("X-Frame-Options: DENY");
header("X-XSS-Protection: 1; mode=block");
header("X-Content-Type-Options: nosniff");
header("Strict-Transport-Security: max-age=31536000");

// Content Security Policy
header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'");

Important Notes:

  • Must be called before any output (HTML, echo, print)
  • Use exit() after redirect headers
  • Headers are case-insensitive
  • Can be overwritten by calling header() again

Question:
Differentiate GET and POST methods?
Answer:

GET and POST are HTTP methods for sending data between client and server.

Detailed Comparison:

FeatureGETPOST
Data LocationURL query stringRequest body
Data Limit~2048 charactersNo practical limit
SecurityLess secure (visible)More secure (hidden)
CachingCan be cachedNot cached
BookmarkingCan be bookmarkedCannot be bookmarked
IdempotentYesNo

GET Method Examples:

// URL: https://example.com/search.php?q=php&category=tutorial
// Accessing GET data
$searchQuery = $_GET["q"] ?? "";
$category = $_GET["category"] ?? "all";

// Validate and sanitize
$searchQuery = filter_var($searchQuery, FILTER_SANITIZE_STRING);
if (strlen($searchQuery) > 100) {
    $searchQuery = substr($searchQuery, 0, 100);
}

// Build search results
$results = searchDatabase($searchQuery, $category);

POST Method Examples:

// HTML Form
<form method="POST" action="process.php">
    <input type="text" name="username" required>
    <input type="password" name="password" required>
    <input type="submit" value="Login">
</form>

// Processing POST data
if ($_SERVER["REQUEST_METHOD"] === "POST") {
    $username = filter_input(INPUT_POST, "username", FILTER_SANITIZE_STRING);
    $password = $_POST["password"];
    
    // Validate
    if (empty($username) || empty($password)) {
        $error = "All fields are required";
    } else {
        // Process login
        $user = authenticateUser($username, $password);
    }
}

When to Use:

  • GET: Search, filtering, pagination, public data retrieval
  • POST: Login, registration, file uploads, data modification

Question:
How PHP script is executed using command line?
Answer:

You must run command line interface program of PHP and file name of PHP script is given as the command line argument.

Question:
Differentiate procedure oriented and object oriented languages?
Answer:

In general, there is much difference between procedure oriented and object oriented languages

  • It is very difficult to use design patterns such as singleton pattern, MVC etc in procedure oriented language whereas in object oriented programming language it is very easy to develop design patterns.
  • In OOP languages the code can be reused using polymorphism and inheritance but it is not possible in procedure oriented language.
  • A new developer feels procedure oriented is easy but understanding whole software is complex when compared to object oriented model.

Question:

What is the maximum length of a table name, database name, and fieldname in mysql?

Answer:

Database name- 64
Table name -64
Fieldname-64

Question:

What is maximum size of a database in mysql?

Answer:

The effective maximum table size for MySQL databases is usually determined by operating system constraints on file sizes, not by MySQL internal limits. The following table lists some examples of operating system file-size limits. This is only a rough guide and is not intended to be definitive. For the most up-to-date information, be sure to check the documentation specific to your operating system.
Operating System    File-size Limit
Win32 w/ FAT/FAT32    2GB/4GB
Win32 w/ NTFS            2TB (possibly larger)
Linux 2.2-Intel 32-bit    2GB (LFS: 4GB)
Linux 2.4+            (using ext3 file system) 4TB
Solaris 9/10            16TB
Mac OS X w/ HFS+    2TB

Question:

What is the difference between JavaScript and PHP?

Answer:

The difference lies with the execution of the languages. PHP is server side scripting language, which
means that it can’t interact directly with the user. Whereas, JavaScript is client side scripting
language, that is used to interact directly with the user..

Question:

Why PHP is also called Scripting language?

Answer:

PHP is basically a general purpose language, which is used to write scripts. Scripts are normal computer files that consist of instructions written in PHP language. It tells the computer to execute the file and give the output on the screen.
PHP is used for webpages and to create websites, thus included as scripting language.

Question:

How to use HTTP Headers inside PHP?

Answer:

HTTP headers can be used in PHP by redirection which is written as:
<?header('Location: http://www.php.com')?> The headers can be added to HTTP response in PHP using the header(). The HTTP headers have to be sent before taking the output of any data. The statement above gets included at the top of the script.

Question:

What is meant by MIME?

Answer:

Multipurpose Internet Mail Extensions.
WWW ability to recognise and handle files of different types is largely dependent on the use of the MIME (Multipurpose Internet Mail Extensions) standard. The standard provides for a system of registration of file types with information about the applications needed to process them. This information is incorporated into Web server and browser software, and enables the automatic recognition and display of registered file types.

Question:
Explain the difference between include, include_once, require, and require_once in PHP.
Answer:
include: Includes a file, continues execution if file not found (warning).\ninclude_once: Same as include but includes file only once.\nrequire: Includes a file, stops execution if file not found (fatal error).\nrequire_once: Same as require but includes file only once.\n\nUse require/require_once for critical files (like config files).\nUse include/include_once for optional files (like templates).\n\nExample:\nrequire_once 'config.php'; // Critical file\ninclude 'header.php'; // Optional template

Question:
Explain PHP traits and when to use them.
Answer:
Traits are a mechanism for code reuse in PHP. They allow you to include methods in multiple classes without using inheritance.\n\nExample:\ntrait Logger {\n public function log($message) {\n echo "Log: $message";\n }\n}\n\nclass User {\n use Logger;\n}\n\nclass Product {\n use Logger;\n}\n\n$user = new User();\n$user->log("User created"); // Works!\n\nTraits solve the problem of multiple inheritance and promote code reuse.

Question:
Explain dependency injection in PHP and its benefits.
Answer:
Dependency injection is a design pattern where dependencies are provided to a class rather than the class creating them itself.\n\nBenefits:\n- Loose coupling\n- Easier testing\n- Better maintainability\n- Follows SOLID principles\n\nExample:\nclass EmailService {\n public function send($message) { /* ... */ }\n}\n\nclass UserController {\n private $emailService;\n \n public function __construct(EmailService $emailService) {\n $this->emailService = $emailService;\n }\n}\n\n// Dependency is injected\n$controller = new UserController(new EmailService());

Question:
Explain visibility modifiers in PHP classes.
Answer:
public: Accessible from anywhere\nprivate: Only accessible within the same class\nprotected: Accessible within the class and its subclasses\n\nExample:\nclass MyClass {\n public $publicVar = "Everyone can see this";\n private $privateVar = "Only MyClass can see this";\n protected $protectedVar = "MyClass and subclasses can see this";\n}\n\nclass ChildClass extends MyClass {\n public function test() {\n echo $this->publicVar; // OK\n echo $this->protectedVar; // OK\n echo $this->privateVar; // Error!\n }\n}

Question:
Explain Composer in PHP and its role in dependency management.
Answer:
Composer is a dependency manager for PHP. It allows you to declare libraries your project depends on and manages them for you.\n\nKey files:\n- composer.json: Defines dependencies\n- composer.lock: Locks specific versions\n- vendor/: Contains downloaded packages\n\nBasic commands:\ncomposer install // Install dependencies\ncomposer update // Update dependencies\ncomposer require vendor/package // Add new dependency\n\nAutoloading:\nrequire_once "vendor/autoload.php";\n\nBenefits: Version management, autoloading, easy package installation.

Question:

What is the difference between include and require?

Answer:

include: Includes a file, continues execution if file not found (warning).\ninclude_once: Same as include but includes file only once.\nrequire: Includes a file, stops execution if file not found (fatal error).\nrequire_once: Same as require but includes file only once.\n\nUse require/require_once for critical files (like config files).\nUse include/include_once for optional files (like templates).\n\nExample:\nrequire_once 'config.php'; // Critical file\ninclude 'header.php'; // Optional template

Question:

What are PHP traits?

Answer:

Traits are a mechanism for code reuse in PHP. They allow you to include methods in multiple classes without using inheritance.\n\nExample:\ntrait Logger {\n public function log($message) {\n echo "Log: $message";\n }\n}\n\nclass User {\n use Logger;\n}\n\nclass Product {\n use Logger;\n}\n\n$user = new User();\n$user->log("User created"); // Works!\n\nTraits solve the problem of multiple inheritance and promote code reuse.

Question:

What is dependency injection?

Answer:

Dependency injection is a design pattern where dependencies are provided to a class rather than the class creating them itself.\n\nBenefits:\n- Loose coupling\n- Easier testing\n- Better maintainability\n- Follows SOLID principles\n\nExample:\nclass EmailService {\n public function send($message) { /* ... */ }\n}\n\nclass UserController {\n private $emailService;\n \n public function __construct(EmailService $emailService) {\n $this->emailService = $emailService;\n }\n}\n\n// Dependency is injected\n$controller = new UserController(new EmailService());

Question:

What is the difference between public, private, and protected?

Answer:

public: Accessible from anywhere\nprivate: Only accessible within the same class\nprotected: Accessible within the class and its subclasses\n\nExample:\nclass MyClass {\n public $publicVar = "Everyone can see this";\n private $privateVar = "Only MyClass can see this";\n protected $protectedVar = "MyClass and subclasses can see this";\n}\n\nclass ChildClass extends MyClass {\n public function test() {\n echo $this->publicVar; // OK\n echo $this->protectedVar; // OK\n echo $this->privateVar; // Error!\n }\n}

Question:
Describe features and benefits of object oriented programming?
Answer:

The major advantage of object oriented programming is code reuseability and easy of modification. Modification and adding of objects is easy thereby reducing the maintenance cost. Modeling the real world is better using object oriented programming than procedure-oriented programming.

Question:

What is Composer and how does it work?

Answer:

Composer is a dependency manager for PHP. It allows you to declare libraries your project depends on and manages them for you.\n\nKey files:\n- composer.json: Defines dependencies\n- composer.lock: Locks specific versions\n- vendor/: Contains downloaded packages\n\nBasic commands:\ncomposer install // Install dependencies\ncomposer update // Update dependencies\ncomposer require vendor/package // Add new dependency\n\nAutoloading:\nrequire_once "vendor/autoload.php";\n\nBenefits: Version management, autoloading, easy package installation.

Question:

How can we increase the execution time of a php script?

Answer:


Set max_execution_time variable in php.ini file to your desired time in second.

Question:

How do you make one way encryption for your passwords in PHP?

Answer:

Using md5 function or sha1 function

Question:

What is difference between mysql_connect and mysql_pconnect ?

Answer:

Mysql_connect opens up a database connection every time a page is loaded. mysql_pconnect opens up a connection, and keeps it open across multiple requests.

Mysql_pconnect uses less resources, because it does not need to establish a database connection every time a page is loaded.

Question:

What are the statements that are used to connect PHP files with MySQL

Answer:

The statements that can be used to connect PHP with MySQL are:
<?
$con = mysql_connect("localhost","root","")
echo $conn;
?>

This statement gets the resource of the localhost.

Question:

How can we submit a form without a submit button?

Answer:

Forms can be submitted without a submit button using JavaScript.

JavaScript Methods:

// Method 1: Using form.submit()
<form id="myForm" action="process.php" method="POST">
    <input type="text" name="username">
    <button type="button" onclick="submitForm()">Submit</button>
</form>

<script>
function submitForm() {
    document.getElementById("myForm").submit();
}
</script>

// Method 2: Auto-submit on change
<form id="autoForm" action="filter.php" method="GET">
    <select name="category" onchange="this.form.submit()">
        <option value="all">All Categories</option>
        <option value="php">PHP</option>
        <option value="javascript">JavaScript</option>
    </select>
</form>

Advanced JavaScript Submission:

// Method 3: Using AJAX
function submitFormAjax() {
    const form = document.getElementById("myForm");
    const formData = new FormData(form);
    
    fetch("process.php", {
        method: "POST",
        body: formData
    })
    .then(response => response.json())
    .then(data => {
        console.log("Success:", data);
        // Handle response
    })
    .catch(error => {
        console.error("Error:", error);
    });
}

// Method 4: Programmatic form creation and submission
function createAndSubmitForm(data) {
    const form = document.createElement("form");
    form.method = "POST";
    form.action = "process.php";
    
    for (const key in data) {
        const input = document.createElement("input");
        input.type = "hidden";
        input.name = key;
        input.value = data[key];
        form.appendChild(input);
    }
    
    document.body.appendChild(form);
    form.submit();
    document.body.removeChild(form);
}

Event-Based Submission:

// Submit on Enter key
<input type="text" onkeypress="if(event.key==='Enter') document.forms[0].submit()">

// Submit after timer
setTimeout(() => {
    document.getElementById("timedForm").submit();
}, 5000); // Submit after 5 seconds

// Submit on page unload
window.addEventListener("beforeunload", () => {
    document.getElementById("trackingForm").submit();
});

Security Considerations: Always validate and sanitize data on the server side, regardless of client-side submission method.

Question:
Explain PHP 8.3's new features including typed class constants, dynamic class constant fetch, and readonly amendments. Provide practical examples.
Answer:

PHP 8.3 introduces several significant features:

1. Typed Class Constants:
You can now specify types for class constants, improving type safety:

class MyClass {
    public const string NAME = "MyClass";
    public const int VERSION = 1;
    public const array CONFIG = ["debug" => true];
}

2. Dynamic Class Constant Fetch:
Allows fetching class constants dynamically using variables:

class Status {
    const ACTIVE = "active";
    const INACTIVE = "inactive";
}

$constantName = "ACTIVE";
$value = Status::{$constantName}; // Returns "active"

3. Readonly Amendments:
- Readonly properties can now be reinitialized during cloning - Better support for readonly properties in inheritance - Improved readonly class behavior

Benefits: Enhanced type safety, better performance, improved developer experience, and more robust object-oriented programming capabilities.

Question:
Describe the implementation and use cases of PHP Fibers for asynchronous programming. How do they compare to traditional threading?
Answer:

PHP Fibers (introduced in PHP 8.1) enable cooperative multitasking:

Implementation:

$fiber = new Fiber(function (): void {
    $value = Fiber::suspend("Hello");
    echo "Fiber resumed with: " . $value;
});

$result = $fiber->start(); // "Hello"
echo $result;
$fiber->resume("World"); // Outputs: "Fiber resumed with: World"

Use Cases:

  • Asynchronous I/O operations
  • Non-blocking database queries
  • Concurrent HTTP requests
  • Event-driven programming
  • Implementing async/await patterns

Comparison with Threading:

  • Fibers: Cooperative, single-threaded, no race conditions, lower memory overhead
  • Threads: Preemptive, multi-threaded, potential race conditions, higher overhead
  • Fibers: Explicit suspension points, deterministic execution
  • Threads: OS-controlled scheduling, non-deterministic

Advantages: Better performance for I/O-bound operations, easier debugging, no need for locks or synchronization primitives.

Question:
Explain advanced PHP design patterns: Repository, Specification, and CQRS patterns. Provide implementation examples and discuss when to use each.
Answer:

Advanced PHP Design Patterns:

1. Repository Pattern:
Encapsulates data access logic and provides a uniform interface:

interface UserRepositoryInterface {
    public function find(int $id): ?User;
    public function save(User $user): void;
    public function findByEmail(string $email): ?User;
}

class DatabaseUserRepository implements UserRepositoryInterface {
    public function find(int $id): ?User {
        // Database query logic
        return $this->db->query("SELECT * FROM users WHERE id = ?", [$id]);
    }
    
    public function save(User $user): void {
        // Save logic
    }
}

2. Specification Pattern:
Encapsulates business rules and query logic:

interface SpecificationInterface {
    public function isSatisfiedBy($candidate): bool;
    public function toSql(): string;
}

class ActiveUserSpecification implements SpecificationInterface {
    public function isSatisfiedBy($user): bool {
        return $user->isActive() && $user->getLastLogin() > new DateTime("-30 days");
    }
    
    public function toSql(): string {
        return "status = 'active' AND last_login > DATE_SUB(NOW(), INTERVAL 30 DAY)";
    }
}

3. CQRS (Command Query Responsibility Segregation):
Separates read and write operations:

// Command side
class CreateUserCommand {
    public function __construct(
        public readonly string $email,
        public readonly string $name
    ) {}
}

class CreateUserHandler {
    public function handle(CreateUserCommand $command): void {
        $user = new User($command->email, $command->name);
        $this->userRepository->save($user);
    }
}

// Query side
class UserQuery {
    public function getUserById(int $id): UserReadModel {
        return $this->readModelRepository->find($id);
    }
}

When to Use:

  • Repository: Complex data access, testing, multiple data sources
  • Specification: Complex business rules, dynamic queries, reusable conditions
  • CQRS: High-performance applications, different read/write requirements, event sourcing

Question:
Discuss PHP performance optimization techniques for 2025, including OPcache configuration, JIT compilation, and memory management strategies.
Answer:

PHP Performance Optimization for 2025:

1. OPcache Configuration:

; php.ini optimizations
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0  ; Production only
opcache.save_comments=0
opcache.enable_file_override=1
opcache.huge_code_pages=1      ; Linux only

2. JIT (Just-In-Time) Compilation:

; Enable JIT in PHP 8.0+
opcache.jit_buffer_size=256M
opcache.jit=tracing           ; or "function" for function-level JIT

// Code optimization for JIT
function calculateFibonacci(int $n): int {
    if ($n <= 1) return $n;
    return calculateFibonacci($n - 1) + calculateFibonacci($n - 2);
}

3. Memory Management Strategies:

  • Object Pooling: Reuse expensive objects
  • Lazy Loading: Load data only when needed
  • Memory Profiling: Use Xdebug or Blackfire
  • Garbage Collection: Optimize gc_collect_cycles()

4. Advanced Techniques:

// Use generators for memory efficiency
function readLargeFile(string $filename): Generator {
    $handle = fopen($filename, "r");
    while (($line = fgets($handle)) !== false) {
        yield trim($line);
    }
    fclose($handle);
}

// Implement object caching
class CachedUserService {
    private array $cache = [];
    
    public function getUser(int $id): User {
        return $this->cache[$id] ??= $this->userRepository->find($id);
    }
}

5. Database Optimization:

  • Connection pooling with persistent connections
  • Query optimization and indexing
  • Database result caching
  • Read/write splitting

Monitoring: Use APM tools like New Relic, Datadog, or open-source alternatives like Jaeger for distributed tracing.

Question:
Explain modern PHP security practices for 2025, including input validation, CSRF protection, SQL injection prevention, and secure session management.
Answer:

Modern PHP Security Practices for 2025:

1. Input Validation & Sanitization:

// Use filter_var with strict validation
function validateEmail(string $email): bool {
    return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}

// Input sanitization
function sanitizeInput(string $input): string {
    return htmlspecialchars(trim($input), ENT_QUOTES, "UTF-8");
}

// Type declarations for strict typing
declare(strict_types=1);

function processUserData(int $userId, string $email): void {
    // Type safety enforced at runtime
}

2. CSRF Protection:

class CSRFProtection {
    public static function generateToken(): string {
        if (!isset($_SESSION["csrf_token"])) {
            $_SESSION["csrf_token"] = bin2hex(random_bytes(32));
        }
        return $_SESSION["csrf_token"];
    }
    
    public static function validateToken(string $token): bool {
        return isset($_SESSION["csrf_token"]) && 
               hash_equals($_SESSION["csrf_token"], $token);
    }
}

3. SQL Injection Prevention:

// Use prepared statements exclusively
class UserRepository {
    public function findByEmail(string $email): ?User {
        $stmt = $this->pdo->prepare("SELECT * FROM users WHERE email = ? AND status = ?");
        $stmt->execute([$email, "active"]);
        return $stmt->fetchObject(User::class) ?: null;
    }
    
    // For dynamic queries, use query builders
    public function findWithFilters(array $filters): array {
        $queryBuilder = new QueryBuilder();
        return $queryBuilder->select("*")
            ->from("users")
            ->where($filters)  // Automatically parameterized
            ->execute();
    }
}

4. Secure Session Management:

// Secure session configuration
ini_set("session.cookie_httponly", 1);
ini_set("session.cookie_secure", 1);
ini_set("session.cookie_samesite", "Strict");
ini_set("session.use_strict_mode", 1);
ini_set("session.gc_maxlifetime", 3600);

class SecureSession {
    public static function start(): void {
        session_start();
        
        // Regenerate session ID periodically
        if (!isset($_SESSION["last_regeneration"])) {
            self::regenerateId();
        } elseif (time() - $_SESSION["last_regeneration"] > 300) {
            self::regenerateId();
        }
    }
    
    private static function regenerateId(): void {
        session_regenerate_id(true);
        $_SESSION["last_regeneration"] = time();
    }
}

5. Additional Security Measures:

  • Content Security Policy: Implement strict CSP headers
  • Rate Limiting: Prevent brute force attacks
  • Password Hashing: Use password_hash() with strong algorithms
  • HTTPS Enforcement: Redirect all traffic to HTTPS
  • Security Headers: X-Frame-Options, X-XSS-Protection, etc.

6. Modern Authentication:

// JWT implementation with proper validation
class JWTAuth {
    public function createToken(User $user): string {
        $payload = [
            "sub" => $user->getId(),
            "iat" => time(),
            "exp" => time() + 3600,
            "aud" => "your-app.com"
        ];
        
        return JWT::encode($payload, $this->secretKey, "HS256");
    }
}

Question:
What will be the output of this PHP 8+ code? Explain the behavior of match expression with type juggling.
Answer:

Code Analysis:

$value = "2";
$result = match($value) {
    1 => "one",
    2 => "two", 
    "2" => "string two",
    default => "unknown"
};
echo $result;

Output: "two"

Explanation:

  • Match expressions use strict comparison (===) by default
  • Since $value is string "2", it matches the first case where 2 (integer) is compared
  • However, match does type coercion for the first matching case
  • The string "2" matches integer 2, so "two" is returned
  • If we had strict types enabled, this would behave differently

Key Difference from Switch: Match is exhaustive and uses strict comparison, but still allows type coercion in pattern matching.

Question:
Analyze this PHP code and explain the memory implications. What are the potential issues and how would you optimize it?
Answer:

Code Analysis:

function processLargeDataset($filename) {
    $data = file_get_contents($filename); // 100MB file
    $lines = explode("\n", $data);
    $results = [];
    
    foreach($lines as $line) {
        $processed = expensive_operation($line);
        $results[] = $processed;
    }
    
    return $results;
}

Memory Issues:

  • Memory Spike: file_get_contents() loads entire file into memory
  • Double Memory Usage: explode() creates another copy of data
  • Array Growth: $results array grows continuously
  • Peak Usage: Could reach 300MB+ for 100MB file

Optimized Solution:

function processLargeDatasetOptimized($filename): Generator {
    $handle = fopen($filename, "r");
    if (!$handle) throw new Exception("Cannot open file");
    
    try {
        while (($line = fgets($handle)) !== false) {
            yield expensive_operation(trim($line));
        }
    } finally {
        fclose($handle);
    }
}

// Usage with memory control
foreach(processLargeDatasetOptimized($filename) as $result) {
    // Process one result at a time
    // Memory usage remains constant
}

Benefits: Constant memory usage, lazy evaluation, better performance for large datasets.

Question:
Explain PHP 8+ Attributes with a practical example. How do they differ from annotations and what are their performance implications?
Answer:

PHP Attributes (PHP 8.0+):

Practical Example - API Route Mapping:

#[Attribute(Attribute::TARGET_METHOD)]
class Route {
    public function __construct(
        public string $method,
        public string $path,
        public array $middleware = []
    ) {}
}

#[Attribute(Attribute::TARGET_PARAMETER)]
class Validate {
    public function __construct(public string $rules) {}
}

class UserController {
    #[Route("POST", "/users", ["auth", "throttle"])]
    public function create(
        #[Validate("required|email")] string $email,
        #[Validate("required|min:8")] string $password
    ): User {
        return User::create(compact("email", "password"));
    }
}

// Attribute Processing
class RouteProcessor {
    public function processController(string $className): array {
        $reflection = new ReflectionClass($className);
        $routes = [];
        
        foreach($reflection->getMethods() as $method) {
            $attributes = $method->getAttributes(Route::class);
            foreach($attributes as $attribute) {
                $route = $attribute->newInstance();
                $routes[] = [
                    "method" => $route->method,
                    "path" => $route->path,
                    "handler" => [$className, $method->getName()],
                    "middleware" => $route->middleware
                ];
            }
        }
        return $routes;
    }
}

Differences from Annotations:

  • Native Support: Built into PHP, no parsing needed
  • Type Safety: Attributes are actual PHP classes
  • Performance: Compiled into opcache, faster than docblock parsing
  • IDE Support: Full autocompletion and refactoring

Performance Implications:

  • Compile Time: Minimal overhead, cached in opcache
  • Runtime: Only accessed via Reflection API when needed
  • Memory: Stored efficiently in opcache metadata

Question:
What is the output of this PHP code? Explain reference behavior and memory management.
Answer:

Code Analysis:

$a = ["x" => 1, "y" => 2];
$b = &$a;
$c = $a;

$a["x"] = 10;
$c["y"] = 20;

unset($a);

var_dump($b);
var_dump($c);

Output:

array(2) {
  ["x"]=> int(10)
  ["y"]=> int(2)
}
array(2) {
  ["x"]=> int(1)
  ["y"]=> int(20)
}

Explanation:

  1. $b = &$a: $b becomes a reference to $a (same memory location)
  2. $c = $a: $c gets a copy of $a (copy-on-write)
  3. $a["x"] = 10: Modifies original array, affects both $a and $b
  4. $c["y"] = 20: Triggers copy-on-write, $c becomes independent
  5. unset($a): Removes $a variable, but $b still references the data

Memory Management:

  • Copy-on-Write: PHP optimizes memory by sharing data until modification
  • Reference Counting: Memory freed when all references are removed
  • Zval Structure: Each variable has reference count and type information

Best Practices:

  • Use references sparingly to avoid confusion
  • Understand copy-on-write behavior for large arrays
  • Use unset() to free memory when working with large datasets

Question:
Implement a thread-safe singleton pattern in PHP using modern techniques. Discuss the challenges and alternatives.
Answer:

Thread-Safe Singleton Implementation:

final class DatabaseConnection {
    private static ?self $instance = null;
    private static object $lock;
    private PDO $connection;
    
    private function __construct() {
        // Initialize lock object for thread safety
        if (!isset(self::$lock)) {
            self::$lock = new stdClass();
        }
        
        $this->connection = new PDO(
            "mysql:host=localhost;dbname=app",
            "user", "password",
            [PDO::ATTR_PERSISTENT => true]
        );
    }
    
    public static function getInstance(): self {
        if (self::$instance === null) {
            // Double-checked locking pattern
            synchronized(self::$lock, function() {
                if (self::$instance === null) {
                    self::$instance = new self();
                }
            });
        }
        return self::$instance;
    }
    
    public function getConnection(): PDO {
        return $this->connection;
    }
    
    // Prevent cloning and unserialization
    private function __clone() {}
    private function __wakeup() {}
    public function __serialize(): array {
        throw new Exception("Singleton cannot be serialized");
    }
}

Modern Alternative - Dependency Injection:

// Service Container Approach
class Container {
    private array $services = [];
    private array $singletons = [];
    
    public function singleton(string $abstract, callable $factory): void {
        $this->services[$abstract] = $factory;
        $this->singletons[$abstract] = true;
    }
    
    public function get(string $abstract): mixed {
        if (isset($this->singletons[$abstract])) {
            static $instances = [];
            return $instances[$abstract] ??= $this->services[$abstract]();
        }
        
        return $this->services[$abstract]();
    }
}

// Usage
$container = new Container();
$container->singleton(DatabaseConnection::class, fn() => new DatabaseConnection());

// Thread-safe through container
$db = $container->get(DatabaseConnection::class);

Challenges with Singleton:

  • Testing: Difficult to mock and test
  • Thread Safety: Requires synchronization in multi-threaded environments
  • Global State: Creates hidden dependencies
  • Scalability: Can become bottleneck in high-concurrency applications

Better Alternatives:

  • Dependency Injection: More testable and flexible
  • Service Locator: Centralized service management
  • Factory Pattern: Better control over object creation
  • Connection Pooling: For database connections specifically

Question:
Explain PHP's garbage collection mechanism. How does it handle circular references and what are the performance implications?
Answer:

PHP Garbage Collection Mechanism:

Reference Counting + Cycle Collection:

// Example of circular reference
class Node {
    public $data;
    public $parent;
    public $children = [];
    
    public function addChild(Node $child): void {
        $this->children[] = $child;
        $child->parent = $this; // Creates circular reference
    }
}

$root = new Node();
$child = new Node();
$root->addChild($child); // Circular reference created

// Without proper cleanup, this creates memory leak
unset($root, $child); // Variables removed but objects still referenced

How PHP Handles This:

  1. Reference Counting: Each zval has refcount
  2. Cycle Detection: When refcount decreases, check for cycles
  3. Mark & Sweep: Mark reachable objects, sweep unreachable ones

Garbage Collection Process:

// Manual GC control
gc_enable();           // Enable garbage collection
gc_collect_cycles();   // Force garbage collection
gc_disable();          // Disable garbage collection

// Monitor GC performance
$before = gc_status();
// ... your code ...
$after = gc_status();

echo "Cycles collected: " . ($after["collected"] - $before["collected"]);
echo "Memory freed: " . ($before["memory"] - $after["memory"]) . " bytes";

Performance Implications:

  • CPU Overhead: GC runs periodically, can cause pauses
  • Memory Overhead: Additional metadata for cycle detection
  • Threshold Based: GC triggers when root buffer fills (10,000 items)

Optimization Strategies:

// 1. Explicit cleanup for circular references
class Node {
    public function cleanup(): void {
        foreach($this->children as $child) {
            $child->parent = null;
            $child->cleanup();
        }
        $this->children = [];
    }
}

// 2. Weak references (PHP 7.4+)
class Parent {
    private WeakMap $children;
    
    public function __construct() {
        $this->children = new WeakMap();
    }
    
    public function addChild(Child $child): void {
        $this->children[$child] = true;
        // No strong reference, no circular dependency
    }
}

// 3. Use SplObjectStorage for object collections
$storage = new SplObjectStorage();
$storage->attach($object); // Weak reference-like behavior

Best Practices:

  • Avoid circular references when possible
  • Use weak references for parent-child relationships
  • Monitor memory usage in long-running processes
  • Consider manual gc_collect_cycles() in memory-intensive operations

Question:
What is the output of this PHP 8+ code involving anonymous classes and closures? Explain the scope and binding behavior.
Answer:

Code Analysis:

$multiplier = 10;

$calculator = new class($multiplier) {
    private $factor;
    
    public function __construct($factor) {
        $this->factor = $factor;
    }
    
    public function createMultiplier() {
        return function($value) {
            return $value * $this->factor;
        };
    }
    
    public function createStaticMultiplier() {
        $factor = $this->factor;
        return static function($value) use ($factor) {
            return $value * $factor;
        };
    }
};

$multiply1 = $calculator->createMultiplier();
$multiply2 = $calculator->createStaticMultiplier();

echo $multiply1(5) . "\n";
echo $multiply2(5) . "\n";

// Serialize test
try {
    serialize($multiply1);
    echo "multiply1 serializable\n";
} catch (Exception $e) {
    echo "multiply1 not serializable\n";
}

try {
    serialize($multiply2);
    echo "multiply2 serializable\n";
} catch (Exception $e) {
    echo "multiply2 not serializable\n";
}

Output:

50
50
multiply1 not serializable
multiply2 serializable

Explanation:

1. Anonymous Class Behavior:

  • Anonymous class captures $multiplier in constructor
  • Creates instance with private $factor = 10
  • Class has unique generated name like class@anonymous

2. Closure Binding:

  • createMultiplier(): Returns non-static closure bound to $this
  • createStaticMultiplier(): Returns static closure with captured variable
  • Both access the same value but through different mechanisms

3. Serialization Behavior:

  • $multiply1: Cannot serialize - bound to object instance
  • $multiply2: Can serialize - static closure with captured variables

Advanced Closure Concepts:

// Closure binding manipulation
$closure = function() {
    return $this->factor;
};

// Bind to different object
$boundClosure = $closure->bindTo($calculator, $calculator);
echo $boundClosure(); // 10

// Static binding
$staticClosure = Closure::bind($closure, null, get_class($calculator));
// $staticClosure(); // Error: $this not available in static context

Performance Considerations:

  • Object-bound closures keep object in memory
  • Static closures are more memory efficient
  • Use static closures when $this is not needed
Study Tips
  • Read each question carefully
  • Try to answer before viewing the solution
  • Practice explaining concepts out loud
  • Review regularly to reinforce learning
Share & Practice

Found this helpful? Share with others!

Feedback