PHP Interview Questions with Answers
Most Asked PHP Interview Questions for Software Engineer Roles
Introduction
PHP is a powerful server‑side scripting language used to build dynamic websites, web applications, and APIs. This page compiles the most frequently asked PHP interview questions, covering everything from basic syntax to advanced OOP, security, and framework concepts.
Why PHP?
- Server‑side scripting for dynamic web apps
- Huge ecosystem with Laravel, Symfony, WordPress
- Beginner‑friendly and well‑documented
- Excellent database integration (MySQL, PostgreSQL)
- Scalable – powers Facebook, Wikipedia, Etsy
- Strong community and open‑source
Most Asked PHP Interview Questions
PHP (Hypertext Preprocessor) is a widely-used open-source general-purpose scripting language especially suited for web development.
- Server-side scripting: Runs on web servers
- Dynamic typing: Flexible variable types
- Web development: Built-in for HTML integration
- Large ecosystem: Extensive package library
- Database integration: PDO, MySQLi
<?php
// Hello World in PHP
echo "Hello, World!";
?>Variables in PHP are declared using the $ symbol. PHP is dynamically typed, so type declarations are optional.
- Assignment:
$x = 10; - Dynamic typing: Types are inferred at runtime
- Constants:
define('PI', 3.14159); - Global scope: Variables defined at top level
- Local scope: Variables defined inside functions
<?php
// Variables in PHP
$x = 10; // Integer
$y = 3.14; // Float
$name = "PHP"; // String
$is_active = true; // Boolean
echo $x . "\n";
echo $y . "\n";
echo $name . "\n";
echo var_export($is_active, true) . "\n";
?>PHP supports various data types including scalar, compound, and special types.
- Integer:
int - Float:
float - String:
string - Boolean:
bool - Array:
array - Object:
object - NULL:
null - Resource:
resource
<?php
// Data Types in PHP
// Integer types
$a = 10; // int
$b = 127; // int
// Floating point
$d = 3.14; // float
$e = 2.5; // float
// String
$f = "Hello PHP";
// Boolean
$g = true;
$h = false;
// Array
$j = [1, "hello", 3.14];
// Indexed array
$k = [1, 2, 3, 4, 5];
// Associative array (dictionary)
$l = ["name" => "PHP", "version" => 8.2];
// Object
class Person {
public $name;
public $age;
}
$person = new Person();
$person->name = "Alice";
$person->age = 25;
// NULL
$m = null;
echo gettype($a) . "\n";
echo gettype($d) . "\n";
?>Functions in PHP are defined using the function keyword. They can have parameters, return values, and support type declarations.
- Function declaration:
function name($args) { ... } - Type declarations:
function add(int $a, int $b): int - Anonymous functions:
$fn = function($x) { return $x * 2; } - Arrow functions:
fn($x) => $x * 2 - Variable arguments:
function sum(...$numbers)
<?php
// Functions in PHP
// Function declaration
function add($a, $b) {
return $a + $b;
}
// Function with default parameters
function greet($name = "Guest") {
return "Hello, $name!";
}
// Anonymous function
$square = function($x) {
return $x * $x;
};
// Arrow function (PHP 7.4+)
$double = fn($x) => $x * 2;
// Function with variable number of arguments
function sum(...$numbers) {
return array_sum($numbers);
}
// Function with type declarations
function divide(float $a, float $b): float {
return $a / $b;
}
// Function returning multiple values (using array)
function getPerson() {
return ["name" => "Alice", "age" => 25];
}
echo add(5, 3) . "\n";
echo greet("Alice") . "\n";
echo $square(4) . "\n";
echo $double(5) . "\n";
echo sum(1, 2, 3, 4, 5) . "\n";
print_r(getPerson());
?>PHP arrays are ordered maps that can hold values of any type. They can be indexed or associative.
- Indexed arrays:
[1, 2, 3] - Associative arrays:
['name' => 'Alice'] - Multidimensional: Arrays within arrays
- Functions:
array_map,array_filter,array_reduce - Spread operator:
[...$arr1, ...$arr2]
<?php
// Arrays in PHP
$arr = [1, 2, 3, 4, 5];
// Map - transform each element
$doubled = array_map(fn($x) => $x * 2, $arr);
print_r($doubled);
// Filter - select elements
$evens = array_filter($arr, fn($x) => $x % 2 == 0);
print_r($evens);
// Reduce - aggregate
$sum = array_reduce($arr, fn($carry, $item) => $carry + $item, 0);
echo $sum . "\n";
// Array comprehension (using range and array_map)
$squares = array_map(fn($x) => $x * $x, range(1, 10));
print_r($squares);
// Push and pop
array_push($arr, 6);
print_r($arr);
array_pop($arr);
print_r($arr);
// Array operations
$a = [1, 2, 3];
$b = [4, 5, 6];
$c = array_map(fn($x, $y) => $x + $y, $a, $b);
print_r($c);
?>Associative arrays in PHP are arrays that use named keys instead of numeric indices, similar to dictionaries.
- Creation:
['name' => 'Alice', 'age' => 25] - Access:
$dict['name'] - Add/Update:
$dict['new_key'] = 'value' - Keys/Values:
array_keys,array_values - Check:
isset($dict['key'])
<?php
// Associative Arrays (Dictionaries) in PHP
// Create associative array
$person = ["name" => "Alice", "age" => 25, "city" => "NYC"];
// Access values
echo $person["name"] . "\n";
echo $person["age"] . "\n";
// Add/update values
$person["country"] = "USA";
$person["age"] = 26;
// Get with default
$city = $person["city"] ?? "Unknown";
// Keys and values
print_r(array_keys($person));
print_r(array_values($person));
// Iterate over associative array
foreach ($person as $key => $value) {
echo "$key: $value\n";
}
// Delete key
unset($person["country"]);
// Check if key exists
echo isset($person["name"]) ? "true" : "false";
echo "\n";
// Array comprehension (using range and array_combine)
$keys = range(1, 5);
$values = array_map(fn($x) => $x * $x, range(1, 5));
$squares = array_combine($keys, $values);
print_r($squares);
?>PHP arrays can be used as tuples by using ordered lists of values without keys.
- Creation:
[1, 'hello', 3.14] - Access:
$tuple[0] - Unpacking:
[$a, $b, $c] = $tuple - Named tuples: Use associative arrays
- Spread:
[...$t1, ...$t2]
<?php
// Arrays as Tuples in PHP
// Create tuple-like array
$t = [1, "hello", 3.14, true];
// Access elements
echo $t[0] . "\n";
echo $t[1] . "\n";
// Named array (like named tuple)
$person = ["name" => "Alice", "age" => 25, "city" => "NYC"];
echo $person["name"] . "\n";
echo $person["age"] . "\n";
// Array unpacking (PHP 7.4+)
[$a, $b, $c] = [10, 20, 30];
echo "$a, $b, $c\n";
// Function returning multiple values
function divide($a, $b) {
return [intdiv($a, $b), $a % $b];
}
[$quotient, $remainder] = divide(10, 3);
echo "Quotient: $quotient, Remainder: $remainder\n";
// Array concatenation
$t1 = [1, 2, 3];
$t2 = [4, 5, 6];
$t3 = [...$t1, ...$t2];
print_r($t3);
?>PHP provides standard control flow statements including conditionals, loops, and the match expression.
- If-else:
if ($condition) { ... } - Ternary:
$x = $condition ? 'yes' : 'no' - Match:
match($value) { 1 => 'one', default => 'other' } - For loops:
for ($i = 0; $i < 10; $i++) - Foreach:
foreach ($array as $key => $value)
<?php
// Control Flow in PHP
// If-else statement
$age = 25;
if ($age < 18) {
echo "Minor\n";
} elseif ($age < 65) {
echo "Adult\n";
} else {
echo "Senior\n";
}
// Ternary operator
$status = $age >= 18 ? "Adult" : "Minor";
echo $status . "\n";
// Match expression (PHP 8.0+)
$status = match(true) {
$age < 18 => "Minor",
$age < 65 => "Adult",
default => "Senior"
};
echo $status . "\n";
// For loop
for ($i = 1; $i <= 5; $i++) {
echo $i . "\n";
}
// For loop with array
$fruits = ["apple", "banana", "orange"];
foreach ($fruits as $fruit) {
echo $fruit . "\n";
}
// While loop
$i = 1;
while ($i <= 5) {
echo $i . "\n";
$i++;
}
// Break and continue
for ($i = 1; $i <= 10; $i++) {
if ($i == 6) {
break;
}
if ($i % 2 == 0) {
continue;
}
echo $i . "\n";
}
?>PHP provides several ways to generate arrays including range(), array_map(), and generators.
- Range:
range(1, 10) - Map:
array_map(fn($x) => $x*2, $arr) - Filter:
array_filter($arr, fn($x) => $x > 5) - Generator:
function squares() { yield 1; yield 4; } - Comprehension: Using
array_mapwithrange
<?php
// Array Generation in PHP
// Using range and array_map
$squares = array_map(fn($x) => $x * $x, range(1, 10));
print_r($squares);
// Filter with array_filter
$evens = array_filter(range(1, 20), fn($x) => $x % 2 == 0);
print_r($evens);
// Nested arrays
$matrix = [];
for ($i = 1; $i <= 3; $i++) {
for ($j = 1; $j <= 3; $j++) {
$matrix[] = [$i, $j];
}
}
print_r($matrix);
// Associative array generation
$keys = range(1, 5);
$values = array_map(fn($x) => $x * $x, range(1, 5));
$square_dict = array_combine($keys, $values);
print_r($square_dict);
// Generator expression (lazy)
function squares($n) {
for ($i = 1; $i <= $n; $i++) {
yield $i * $i;
}
}
$sum = 0;
foreach (squares(100) as $num) {
$sum += $num;
}
echo $sum . "\n";
// Conditional array
$results = array_map(fn($x) => $x % 2 == 0 ? "even" : "odd", range(1, 10));
print_r($results);
?>PHP provides extensive string manipulation functions including concatenation, interpolation, and case conversion.
- Concatenation:
'Hello' . ' ' . 'World' - Interpolation:
"Hello $name" - Functions:
strlen,strtoupper,strtolower - Substring:
substr($str, 0, 5) - Split/Join:
explode,implode
<?php
// Strings in PHP
// String creation
$str1 = "Hello";
$str2 = 'World';
$str3 = "Multi-line\nstring";
// String concatenation
$greeting = $str1 . " " . $str2;
echo $greeting . "\n";
// String interpolation
$name = "PHP";
$version = 8.2;
echo "Welcome to $name version $version\n";
// String functions
$text = "Hello, World!";
echo strlen($text) . "\n";
echo strtoupper($text) . "\n";
echo strtolower($text) . "\n";
echo str_replace("World", "PHP", $text) . "\n";
// Substring
echo substr($text, 0, 5) . "\n";
// Split and join
$words = explode(" ", "Hello World PHP");
print_r($words);
$joined = implode("-", $words);
echo $joined . "\n";
// String comparison
echo var_export("hello" == "hello", true) . "\n";
echo var_export("hello" < "world", true) . "\n";
// String formatting
echo sprintf("Value: %.2f", 3.14159) . "\n";
?>Namespaces in PHP provide a way to organize code and avoid name collisions.
- Definition:
namespace MyProject; - Use:
use MyProject\MyClass; - Alias:
use MyProject\MyClass as Alias; - Constants:
namespace\CONSTANT - Functions:
namespace\function_name()
<?php
// Namespaces and Modules in PHP
// Defining a namespace
namespace MyMath;
const PI = 3.14159;
function add($a, $b) {
return $a + $b;
}
function subtract($a, $b) {
return $a - $b;
}
// Private function (not exported)
function multiply($a, $b) {
return $a * $b;
}
// Using a namespace
namespace main;
use MyMath as Math;
echo Math\add(5, 3) . "\n";
echo Math\subtract(10, 4) . "\n";
echo Math\PI . "\n";
// Including external files
// include "math_functions.php";
// Class autoloading
spl_autoload_register(function ($class) {
include $class . '.php';
});
// Using traits
trait Logger {
public function log($message) {
echo "Log: $message\n";
}
}
class User {
use Logger;
}
$user = new User();
$user->log("User created");
?>PHP supports object-oriented programming with classes, inheritance, and type declarations.
- Class definition:
class MyClass { ... } - Properties:
public $name; - Methods:
public function method() { ... } - Constructor:
public function __construct() { ... } - Inheritance:
class Child extends Parent
<?php
// Classes and Types in PHP
// Abstract class
abstract class Animal {
protected $name;
protected $age;
abstract public function makeSound();
}
// Concrete class
class Dog extends Animal {
public function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
}
public function makeSound() {
return "Woof!";
}
}
// Class with properties
class Person {
public string $name;
public int $age;
private string $city;
public function __construct(string $name, int $age, string $city = "Unknown") {
$this->name = $name;
$this->age = $age;
$this->city = $city;
}
public function getCity(): string {
return $this->city;
}
}
// Usage
$dog = new Dog("Rex", 3);
$person = new Person("Alice", 25);
echo $dog->makeSound() . "\n";
echo $person->name . "\n";
echo $person->getCity() . "\n";
?>PHP supports type declarations for function arguments and return values, including union types and nullable types.
- Basic types:
int,float,string,bool - Union types:
int|float - Nullable types:
?string - Mixed type:
mixed - Return type:
: int
<?php
// Type Declarations and Type System in PHP
// Function with type declarations
function describe(int $x): string {
return "Integer: $x";
}
function describeFloat(float $x): string {
return "Float: $x";
}
function describeString(string $x): string {
return "String: $x";
}
function describeArray(array $x): string {
return "Array: " . json_encode($x);
}
// Union types (PHP 8.0+)
function describeMixed(int|float|string $x): string {
return "Value: $x";
}
// Nullable types
function describeNullable(?string $x): string {
return $x ?? "Null value";
}
// Mixed type (PHP 8.0+)
function describeAny(mixed $x): mixed {
return $x;
}
// Usage
echo describe(42) . "\n";
echo describeFloat(3.14) . "\n";
echo describeString("Hello") . "\n";
echo describeArray([1, 2, 3]) . "\n";
echo describeNullable(null) . "\n";
?>PHP provides try-catch-finally blocks for error handling, with support for custom exceptions.
- Try-catch:
try { ... } catch (Exception $e) { ... } - Finally:
try { ... } finally { ... } - Throw:
throw new Exception('message') - Custom exceptions:
class MyException extends Exception - Multiple catch:
catch (SpecificException $e) { ... }
<?php
// Exceptions and Errors in PHP
// Try-catch block
try {
// Code that might error
$result = 10 / 0;
echo $result;
} catch (DivisionByZeroError $e) {
echo "Division by zero error: " . $e->getMessage() . "\n";
}
// Specific error handling
try {
$arr = [1, 2, 3];
echo $arr[10];
} catch (Error $e) {
echo "Error: " . $e->getMessage() . "\n";
}
// Finally block
try {
$file = fopen("data.txt", "r");
if ($file) {
echo "File opened successfully\n";
fclose($file);
}
} catch (Exception $e) {
echo "Error opening file: " . $e->getMessage() . "\n";
} finally {
echo "Cleanup performed\n";
}
// Throwing exceptions
function divide($a, $b) {
if ($b == 0) {
throw new InvalidArgumentException("Cannot divide by zero");
}
return $a / $b;
}
// Custom exception
class MyException extends Exception {
public function __construct($message, $code = 0, Exception $previous = null) {
parent::__construct($message, $code, $previous);
}
}
try {
echo divide(10, 0);
} catch (InvalidArgumentException $e) {
echo "Error: " . $e->getMessage() . "\n";
}
?>PHP provides functions for file operations including reading, writing, and CSV handling.
- Read:
file_get_contents - Write:
file_put_contents - Line by line:
fgets,feof - CSV:
fgetcsv,fputcsv - File info:
is_file,is_dir
<?php
// File I/O in PHP
// Reading files
try {
$content = file_get_contents("example.txt");
echo $content;
} catch (Exception $e) {
echo "File not found\n";
}
// Reading line by line
try {
$file = fopen("data.txt", "r");
if ($file) {
while (($line = fgets($file)) !== false) {
echo $line;
}
fclose($file);
}
} catch (Exception $e) {
echo "Error reading file\n";
}
// Writing files
file_put_contents("output.txt", "Hello, World!\nThis is line 2\n");
// Appending to files
file_put_contents("output.txt", "Appended line\n", FILE_APPEND);
// Reading CSV
if (($handle = fopen("data.csv", "r")) !== false) {
while (($data = fgetcsv($handle)) !== false) {
print_r($data);
}
fclose($handle);
}
// Writing CSV
$data = [
["Name", "Age", "City"],
["Alice", 25, "NYC"],
["Bob", 30, "LA"]
];
$file = fopen("output.csv", "w");
foreach ($data as $row) {
fputcsv($file, $row);
}
fclose($file);
?>PHP uses Composer as a dependency manager. Packages are installed via Composer and autoloaded.
- Composer:
composer require vendor/package - Autoloading:
require 'vendor/autoload.php' - Using packages:
use Vendor\\Package\\Class - composer.json: Project dependencies
- composer.lock: Locked versions
<?php
// Composer and Packages in PHP
// Using Composer
// composer require monolog/monolog
// Using packages
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
// Create a logger
$log = new Logger('name');
$log->pushHandler(new StreamHandler('app.log', Logger::WARNING));
// Add log records
$log->warning('Foo');
$log->error('Bar');
// Using Guzzle HTTP client
// composer require guzzlehttp/guzzle
use GuzzleHttp\Client;
$client = new Client();
$response = $client->get('https://api.github.com');
echo $response->getBody();
// Using dotenv for environment variables
// composer require vlucas/phpdotenv
use Dotenv\Dotenv;
$dotenv = Dotenv::createImmutable(__DIR__);
$dotenv->load();
echo $_ENV['APP_ENV'] ?? 'production';
// Autoloading
// composer dump-autoload
// Using PHPUnit for testing
// composer require --dev phpunit/phpunit
// Using Laravel or Symfony components
// composer require laravel/framework
// composer require symfony/http-foundation
?>PHP can create plots using GD library, ImageMagick, or JavaScript libraries like Chart.js.
- GD:
imagecreatetruecolor - Chart.js: JavaScript library
- ImageMagick: Advanced image processing
- Custom: Generate SVG
- Web-based: Use Chart.js with PHP data
<?php
// Plotting in PHP
// Using ImageMagick or GD for simple plots
function create_plot($data) {
$width = 800;
$height = 600;
$image = imagecreatetruecolor($width, $height);
// Colors
$white = imagecolorallocate($image, 255, 255, 255);
$black = imagecolorallocate($image, 0, 0, 0);
$red = imagecolorallocate($image, 255, 0, 0);
$blue = imagecolorallocate($image, 0, 0, 255);
// Fill background
imagefill($image, 0, 0, $white);
// Draw axes
imageline($image, 50, 50, 50, $height - 50, $black);
imageline($image, 50, $height - 50, $width - 50, $height - 50, $black);
// Draw data points
$max_y = max($data) ?: 1;
$x_scale = ($width - 100) / (count($data) - 1);
$y_scale = ($height - 100) / $max_y;
for ($i = 0; $i < count($data) - 1; $i++) {
$x1 = 50 + $i * $x_scale;
$y1 = $height - 50 - $data[$i] * $y_scale;
$x2 = 50 + ($i + 1) * $x_scale;
$y2 = $height - 50 - $data[$i + 1] * $y_scale;
imageline($image, $x1, $y1, $x2, $y2, $red);
imagefilledellipse($image, $x1, $y1, 5, 5, $blue);
}
// Save image
imagepng($image, "plot.png");
imagedestroy($image);
}
$data = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100];
create_plot($data);
echo "Plot created: plot.png\n";
// Using Chart.js for web-based plots
// echo '<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>';
// echo '<canvas id="myChart"></canvas>';
// echo '<script>';
// echo 'new Chart(document.getElementById("myChart"), { type: "line", data: { labels: [1,2,3,4,5], datasets: [{ data: [1,4,9,16,25] }] } });';
// echo '</script>';
?>PHP provides built-in data structures through arrays and Spl extensions for specialized structures.
- Stack:
SplStack - Queue:
SplQueue - Map: Associative arrays
- Set:
array_unique - Linked list:
SplDoublyLinkedList
<?php
// Data Structures in PHP
// Using arrays as data structures
// Stack (LIFO)
class Stack {
private $items = [];
public function push($item) {
array_push($this->items, $item);
}
public function pop() {
return array_pop($this->items);
}
public function peek() {
return end($this->items);
}
public function isEmpty() {
return empty($this->items);
}
}
// Queue (FIFO)
class Queue {
private $items = [];
public function enqueue($item) {
array_push($this->items, $item);
}
public function dequeue() {
return array_shift($this->items);
}
public function peek() {
return reset($this->items);
}
public function isEmpty() {
return empty($this->items);
}
}
// Map (using associative array)
$map = [
"Alice" => 25,
"Bob" => 30,
"Charlie" => 35
];
// Set (using array with unique values)
$set = array_unique([1, 2, 2, 3, 3, 4]);
// Usage
$stack = new Stack();
$stack->push(1);
$stack->push(2);
$stack->push(3);
echo $stack->pop() . "\n"; // 3
$queue = new Queue();
$queue->enqueue(1);
$queue->enqueue(2);
$queue->enqueue(3);
echo $queue->dequeue() . "\n"; // 1
// Using Spl data structures (built-in)
$splStack = new SplStack();
$splStack->push(1);
$splStack->push(2);
echo $splStack->pop() . "\n"; // 2
$splQueue = new SplQueue();
$splQueue->enqueue(1);
$splQueue->enqueue(2);
echo $splQueue->dequeue() . "\n"; // 1
?>PHP provides statistical functions through built-in functions and custom implementations.
- Mean:
array_sum($data) / count($data) - Median: Sort and find middle
- Standard deviation: Custom calculation
- Correlation: Manual calculation
- Quantiles: Custom implementation
<?php
// Statistics in PHP
// Basic statistics functions
function mean($data) {
return array_sum($data) / count($data);
}
function median($data) {
sort($data);
$n = count($data);
if ($n % 2 == 1) {
return $data[($n - 1) / 2];
} else {
return ($data[$n / 2 - 1] + $data[$n / 2]) / 2;
}
}
function standardDeviation($data) {
$mean = mean($data);
$variance = array_sum(array_map(fn($x) => pow($x - $mean, 2), $data)) / count($data);
return sqrt($variance);
}
function variance($data) {
$mean = mean($data);
return array_sum(array_map(fn($x) => pow($x - $mean, 2), $data)) / count($data);
}
function correlation($x, $y) {
$n = count($x);
$mean_x = mean($x);
$mean_y = mean($y);
$sum_xy = 0;
$sum_x2 = 0;
$sum_y2 = 0;
for ($i = 0; $i < $n; $i++) {
$dx = $x[$i] - $mean_x;
$dy = $y[$i] - $mean_y;
$sum_xy += $dx * $dy;
$sum_x2 += $dx * $dx;
$sum_y2 += $dy * $dy;
}
return $sum_xy / sqrt($sum_x2 * $sum_y2);
}
function quantile($data, $q) {
sort($data);
$n = count($data);
$pos = ($n - 1) * $q;
$base = floor($pos);
$frac = $pos - $base;
if ($frac == 0) {
return $data[$base];
} else {
return $data[$base] + $frac * ($data[$base + 1] - $data[$base]);
}
}
// Usage
$data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
echo "Mean: " . mean($data) . "\n";
echo "Median: " . median($data) . "\n";
echo "Standard Deviation: " . standardDeviation($data) . "\n";
echo "Variance: " . variance($data) . "\n";
$x = range(1, 100);
$y = array_map(fn($v) => 2 * $v + rand(-10, 10), $x);
echo "Correlation: " . correlation($x, $y) . "\n";
echo "Quantile (0.25): " . quantile($data, 0.25) . "\n";
echo "Quantile (0.75): " . quantile($data, 0.75) . "\n";
?>PHP provides linear algebra operations through custom implementations or libraries.
- Matrix multiplication:
matMul - Transpose:
transpose - Determinant:
determinant - Eigenvalues: Complex calculation
- Inverse: Using Gauss-Jordan
<?php
// Linear Algebra in PHP
// Simple linear algebra operations
function matMul($a, $b) {
$rows = count($a);
$cols = count($b[0]);
$inner = count($b);
$result = array_fill(0, $rows, array_fill(0, $cols, 0));
for ($i = 0; $i < $rows; $i++) {
for ($j = 0; $j < $cols; $j++) {
for ($k = 0; $k < $inner; $k++) {
$result[$i][$j] += $a[$i][$k] * $b[$k][$j];
}
}
}
return $result;
}
function transpose($matrix) {
$rows = count($matrix);
$cols = count($matrix[0]);
$result = array_fill(0, $cols, array_fill(0, $rows, 0));
for ($i = 0; $i < $rows; $i++) {
for ($j = 0; $j < $cols; $j++) {
$result[$j][$i] = $matrix[$i][$j];
}
}
return $result;
}
function determinant($matrix) {
$n = count($matrix);
if ($n == 1) {
return $matrix[0][0];
}
if ($n == 2) {
return $matrix[0][0] * $matrix[1][1] - $matrix[0][1] * $matrix[1][0];
}
$det = 0;
for ($j = 0; $j < $n; $j++) {
$subMatrix = [];
for ($i = 1; $i < $n; $i++) {
$row = [];
for ($k = 0; $k < $n; $k++) {
if ($k != $j) {
$row[] = $matrix[$i][$k];
}
}
$subMatrix[] = $row;
}
$det += ($j % 2 == 0 ? 1 : -1) * $matrix[0][$j] * determinant($subMatrix);
}
return $det;
}
// Usage
$A = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 10]
];
$B = [
[1],
[2],
[3]
];
$product = matMul($A, $B);
echo "Matrix product:\n";
print_r($product);
$transpose = transpose($A);
echo "Transpose:\n";
print_r($transpose);
$det = determinant($A);
echo "Determinant: $det\n";
?>PHP provides DateTime class and date functions for comprehensive date and time handling.
- Current:
new DateTime() - Create:
new DateTime('2024-01-01') - Arithmetic:
$date->modify('+1 day') - Difference:
$date1->diff($date2) - Formatting:
$date->format('Y-m-d')
<?php
// Dates and Time in PHP
// Current date and time
$now = new DateTime();
echo $now->format('Y-m-d H:i:s') . "\n";
// Date creation
$date1 = new DateTime('2024-01-01');
$date2 = new DateTime('2024-01-01 12:00:00');
echo $date1->format('Y-m-d') . "\n";
echo $date2->format('Y-m-d H:i:s') . "\n";
// Date arithmetic
$date1->modify('+10 days');
echo $date1->format('Y-m-d') . "\n";
$date1->modify('+2 months');
echo $date1->format('Y-m-d') . "\n";
// Date difference
$diff = $now->diff($date2);
echo $diff->format('%d days, %h hours') . "\n";
// Formatting dates
$date = DateTime::createFromFormat('Y-m-d', '2024-01-01');
echo $date->format('Y-m-d H:i:s') . "\n";
// Date functions
echo date('Y') . "\n";
echo date('m') . "\n";
echo date('d') . "\n";
echo date('l') . "\n";
// Date range
$start = new DateTime('2024-01-01');
$end = new DateTime('2024-01-10');
$interval = new DateInterval('P1D');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $date) {
echo $date->format('Y-m-d') . "\n";
}
// Timezone handling
$timezone = new DateTimeZone('America/New_York');
$date = new DateTime('now', $timezone);
echo $date->format('Y-m-d H:i:s') . "\n";
// Timestamps
$timestamp = time();
echo date('Y-m-d H:i:s', $timestamp) . "\n";
echo strtotime('2024-01-01') . "\n";
?>PHP provides PCRE functions for regular expression matching, replacement, and splitting.
- Match:
preg_match('/hello/', $text) - Find all:
preg_match_all('/hello/', $text) - Capture groups:
preg_match('/(\d+)/', $text) - Replace:
preg_replace('/\d+/', 'NUM', $text) - Split:
preg_split('/[\s,]+/', $text)
<?php
// Regular Expressions in PHP
// Create regex
$text = "hello world";
// Match
preg_match('/hello/', $text, $matches);
print_r($matches);
// Find all
$text2 = "hello world hello again";
preg_match_all('/hello/', $text2, $matches);
echo count($matches[0]) . "\n";
// Regex with capture groups
$text3 = "Date: 2024-01-01";
preg_match('/(\d{4})-(\d{2})-(\d{2})/', $text3, $matches);
if (!empty($matches)) {
echo $matches[1] . "\n"; // year
echo $matches[2] . "\n"; // month
echo $matches[3] . "\n"; // day
}
// Replace with regex
$replaced = preg_replace('/\d+/', 'NUM', 'Hello 123 World');
echo $replaced . "\n";
// Case insensitive
preg_match('/hello/i', 'HELLO world', $matches);
print_r($matches);
// Regular expression functions
preg_match('/^\d{3}-\d{4}$/', '123-4567', $matches);
echo var_export(!empty($matches), true) . "\n";
// Split with regex
$parts = preg_split('/[, ]+/', 'Hello World PHP');
print_r($parts);
// Replace callback
$result = preg_replace_callback('/\d+/', function($matches) {
return $matches[0] * 2;
}, '1 2 3 4 5');
echo $result . "\n";
?>PHP supports parallel computing through PCNTL, pthreads, parallel extension, and async libraries.
- PCNTL: Process forking
- pthreads: Threading (deprecated)
- parallel: New parallel extension
- Amp: Async programming
- ReactPHP: Event-driven
<?php
// Parallel Computing in PHP
// Using PCNTL for process forking
if (function_exists('pcntl_fork')) {
$pid = pcntl_fork();
if ($pid == -1) {
die('Could not fork');
} else if ($pid) {
// Parent process
echo "Parent process\n";
pcntl_wait($status);
} else {
// Child process
echo "Child process\n";
exit(0);
}
}
// Using pthreads for threading (PHP 7.2-8.0, not available in PHP 8.1+)
// class MyThread extends Thread {
// public function run() {
// echo "Thread running\n";
// }
// }
// $thread = new MyThread();
// $thread->start();
// Using parallel extension (PHP 8.0+)
// composer require ext-parallel
// Using Amp for async programming
// composer require amphp/amp
use Amp\Loop;
use Amp\Promise;
use function Amp\async;
Loop::run(function() {
$promise1 = async(function() {
return "Task 1 completed";
});
$promise2 = async(function() {
return "Task 2 completed";
});
$result1 = yield $promise1;
$result2 = yield $promise2;
echo "$result1\n$result2\n";
});
// Using ReactPHP for event-driven programming
// composer require react/event-loop
use React\EventLoop\Factory;
$loop = Factory::create();
$loop->addTimer(2, function() {
echo "After 2 seconds\n";
});
$loop->run();
// Parallel processing with array_map
$data = range(1, 100);
$chunks = array_chunk($data, 10);
$results = [];
foreach ($chunks as $chunk) {
$pid = pcntl_fork();
if ($pid == 0) {
// Process chunk
$result = array_sum($chunk);
file_put_contents("/tmp/result_$pid.txt", $result);
exit(0);
}
}
// Wait for all child processes
while (pcntl_waitpid(0, $status) != -1) {
// Wait for children
}
?>PHP supports metaprogramming through magic methods, eval, and reflection for dynamic code manipulation.
- eval:
eval('echo 1+2;') - Magic methods:
__call,__set,__get - Reflection:
ReflectionClass - Dynamic calls: Variable functions
- Attributes: Metadata (PHP 8.0+)
<?php
// Metaprogramming in PHP
// Using eval for dynamic code execution
$code = '$x = 10; $y = 20; echo $x + $y;';
eval($code);
// Dynamic function calls
function add($a, $b) {
return $a + $b;
}
$functionName = 'add';
echo $functionName(5, 3) . "\n";
// Dynamic method calls
class MyClass {
public function method1() {
return "Method 1 called";
}
public function method2() {
return "Method 2 called";
}
}
$obj = new MyClass();
$methodName = 'method1';
echo $obj->$methodName() . "\n";
// Using __call and __callStatic for method overloading
class DynamicClass {
public function __call($name, $arguments) {
echo "Called method: $name with args: " . implode(', ', $arguments) . "\n";
}
public static function __callStatic($name, $arguments) {
echo "Called static method: $name\n";
}
}
$obj = new DynamicClass();
$obj->undefinedMethod(1, 2, 3);
DynamicClass::undefinedStaticMethod();
// Using __set and __get for property overloading
class PropertyOverload {
private $data = [];
public function __set($name, $value) {
$this->data[$name] = $value;
}
public function __get($name) {
return $this->data[$name] ?? null;
}
}
$obj = new PropertyOverload();
$obj->dynamicProperty = 'value';
echo $obj->dynamicProperty . "\n";
// Reflection for metaprogramming
$reflection = new ReflectionClass('MyClass');
foreach ($reflection->getMethods() as $method) {
echo $method->getName() . "\n";
}
?>PHP provides FFI (Foreign Function Interface) for calling C functions and extensions for deeper integration.
- FFI:
FFI::cdef - C extensions: Write PHP extensions in C
- Calling C:
ffi->printf - Structs:
FFI::new - Memory: Manual management
<?php
// Interoperability with C in PHP
// Using FFI (Foreign Function Interface) in PHP 7.4+
// FFI allows calling C functions from PHP
// Example: Using C library functions
if (extension_loaded('ffi')) {
// Load C library
$libc = FFI::cdef(
"int printf(const char *format, ...);",
"libc.so.6"
);
// Call C function
$libc->printf("Hello from C: %d\n", 42);
// Using math functions
$libm = FFI::cdef(
"double sin(double x);",
"libm.so.6"
);
$result = $libm->sin(0.5);
echo "sin(0.5) = $result\n";
}
// Using C structs with FFI
if (extension_loaded('ffi')) {
$cdef = FFI::cdef(
"typedef struct { int x; int y; } Point;",
"libc.so.6"
);
$point = $cdef->new('Point');
$point->x = 10;
$point->y = 20;
echo "Point: x={$point->x}, y={$point->y}\n";
}
// Extension for C integration
// PHP extensions can be written in C
// Example: Creating a simple PHP extension
// (Save as myextension.c and compile)
// Using PHP's C API
// int my_add(int a, int b) { return a + b; }
// PHP_FUNCTION(my_add) {
// long a, b;
// if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &a, &b) == FAILURE) {
// return;
// }
// RETURN_LONG(a + b);
// }
?>PHP performance can be optimized through type declarations, opcode caching, and efficient code practices.
- Type declarations:
function add(int $a, int $b): int - OPcache: Enable opcode caching
- Preallocate:
array_fill - Static methods:
Class::method() - Avoid globals: Use constants
<?php
// Performance Optimization in PHP
// Performance tips
// 1. Use type declarations
function sumArray(array $arr): int {
$sum = 0;
foreach ($arr as $value) {
$sum += $value;
}
return $sum;
}
// 2. Avoid global variables
const GLOBAL_CONST = 10;
function useGlobal(): int {
return GLOBAL_CONST * 2;
}
// 3. Use strict_types
declare(strict_types=1);
// 4. Preallocate arrays
function preallocate(): array {
$arr = array_fill(0, 1000, 0);
for ($i = 0; $i < 1000; $i++) {
$arr[$i] = $i * $i;
}
return $arr;
}
// 5. Use foreach instead of for for arrays
function sumArrayOptimized(array $arr): int {
$sum = 0;
foreach ($arr as $value) {
$sum += $value;
}
return $sum;
}
// 6. Use opcode caching (OPcache)
// Enable OPcache in php.ini:
// opcache.enable=1
// opcache.memory_consumption=128
// 7. Use static methods when possible
class Math {
public static function add($a, $b) {
return $a + $b;
}
}
$result = Math::add(5, 3);
// 8. Avoid unnecessary object creation
function processData(array $data) {
$result = [];
foreach ($data as $item) {
// Avoid creating new objects in loops
$result[] = $item * 2;
}
return $result;
}
// 9. Use memory efficient data structures
$splFixedArray = new SplFixedArray(1000);
for ($i = 0; $i < 1000; $i++) {
$splFixedArray[$i] = $i;
}
// 10. Profile your code
// Using Xdebug for profiling
// xdebug_start_trace();
// // Your code
// xdebug_stop_trace();
?>PHP provides networking capabilities through cURL, sockets, and HTTP client libraries.
- cURL:
curl_init,curl_exec - HTTP client: Guzzle
- WebSockets: Ratchet
- Socket server:
socket_create - Built-in server:
php -S localhost:8080
<?php
// Networking in PHP
// HTTP client using cURL
function fetchData($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
throw new Exception("cURL error: $error");
}
return $response;
}
try {
$data = fetchData("https://api.github.com");
echo $data;
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
// POST request
function postData($url, $data) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
// HTTP server (built-in)
// php -S localhost:8080
// Socket server
function socketServer() {
$host = '127.0.0.1';
$port = 8080;
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, $host, $port);
socket_listen($socket, 5);
echo "Server listening on $host:$port\n";
while (true) {
$client = socket_accept($socket);
$input = socket_read($client, 1024);
$response = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nHello from server!";
socket_write($client, $response);
socket_close($client);
}
}
// WebSocket example using Ratchet
// composer require cboden/ratchet
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class Chat implements MessageComponentInterface {
protected $clients;
public function __construct() {
$this->clients = new \SplObjectStorage();
}
public function onOpen(ConnectionInterface $conn) {
$this->clients->attach($conn);
echo "New connection: {$conn->resourceId}\n";
}
public function onClose(ConnectionInterface $conn) {
$this->clients->detach($conn);
echo "Connection closed: {$conn->resourceId}\n";
}
public function onError(ConnectionInterface $conn, \Exception $e) {
echo "Error: {$e->getMessage()}\n";
$conn->close();
}
public function onMessage(ConnectionInterface $from, $msg) {
foreach ($this->clients as $client) {
if ($from !== $client) {
$client->send($msg);
}
}
}
}
// Running WebSocket server
// use Ratchet\Server\IoServer;
// use Ratchet\Http\HttpServer;
// use Ratchet\WebSocket\WsServer;
//
// $server = IoServer::factory(
// new HttpServer(
// new WsServer(
// new Chat()
// )
// ),
// 8080
// );
// $server->run();
?>PHP provides built-in functions for JSON encoding and decoding with support for custom serialization.
- Encode:
json_encode($data) - Decode:
json_decode($json, true) - Pretty print:
JSON_PRETTY_PRINT - Error handling:
json_last_error - Custom serialization:
JsonSerializable
<?php
// Working with JSON in PHP
// Encode to JSON
$data = [
'name' => 'Alice',
'age' => 25,
'city' => 'NYC',
'hobbies' => ['reading', 'coding']
];
$json_string = json_encode($data);
echo $json_string . "\n";
// Pretty print
$pretty_json = json_encode($data, JSON_PRETTY_PRINT);
echo $pretty_json . "\n";
// Decode from JSON
$json_str = '{"name":"Bob","age":30,"city":"LA"}';
$parsed = json_decode($json_str, true);
echo $parsed['name'] . "\n";
echo $parsed['age'] . "\n";
// Working with arrays
$json_array = json_encode([1, 2, 3, 4, 5]);
echo $json_array . "\n";
$parsed_array = json_decode($json_array, true);
print_r($parsed_array);
// Nested structures
$nested = [
'user' => [
'id' => 1,
'profile' => [
'name' => 'Alice',
'email' => 'alice@example.com'
]
]
];
echo json_encode($nested, JSON_PRETTY_PRINT) . "\n";
// Read JSON from file
$json_content = file_get_contents('data.json');
$data = json_decode($json_content, true);
// Write JSON to file
file_put_contents('data.json', json_encode($data, JSON_PRETTY_PRINT));
// Error handling
if (json_last_error() !== JSON_ERROR_NONE) {
echo 'JSON Error: ' . json_last_error_msg() . "\n";
}
// JSON with custom encoding
class User {
public $name;
public $age;
public function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
}
}
$user = new User('Alice', 25);
$json = json_encode($user);
echo $json . "\n";
// Custom JSON serialization
class SerializableUser implements JsonSerializable {
public $name;
public $age;
public function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
}
public function jsonSerialize() {
return [
'fullname' => $this->name,
'years' => $this->age
];
}
}
$user = new SerializableUser('Alice', 25);
echo json_encode($user) . "\n";
?>PHP testing is done using PHPUnit for unit testing, with support for data providers and mocking.
- PHPUnit:
vendor/bin/phpunit - Assertions:
$this->assertEquals - Data providers:
@dataProvider - Mocking:
createMock - Coverage:
--coverage-html
<?php
// Testing in PHP
// Using PHPUnit for testing
// composer require --dev phpunit/phpunit
// Basic test example
class MathTest extends PHPUnit\Framework\TestCase {
public function testAddition() {
$this->assertEquals(4, 2 + 2);
$this->assertNotEquals(5, 2 + 2);
}
public function testFloatingPoint() {
$this->assertEqualsWithDelta(0.3, 0.1 + 0.2, 0.0001);
}
public function testExceptions() {
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Cannot divide by zero');
$this->divide(10, 0);
}
private function divide($a, $b) {
if ($b == 0) {
throw new InvalidArgumentException('Cannot divide by zero');
}
return $a / $b;
}
public function testArrays() {
$arr = [1, 2, 3];
$this->assertCount(3, $arr);
$this->assertContains(2, $arr);
$this->assertArrayHasKey(0, $arr);
}
/**
* @dataProvider additionProvider
*/
public function testAddWithDataProvider($a, $b, $expected) {
$this->assertEquals($expected, $a + $b);
}
public function additionProvider() {
return [
[1, 2, 3],
[0, 0, 0],
[-1, 1, 0],
[5, -3, 2]
];
}
}
// Using PHPUnit with coverage
// vendor/bin/phpunit --coverage-html coverage
// Simple test without PHPUnit
function assertEquals($expected, $actual, $message = '') {
if ($expected != $actual) {
throw new Exception("Assertion failed: $message");
}
}
function assertTrue($condition, $message = '') {
if (!$condition) {
throw new Exception("Assertion failed: $message");
}
}
// Mocking in PHPUnit
class UserServiceTest extends PHPUnit\Framework\TestCase {
public function testUserService() {
$mock = $this->createMock(UserRepository::class);
$mock->method('find')
->willReturn(['id' => 1, 'name' => 'Alice']);
$service = new UserService($mock);
$user = $service->getUser(1);
$this->assertEquals('Alice', $user['name']);
}
}
// Integration tests
class DatabaseTest extends PHPUnit\Framework\TestCase {
private $pdo;
protected function setUp(): void {
$this->pdo = new PDO('sqlite::memory:');
$this->pdo->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');
}
public function testDatabaseInsert() {
$stmt = $this->pdo->prepare('INSERT INTO users (name) VALUES (?)');
$stmt->execute(['Alice']);
$result = $this->pdo->query('SELECT * FROM users')->fetch();
$this->assertEquals('Alice', $result['name']);
}
}
?>PHP provides debugging through var_dump, error_log, assertions, and Xdebug for step debugging.
- var_dump:
var_dump($variable) - print_r:
print_r($array) - error_log:
error_log('message') - Assertions:
assert($condition) - Xdebug: Step debugging
<?php
// Debugging in PHP
// Using var_dump for debugging
$x = 10;
$y = 20;
var_dump($x + $y);
// Using print_r for arrays
$arr = ['a' => 1, 'b' => 2, 'c' => 3];
print_r($arr);
// Using var_export for PHP code output
$data = ['name' => 'Alice', 'age' => 25];
var_export($data);
echo "\n";
// Using debug_backtrace
function debugTrace() {
$trace = debug_backtrace();
foreach ($trace as $call) {
echo $call['file'] ?? 'unknown' . ':' . ($call['line'] ?? 0) . "\n";
}
}
debugTrace();
// Using error_log for logging
error_log("This is an error message", 0);
error_log("This is an error message", 3, "/var/log/php_errors.log");
// Using trigger_error for user errors
trigger_error("Custom error message", E_USER_WARNING);
// Using set_error_handler for custom error handling
set_error_handler(function($errno, $errstr, $errfile, $errline) {
echo "Error: [$errno] $errstr in $errfile on line $errline\n";
return true;
});
// Using xdebug
// xdebug_start_trace('trace.xt');
// Your code here
// xdebug_stop_trace();
// Using Monolog for structured logging
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$log = new Logger('debug');
$log->pushHandler(new StreamHandler('app.log', Logger::DEBUG));
$log->info('This is an info message');
$log->warning('This is a warning');
$log->error('This is an error', ['context' => 'data']);
// Using assertions for debugging
assert_options(ASSERT_ACTIVE, 1);
assert_options(ASSERT_WARNING, 1);
assert_options(ASSERT_BAIL, 0);
assert_options(ASSERT_CALLBACK, 'assertCallback');
function assertCallback($file, $line, $code) {
echo "Assertion failed: $code in $file on line $line\n";
}
assert($x == 10);
// Using breakpoints with Xdebug (via IDE)
// set breakpoints in your IDE and run with Xdebug enabled
?>Abstract classes and interfaces define contracts for classes to implement, with abstract methods and type definitions.
- Abstract class:
abstract class Animal { ... } - Interface:
interface Animal { ... } - Implementation:
class Dog extends Animal - Multiple interfaces:
implements Interface1, Interface2 - Type checking:
instanceof
<?php
// Abstract Classes and Interfaces
// Abstract class
abstract class Animal {
protected $name;
protected $age;
public function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
}
abstract public function makeSound(): string;
public function getName(): string {
return $this->name;
}
}
// Concrete classes
class Dog extends Animal {
public function makeSound(): string {
return "Woof!";
}
}
class Cat extends Animal {
public function makeSound(): string {
return "Meow!";
}
}
class Sparrow extends Animal {
private $wingspan;
public function __construct($name, $age, $wingspan) {
parent::__construct($name, $age);
$this->wingspan = $wingspan;
}
public function makeSound(): string {
return "Chirp!";
}
}
// Interface
interface SoundMaker {
public function makeSound(): string;
}
interface AnimalInterface {
public function getName(): string;
public function getAge(): int;
}
// Class implementing multiple interfaces
class Lion implements AnimalInterface, SoundMaker {
private $name;
private $age;
public function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
}
public function getName(): string {
return $this->name;
}
public function getAge(): int {
return $this->age;
}
public function makeSound(): string {
return "Roar!";
}
}
// Usage
$dog = new Dog("Rex", 3);
$cat = new Cat("Whiskers", 2);
$sparrow = new Sparrow("Tweet", 1, 15.0);
echo $dog->getName() . " says " . $dog->makeSound() . "\n";
echo $cat->getName() . " says " . $cat->makeSound() . "\n";
echo $sparrow->getName() . " says " . $sparrow->makeSound() . "\n";
// Type checking
echo var_export($dog instanceof Animal, true) . "\n";
echo var_export($dog instanceof SoundMaker, true) . "\n";
?>PHP supports type hints and union types, but true generics are not available. Static analysis tools provide generic-like behavior.
- Type hints:
function add(int $a, int $b): int - Union types:
int|float - Mixed type:
mixed - Iterable:
iterable - PHPStan/Psalm: Static analysis
<?php
// Generics and Type Hints in PHP
// PHP doesn't have direct generics like Java, but we can use type hints
// Basic type hints
function processNumber(int $x): int {
return $x * 2;
}
function processArray(array $items): array {
return array_map(fn($item) => $item * 2, $items);
}
// Using mixed type
function processMixed(mixed $value): mixed {
return $value;
}
// Using multiple types (union types)
function processNumberOrString(int|string $value): int|string {
return $value;
}
// Using nullable types
function processNullable(?string $value): ?string {
return $value;
}
// Using iterable type
function processIterable(iterable $items): iterable {
foreach ($items as $item) {
yield $item * 2;
}
}
// Generic-like class using type hints
class Collection {
private array $items = [];
public function add(mixed $item): void {
$this->items[] = $item;
}
public function get(int $index): mixed {
return $this->items[$index] ?? null;
}
public function map(callable $callback): array {
return array_map($callback, $this->items);
}
}
// Using PHPStan for static analysis
// composer require --dev phpstan/phpstan
// vendor/bin/phpstan analyse src
// Using Psalm for type checking
// composer require --dev vimeo/psalm
// vendor/bin/psalm
// Example with class type hints
class UserService {
private array $users = [];
public function addUser(User $user): void {
$this->users[] = $user;
}
public function getUsers(): array {
return $this->users;
}
}
// Using interface type hints
interface Repository {
public function find(int $id): ?object;
}
class UserRepository implements Repository {
public function find(int $id): ?object {
// Implementation
return null;
}
}
?>Traits provide a mechanism for code reuse in single inheritance languages like PHP.
- Definition:
trait Logger { ... } - Use:
use Logger; - Multiple traits:
use Logger, Timestamp; - Conflict resolution:
insteadof,as - Properties: Traits can have properties
<?php
// Traits and Composition in PHP
// Basic trait
trait Logger {
public function log($message) {
echo "Log: $message\n";
}
}
trait Timestamp {
public function getTimestamp() {
return date('Y-m-d H:i:s');
}
}
// Using multiple traits
class User {
use Logger, Timestamp;
private $name;
public function __construct($name) {
$this->name = $name;
$this->log("User created at " . $this->getTimestamp());
}
}
// Trait with properties
trait ConfigTrait {
private $config = [];
public function setConfig($key, $value) {
$this->config[$key] = $value;
}
public function getConfig($key) {
return $this->config[$key] ?? null;
}
}
// Trait conflict resolution
trait A {
public function sayHello() {
echo "Hello from A\n";
}
}
trait B {
public function sayHello() {
echo "Hello from B\n";
}
}
class Greeter {
use A, B {
A::sayHello insteadof B;
B::sayHello as sayHelloB;
}
}
// Abstract trait methods
trait Validatable {
abstract public function validate(): bool;
public function isValid(): bool {
return $this->validate();
}
}
class UserData {
use Validatable;
private $data;
public function __construct($data) {
$this->data = $data;
}
public function validate(): bool {
return isset($this->data['name']) && isset($this->data['email']);
}
}
// Trait with static methods
trait StaticLogger {
public static function staticLog($message) {
echo "Static log: $message\n";
}
}
class Application {
use StaticLogger;
}
// Usage
$user = new User("Alice");
$user->log("User logged in");
$greeter = new Greeter();
$greeter->sayHello();
$greeter->sayHelloB();
$userData = new UserData(['name' => 'Alice', 'email' => 'alice@example.com']);
echo var_export($userData->isValid(), true) . "\n";
Application::staticLog("Application started");
?>Generators in PHP provide a simple way to implement iterators, and coroutines enable cooperative multitasking.
- Generator:
function gen() { yield 1; yield 2; } - Yield from:
yield from [3, 4, 5] - Send:
$gen->send(10) - Return:
return 'done' - Task scheduler: Coroutine support
<?php
// Generators and Coroutines in PHP
// Basic generator
function fibonacciGenerator() {
$a = 0;
$b = 1;
while (true) {
yield $a;
$c = $a + $b;
$a = $b;
$b = $c;
}
}
$fib = fibonacciGenerator();
for ($i = 0; $i < 10; $i++) {
echo $fib->current() . " ";
$fib->next();
}
echo "\n";
// Generator with send
function counter() {
$i = 0;
while (true) {
$value = yield $i;
if ($value !== null) {
$i = $value;
}
$i++;
}
}
$counter = counter();
echo $counter->current() . "\n"; // 0
$counter->next();
echo $counter->current() . "\n"; // 1
$counter->send(10);
echo $counter->current() . "\n"; // 10
// Generator with return
function rangeWithReturn($start, $end) {
for ($i = $start; $i <= $end; $i++) {
yield $i;
}
return "Completed range $start to $end";
}
$range = rangeWithReturn(1, 5);
foreach ($range as $value) {
echo $value . " ";
}
echo "\n";
echo $range->getReturn() . "\n";
// Generator delegation
function generateNumbers() {
yield 1;
yield 2;
yield from [3, 4, 5];
yield 6;
}
foreach (generateNumbers() as $num) {
echo $num . " ";
}
echo "\n";
// Generator with keys
function keyedGenerator() {
yield 'a' => 1;
yield 'b' => 2;
yield 'c' => 3;
}
foreach (keyedGenerator() as $key => $value) {
echo "$key => $value\n";
}
// Using generators for large datasets
function readLargeFile($filename) {
$handle = fopen($filename, 'r');
if (!$handle) {
return;
}
while (($line = fgets($handle)) !== false) {
yield trim($line);
}
fclose($handle);
}
// Coroutine-like behavior with generators
function task($name, $delay) {
$i = 0;
while ($i < 3) {
yield "$name: Step $i";
sleep($delay);
$i++;
}
}
function scheduler($tasks) {
while (!empty($tasks)) {
foreach ($tasks as $key => $task) {
if ($task->valid()) {
echo $task->current() . "\n";
$task->next();
} else {
unset($tasks[$key]);
}
}
}
}
$tasks = [
task('Task1', 1),
task('Task2', 2)
];
scheduler($tasks);
?>PHP provides advanced array operations including matrix operations, element-wise operations, and various transformations.
- Matrix ops:
matMul - Element-wise:
array_map - Transpose:
transpose - Norm: Frobenius norm
- Trace/Diagonal:
trace,diag
<?php
// Advanced Array Operations
// Array initialization
$A = array_fill(0, 3, array_fill(0, 3, 0));
$B = array_fill(0, 3, array_fill(0, 3, 1));
$C = array_fill(0, 3, array_fill(0, 3, 5));
// Identity matrix
$I = [];
for ($i = 0; $i < 3; $i++) {
$I[$i] = array_fill(0, 3, 0);
$I[$i][$i] = 1;
}
// Reshaping
$arr = range(1, 9);
$matrix = array_chunk($arr, 3);
print_r($matrix);
// Transpose
function transpose($matrix) {
$rows = count($matrix);
$cols = count($matrix[0]);
$result = array_fill(0, $cols, array_fill(0, $rows, 0));
for ($i = 0; $i < $rows; $i++) {
for ($j = 0; $j < $cols; $j++) {
$result[$j][$i] = $matrix[$i][$j];
}
}
return $result;
}
// Element-wise operations
$A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
$B = array_map(function($row) {
return array_map(fn($val) => $val + 1, $row);
}, $A);
$C = array_map(function($row) {
return array_map(fn($val) => $val * 2, $row);
}, $A);
$D = array_map(function($row) {
return array_map(fn($val) => $val * $val, $row);
}, $A);
// Matrix multiplication
function matMul($a, $b) {
$rows = count($a);
$cols = count($b[0]);
$inner = count($b);
$result = array_fill(0, $rows, array_fill(0, $cols, 0));
for ($i = 0; $i < $rows; $i++) {
for ($j = 0; $j < $cols; $j++) {
for ($k = 0; $k < $inner; $k++) {
$result[$i][$j] += $a[$i][$k] * $b[$k][$j];
}
}
}
return $result;
}
$X = array_map(function() {
return array_map(fn() => mt_rand(0, 10) / 10, range(0, 2));
}, range(0, 2));
$Y = array_map(function() {
return array_map(fn() => mt_rand(0, 10) / 10, range(0, 2));
}, range(0, 2));
$Z = matMul($X, $Y);
// Element-wise multiplication
$W = array_map(function($rowX, $rowY) {
return array_map(fn($x, $y) => $x * $y, $rowX, $rowY);
}, $X, $Y);
// Matrix norm (Frobenius)
function norm($matrix) {
$sum = 0;
foreach ($matrix as $row) {
foreach ($row as $val) {
$sum += $val * $val;
}
}
return sqrt($sum);
}
// Trace
function trace($matrix) {
$sum = 0;
for ($i = 0; $i < count($matrix); $i++) {
$sum += $matrix[$i][$i];
}
return $sum;
}
// Diagonal
function diag($matrix) {
$result = [];
for ($i = 0; $i < count($matrix); $i++) {
$result[] = $matrix[$i][$i];
}
return $result;
}
echo "Norm: " . norm($X) . "\n";
echo "Trace: " . trace($X) . "\n";
print_r(diag($X));
?>PHP handles missing data using null values, with operators and functions for safe handling.
- Null coalescing:
$value ?? 'default' - Null coalescing assignment:
$value ??= 'default' - Null check:
is_null($value) - Filter:
array_filter($data, fn($x) => $x !== null) - Optional:
?string $value
<?php
// Working with Missing Data (NULL handling)
// Creating arrays with missing values
$data = [1, 2, null, 4, 5, null, 7];
print_r($data);
// Check for null values
function hasNull($arr) {
return in_array(null, $arr, true);
}
echo "Has null: " . var_export(hasNull($data), true) . "\n";
// Remove null values
$clean_data = array_filter($data, fn($x) => $x !== null);
print_r($clean_data);
// Replace null values
$replaced = array_map(fn($x) => $x ?? 0, $data);
print_r($replaced);
// Operations with null values
$x = [1, 2, null, 4];
$y = [5, 6, null, 8];
$z = array_map(function($a, $b) {
if ($a !== null && $b !== null) {
return $a + $b;
}
return null;
}, $x, $y);
print_r($z);
// Ignoring null values
$sum_complete = array_reduce(array_filter($x, fn($v) => $v !== null), fn($acc, $v) => $acc + $v, 0);
echo "Sum of complete data: $sum_complete\n";
// Null coalescing operator
$value = $data[10] ?? 'default';
echo $value . "\n";
// Null coalescing assignment (PHP 7.4+)
$value = null;
$value ??= 'default';
echo $value . "\n";
// Optional and Nullable types
function processNullable(?string $value): ?string {
return $value;
}
// Working with NULL in arrays
$array = [
'name' => 'Alice',
'age' => null,
'city' => 'NYC'
];
foreach ($array as $key => $value) {
if ($value === null) {
echo "$key is null\n";
} else {
echo "$key: $value\n";
}
}
// Using array_key_exists vs isset
$arr = ['a' => null, 'b' => 1];
echo var_export(isset($arr['a']), true) . "\n"; // false
echo var_export(array_key_exists('a', $arr), true) . "\n"; // true
?>PHP provides built-in sorting functions and custom search implementations.
- Sort:
sort($arr) - Custom sort:
usort($arr, fn($a, $b) => $a <=> $b) - Associative sort:
asort,ksort - Search:
array_filter,in_array - Binary search: Custom implementation
<?php
// Sorting and Searching
// Basic sorting
$arr = [5, 2, 8, 1, 9, 3];
sort($arr);
print_r($arr);
// Sorting without mutation
$arr2 = [5, 2, 8, 1, 9, 3];
$sorted = $arr2;
sort($sorted);
print_r($arr2);
print_r($sorted);
// Sorting with custom comparator
$arr3 = [[5, 'apple'], [3, 'banana'], [8, 'cherry']];
usort($arr3, function($a, $b) {
return $a[0] <=> $b[0];
});
print_r($arr3);
// Sorting descending
$arr4 = [5, 2, 8, 1, 9, 3];
rsort($arr4);
print_r($arr4);
// Associative array sorting
$arr5 = ['apple' => 5, 'banana' => 3, 'cherry' => 8];
asort($arr5); // Sort by values, keep keys
print_r($arr5);
ksort($arr5); // Sort by keys
print_r($arr5);
// Search functions
$arr6 = [1, 3, 5, 7, 9, 11];
$greater_than_5 = array_filter($arr6, fn($x) => $x > 5);
print_r($greater_than_5);
$first_greater_than_5 = array_find($arr6, fn($x) => $x > 5); // PHP 8.4+
$last_greater_than_5 = null;
foreach ($arr6 as $value) {
if ($value > 5) {
$last_greater_than_5 = $value;
}
}
echo "First greater: " . ($first_greater_than_5 ?? 'null') . "\n";
echo "Last greater: " . ($last_greater_than_5 ?? 'null') . "\n";
// Contains
$has_seven = in_array(7, $arr6);
$has_four = in_array(4, $arr6);
echo "Has 7: " . var_export($has_seven, true) . "\n";
echo "Has 4: " . var_export($has_four, true) . "\n";
// Binary search (PHP 8.4+)
$arr7 = [1, 2, 3, 4, 5, 6, 7];
// $index = array_binary_search($arr7, 5); // PHP 8.4+
// echo "Found at index: $index\n";
// Custom binary search
function binarySearch($arr, $target) {
$left = 0;
$right = count($arr) - 1;
while ($left <= $right) {
$mid = intdiv($left + $right, 2);
if ($arr[$mid] == $target) {
return $mid;
} elseif ($arr[$mid] < $target) {
$left = $mid + 1;
} else {
$right = $mid - 1;
}
}
return -1;
}
$index = binarySearch($arr7, 5);
echo "Found at index: $index\n";
?>PHP provides extensive mathematical functions for arithmetic, trigonometry, statistics, and linear algebra.
- Arithmetic:
+,-,*,/,% - Trigonometric:
sin,cos,tan - Random:
rand,mt_rand - Statistics:
array_sum, custom stats - Linear algebra: Custom implementations
<?php
// Mathematical Operations
// Basic arithmetic
$x = 10;
$y = 3;
echo "x + y = " . ($x + $y) . "\n";
echo "x - y = " . ($x - $y) . "\n";
echo "x * y = " . ($x * $y) . "\n";
echo "x / y = " . ($x / $y) . "\n";
echo "x % y = " . ($x % $y) . "\n";
echo "x ^ y = " . pow($x, $y) . "\n";
// Mathematical functions
$pi = M_PI;
echo "sin(pi/4) = " . sin($pi / 4) . "\n";
echo "cos(pi/4) = " . cos($pi / 4) . "\n";
echo "tan(pi/4) = " . tan($pi / 4) . "\n";
echo "exp(1) = " . exp(1) . "\n";
echo "log(e) = " . log(exp(1)) . "\n";
echo "log10(100) = " . log10(100) . "\n";
echo "sqrt(9) = " . sqrt(9) . "\n";
// Special functions
echo "abs(-5) = " . abs(-5) . "\n";
echo "ceil(3.14) = " . ceil(3.14) . "\n";
echo "floor(3.14) = " . floor(3.14) . "\n";
echo "round(3.14) = " . round(3.14) . "\n";
echo "max(1, 3, 5, 2, 4) = " . max(1, 3, 5, 2, 4) . "\n";
echo "min(1, 3, 5, 2, 4) = " . min(1, 3, 5, 2, 4) . "\n";
// Random numbers
echo "rand(1, 10) = " . rand(1, 10) . "\n";
echo "mt_rand(1, 10) = " . mt_rand(1, 10) . "\n";
echo "random_int(1, 10) = " . random_int(1, 10) . "\n";
// Statistics (using built-in functions)
$data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
echo "sum = " . array_sum($data) . "\n";
echo "mean = " . array_sum($data) / count($data) . "\n";
echo "min = " . min($data) . "\n";
echo "max = " . max($data) . "\n";
// Using stats package (if available)
// composer require stats/stats
// Linear algebra functions
function matMul($a, $b) {
$rows = count($a);
$cols = count($b[0]);
$inner = count($b);
$result = array_fill(0, $rows, array_fill(0, $cols, 0));
for ($i = 0; $i < $rows; $i++) {
for ($j = 0; $j < $cols; $j++) {
for ($k = 0; $k < $inner; $k++) {
$result[$i][$j] += $a[$i][$k] * $b[$k][$j];
}
}
}
return $result;
}
$A = [[1, 2], [3, 4]];
$B = [[5, 6], [7, 8]];
$C = matMul($A, $B);
print_r($C);
?>PHP provides various serialization methods including serialize, JSON, and XML for data exchange.
- serialize:
serialize($data) - JSON:
json_encode,json_decode - var_export:
var_export($data, true) - XML:
SimpleXMLElement - CSV:
fputcsv,fgetcsv
<?php
// Data Serialization
// Using serialize/unserialize
$data = ['name' => 'Alice', 'age' => 25, 'hobbies' => ['reading', 'coding']];
$serialized = serialize($data);
echo $serialized . "\n";
$deserialized = unserialize($serialized);
print_r($deserialized);
// Using json_encode/json_decode
$json_data = json_encode($data, JSON_PRETTY_PRINT);
echo $json_data . "\n";
$parsed = json_decode($json_data, true);
print_r($parsed);
// Using var_export with eval
$exported = var_export($data, true);
echo $exported . "\n";
eval('$restored = ' . $exported . ';');
print_r($restored);
// Using yaml (requires yaml extension)
// $yaml = yaml_emit($data);
// echo $yaml . "\n";
// Using XML serialization
function arrayToXML($data, $rootNode) {
$xml = new SimpleXMLElement("<$rootNode/>");
arrayToXMLRecursive($data, $xml);
return $xml;
}
function arrayToXMLRecursive($data, &$xml) {
foreach ($data as $key => $value) {
if (is_array($value)) {
$node = $xml->addChild($key);
arrayToXMLRecursive($value, $node);
} else {
$xml->addChild($key, $value);
}
}
}
$xml = arrayToXML($data, 'root');
echo $xml->asXML();
// Using CSV serialization
function arrayToCSV($data) {
$output = fopen('php://memory', 'r+');
foreach ($data as $row) {
fputcsv($output, $row);
}
rewind($output);
return stream_get_contents($output);
}
function csvToArray($csv) {
$rows = [];
$handle = fopen('php://memory', 'r+');
fwrite($handle, $csv);
rewind($handle);
while (($row = fgetcsv($handle)) !== false) {
$rows[] = $row;
}
fclose($handle);
return $rows;
}
// Using msgpack (requires msgpack extension)
// $packed = msgpack_pack($data);
// $unpacked = msgpack_unpack($packed);
// Using Igbinary (requires igbinary extension)
// $packed = igbinary_serialize($data);
// $unpacked = igbinary_unserialize($packed);
?>PHP can interface with databases, Redis, Memcached, SOAP services, and execute shell commands.
- Database: PDO, MySQLi
- Redis:
Redisextension - Memcached:
Memcachedextension - SOAP:
SoapClient - Shell:
exec,shell_exec
<?php
// Interfacing with External Systems
// Database connections
try {
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([1]);
$user = $stmt->fetch();
print_r($user);
} catch (PDOException $e) {
echo "Database error: " . $e->getMessage() . "\n";
}
// Redis
// $redis = new Redis();
// $redis->connect('127.0.0.1', 6379);
// $redis->set('key', 'value');
// $value = $redis->get('key');
// Memcached
// $memcached = new Memcached();
// $memcached->addServer('localhost', 11211);
// $memcached->set('key', 'value');
// $value = $memcached->get('key');
// Executing shell commands
$output = shell_exec('ls -la');
echo $output;
// Executing with exec
exec('ls -la', $output, $returnCode);
print_r($output);
// Using system
system('echo "Hello from system"');
// Using popen
$handle = popen('ls -la', 'r');
while (!feof($handle)) {
echo fgets($handle);
}
pclose($handle);
// SOAP client
try {
$client = new SoapClient('https://example.com/service.wsdl');
$result = $client->someMethod(['param' => 'value']);
print_r($result);
} catch (SoapFault $e) {
echo "SOAP error: " . $e->getMessage() . "\n";
}
// REST API client (using Guzzle)
// composer require guzzlehttp/guzzle
use GuzzleHttp\Client;
$client = new Client();
$response = $client->get('https://api.github.com');
echo $response->getBody();
// Using PHP extensions
// echo "Loaded extensions: " . implode(', ', get_loaded_extensions()) . "\n";
// echo "Extension info: " . phpinfo() . "\n";
?>Reverse a string using strrev, manual iteration, or recursion.
- Built-in:
strrev($s) - Manual:
for ($i = strlen($s)-1; $i >= 0; $i--) - Recursive:
reverseStringRecursive - Array:
implode('', array_reverse(str_split($s)))
<?php
// Reverse a string
function reverseString($s) {
return strrev($s);
}
function reverseStringManual($s) {
$len = strlen($s);
$reversed = '';
for ($i = $len - 1; $i >= 0; $i--) {
$reversed .= $s[$i];
}
return $reversed;
}
function reverseStringRecursive($s) {
if (strlen($s) <= 1) {
return $s;
}
return reverseStringRecursive(substr($s, 1)) . $s[0];
}
function reverseStringByArray($s) {
return implode('', array_reverse(str_split($s)));
}
$s = "hello";
echo "Original: $s\n";
echo "Reversed: " . reverseString($s) . "\n";
echo "Reversed (manual): " . reverseStringManual($s) . "\n";
echo "Reversed (recursive): " . reverseStringRecursive($s) . "\n";
echo "Reversed (array): " . reverseStringByArray($s) . "\n";
?>Check if a string is a palindrome by comparing characters from both ends.
- Built-in:
$s === strrev($s) - Manual: Two-pointer comparison
- Recursive:
isPalindromeRecursive - Case insensitive:
strtolower
<?php
// Check palindrome
function isPalindrome($s) {
$cleaned = strtolower(str_replace(' ', '', $s));
return $cleaned === strrev($cleaned);
}
function isPalindromeManual($s) {
$cleaned = strtolower(str_replace(' ', '', $s));
$len = strlen($cleaned);
for ($i = 0; $i < $len / 2; $i++) {
if ($cleaned[$i] !== $cleaned[$len - 1 - $i]) {
return false;
}
}
return true;
}
function isPalindromeRecursive($s) {
$cleaned = strtolower(str_replace(' ', '', $s));
$len = strlen($cleaned);
if ($len <= 1) {
return true;
}
if ($cleaned[0] !== $cleaned[$len - 1]) {
return false;
}
return isPalindromeRecursive(substr($cleaned, 1, $len - 2));
}
$strings = ["racecar", "hello", "A man a plan a canal Panama", "race a car"];
foreach ($strings as $s) {
echo ""$s" is palindrome: " . var_export(isPalindrome($s), true) . "\n";
}
?>Find the maximum value using max, iteration, or recursion.
- Built-in:
max($arr) - Manual:
foreachiteration - Recursive:
findMaxRecursive - Reduce:
array_reduce
<?php
// Find max in array
function findMax($arr) {
return max($arr);
}
function findMaxManual($arr) {
if (empty($arr)) {
return null;
}
$max = $arr[0];
foreach ($arr as $value) {
if ($value > $max) {
$max = $value;
}
}
return $max;
}
function findMaxRecursive($arr, $index = 0, $max = null) {
if ($index >= count($arr)) {
return $max;
}
if ($max === null || $arr[$index] > $max) {
$max = $arr[$index];
}
return findMaxRecursive($arr, $index + 1, $max);
}
function findMaxReduce($arr) {
return array_reduce($arr, function($carry, $item) {
return $carry === null || $item > $carry ? $item : $carry;
}, null);
}
$arr = [1, 5, 3, 9, 2];
echo "Array: " . implode(', ', $arr) . "\n";
echo "Max: " . findMax($arr) . "\n";
echo "Max (manual): " . findMaxManual($arr) . "\n";
echo "Max (recursive): " . findMaxRecursive($arr) . "\n";
echo "Max (reduce): " . findMaxReduce($arr) . "\n";
?>Remove duplicates using array_unique, manual loop, or array keys.
- Built-in:
array_unique($arr) - Manual:
in_arraycheck - Set: Using array keys
- Preserve order:
array_values
<?php
// Remove duplicates
function removeDuplicates($arr) {
return array_unique($arr);
}
function removeDuplicatesManual($arr) {
$seen = [];
$result = [];
foreach ($arr as $value) {
if (!in_array($value, $seen)) {
$seen[] = $value;
$result[] = $value;
}
}
return $result;
}
function removeDuplicatesSet($arr) {
$set = [];
foreach ($arr as $value) {
$set[$value] = true;
}
return array_keys($set);
}
$arr = ['apple', 'banana', 'apple', 'orange', 'banana', 'grape'];
echo "Original: " . implode(', ', $arr) . "\n";
echo "Without duplicates: " . implode(', ', removeDuplicates($arr)) . "\n";
echo "Without duplicates (manual): " . implode(', ', removeDuplicatesManual($arr)) . "\n";
echo "Without duplicates (set): " . implode(', ', removeDuplicatesSet($arr)) . "\n";
?>Merge arrays using array_merge, spread operator, or manual merge.
- array_merge:
array_merge($arr1, $arr2) - Spread:
[...$arr1, ...$arr2] - Sorted merge:
mergeSorted - Unique:
array_unique(array_merge($arr1, $arr2))
<?php
// Merge arrays
function mergeArrays($arr1, $arr2) {
return array_merge($arr1, $arr2);
}
function mergeArraysSpread($arr1, $arr2) {
return [...$arr1, ...$arr2];
}
function mergeSorted($arr1, $arr2) {
$result = [];
$i = 0;
$j = 0;
while ($i < count($arr1) && $j < count($arr2)) {
if ($arr1[$i] <= $arr2[$j]) {
$result[] = $arr1[$i];
$i++;
} else {
$result[] = $arr2[$j];
$j++;
}
}
while ($i < count($arr1)) {
$result[] = $arr1[$i];
$i++;
}
while ($j < count($arr2)) {
$result[] = $arr2[$j];
$j++;
}
return $result;
}
function mergeUnique($arr1, $arr2) {
return array_unique(array_merge($arr1, $arr2));
}
$arr1 = [1, 2, 3];
$arr2 = [4, 5, 6];
echo "Merged: " . implode(', ', mergeArrays($arr1, $arr2)) . "\n";
echo "Merged (spread): " . implode(', ', mergeArraysSpread($arr1, $arr2)) . "\n";
$sorted1 = [1, 3, 5, 7];
$sorted2 = [2, 4, 6, 8];
echo "Merged sorted: " . implode(', ', mergeSorted($sorted1, $sorted2)) . "\n";
?>Convert string to number using floatval, intval, or type casting.
- Float:
floatval($s) - Int:
intval($s) - Casting:
(float)$s,(int)$s - Safe:
is_numericcheck
<?php
// Convert string to number
function stringToNumber($s) {
return floatval($s);
}
function stringToInt($s) {
return intval($s);
}
function stringToFloat($s) {
return floatval($s);
}
function stringToNumberSafe($s) {
if (is_numeric($s)) {
return floatval($s);
}
return 0;
}
function stringToIntWithFilter($s) {
return filter_var($s, FILTER_VALIDATE_INT) ?: 0;
}
function stringToFloatWithFilter($s) {
return filter_var($s, FILTER_VALIDATE_FLOAT) ?: 0.0;
}
$strings = ["42", "3.14", "hello", "123", "45.67"];
foreach ($strings as $s) {
echo ""$s" -> int: " . stringToInt($s) . ", float: " . stringToFloat($s) . "\n";
}
?>Iterate through associative arrays using foreach or array_keys.
- foreach:
foreach ($dict as $key => $value) - Keys:
array_keyswithforeach - Values:
array_valuesfor values only - Find key:
$dict[$key] ?? null
<?php
// Loop through dictionary (associative array)
function loopDict($dict) {
foreach ($dict as $key => $value) {
echo "$key => $value\n";
}
}
function loopDictWithKeys($dict) {
foreach (array_keys($dict) as $key) {
echo "$key => {$dict[$key]}\n";
}
}
function loopDictWithValues($dict) {
foreach (array_values($dict) as $value) {
echo "$value\n";
}
}
function findKey($dict, $key) {
return $dict[$key] ?? null;
}
$data = ["name" => "Alice", "age" => 25, "city" => "NYC"];
echo "Dictionary:\n";
loopDict($data);
echo "\n";
$name = findKey($data, "name");
echo "Name: $name\n";
$country = findKey($data, "country");
echo "Country: " . ($country ?? "Not found") . "\n";
?>Delay execution using sleep or usleep for blocking delays.
- Seconds:
sleep($seconds) - Microseconds:
usleep($microseconds) - Async: Using
pcntl_fork - Callback:
delayWithCallback
<?php
// Delay function execution
function delaySeconds($seconds, $callback) {
sleep($seconds);
return $callback();
}
function delayAsync($seconds, $callback) {
// This is a simplified approach using pcntl
if (function_exists('pcntl_fork')) {
$pid = pcntl_fork();
if ($pid == 0) {
sleep($seconds);
$callback();
exit(0);
}
return $pid;
}
return null;
}
function delayWithCallback($seconds, $callback, $resultCallback) {
if (function_exists('pcntl_fork')) {
$pid = pcntl_fork();
if ($pid == 0) {
sleep($seconds);
$result = $callback();
// In a real application, you'd use IPC here
$resultCallback($result);
exit(0);
}
return $pid;
}
return null;
}
function delayedPrint($message, $seconds) {
echo "Starting delay of $seconds seconds\n";
delaySeconds($seconds, function() use ($message) {
echo "$message\n";
return true;
});
}
echo "Delayed execution examples:\n";
delayedPrint("After 2 seconds", 2);
// For async examples, we'd need to handle process management
echo "Main script continues\n";
?>Make HTTP requests using cURL, file_get_contents, or Guzzle.
- cURL:
curl_init,curl_exec - file_get_contents: With stream context
- Guzzle:
$client->get() - Error handling: Try-catch
<?php
// HTTP GET request
function fetchData($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_USERAGENT, 'PHP Script');
$response = curl_exec($ch);
$error = curl_error($ch);
$info = curl_getinfo($ch);
curl_close($ch);
if ($error) {
throw new Exception("cURL error: $error");
}
return $response;
}
function postData($url, $data) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
// Using file_get_contents with stream context
function fetchDataSimple($url) {
$context = stream_context_create([
'http' => [
'method' => 'GET',
'header' => 'User-Agent: PHP Script'
]
]);
return file_get_contents($url, false, $context);
}
try {
$result = fetchData("https://api.github.com");
echo substr($result, 0, 500) . "...\n";
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
// Example POST request
$postData = ['name' => 'Alice', 'age' => 25];
// $result = postData('https://httpbin.org/post', $postData);
// echo $result;
?>Create promise-like behavior using a custom Promise class with then, catch, and all methods.
- Promise class: Custom implementation
- then: Chain callbacks
- catch: Error handling
- all: Multiple promises
<?php
// Create a promise-like task
class Promise {
private $callbacks = [];
private $state = 'pending';
private $result = null;
public function __construct($executor) {
try {
$executor(
function($value) {
$this->resolve($value);
},
function($reason) {
$this->reject($reason);
}
);
} catch (Exception $e) {
$this->reject($e);
}
}
private function resolve($value) {
if ($this->state !== 'pending') {
return;
}
$this->state = 'fulfilled';
$this->result = $value;
$this->executeCallbacks();
}
private function reject($reason) {
if ($this->state !== 'pending') {
return;
}
$this->state = 'rejected';
$this->result = $reason;
$this->executeCallbacks();
}
private function executeCallbacks() {
foreach ($this->callbacks as $callback) {
call_user_func($callback, $this->result);
}
$this->callbacks = [];
}
public function then($onFulfilled = null, $onRejected = null) {
$promise = new self(function($resolve, $reject) use ($onFulfilled, $onRejected) {
$callback = function($value) use ($resolve, $reject, $onFulfilled, $onRejected) {
if ($this->state === 'fulfilled' && $onFulfilled) {
try {
$result = $onFulfilled($value);
$resolve($result);
} catch (Exception $e) {
$reject($e);
}
} elseif ($this->state === 'rejected' && $onRejected) {
try {
$result = $onRejected($value);
$resolve($result);
} catch (Exception $e) {
$reject($e);
}
} else {
$this->state === 'fulfilled' ? $resolve($value) : $reject($value);
}
};
if ($this->state === 'pending') {
$this->callbacks[] = $callback;
} else {
$callback($this->result);
}
});
return $promise;
}
public function catch($onRejected) {
return $this->then(null, $onRejected);
}
public static function all($promises) {
return new self(function($resolve, $reject) use ($promises) {
$results = [];
$remaining = count($promises);
if ($remaining === 0) {
$resolve($results);
return;
}
foreach ($promises as $index => $promise) {
$promise->then(
function($value) use ($index, &$results, &$remaining, $resolve) {
$results[$index] = $value;
$remaining--;
if ($remaining === 0) {
$resolve($results);
}
},
function($reason) use ($reject) {
$reject($reason);
}
);
}
});
}
}
// Usage
$promise1 = new Promise(function($resolve, $reject) {
sleep(1);
$resolve("Success!");
});
$promise1->then(function($value) {
echo "Result: $value\n";
});
$promise2 = new Promise(function($resolve, $reject) {
sleep(2);
$reject("Failed!");
});
$promise2->catch(function($reason) {
echo "Error: $reason\n";
});
// Promise.all
$promises = [
new Promise(function($resolve) { sleep(1); $resolve("One"); }),
new Promise(function($resolve) { sleep(2); $resolve("Two"); }),
new Promise(function($resolve) { sleep(1); $resolve("Three"); })
];
Promise::all($promises)->then(function($results) {
echo "All promises complete: " . implode(', ', $results) . "\n";
});
// Wait for all promises to complete
sleep(3);
?>Calculate factorial using recursion, iteration, or tail recursion.
- Recursive:
function fact($n) { return $n <= 1 ? 1 : $n * fact($n-1); } - Iterative:
for ($i = 2; $i <= $n; $i++) - Tail recursive:
factTail($n, 1) - Edge cases: 0! = 1
<?php
// Factorial
function factorial($n) {
if ($n <= 1) {
return 1;
}
return $n * factorial($n - 1);
}
function factorialIterative($n) {
$result = 1;
for ($i = 2; $i <= $n; $i++) {
$result *= $i;
}
return $result;
}
function factorialTailRecursive($n, $acc = 1) {
if ($n <= 1) {
return $acc;
}
return factorialTailRecursive($n - 1, $acc * $n);
}
$n = 5;
echo "Factorial of $n:\n";
echo "Recursive: " . factorial($n) . "\n";
echo "Iterative: " . factorialIterative($n) . "\n";
echo "Tail recursive: " . factorialTailRecursive($n) . "\n";
?>Calculate Fibonacci numbers using recursion, iteration, or memoization.
- Recursive:
function fib($n) { return $n <= 1 ? $n : fib($n-1) + fib($n-2); } - Iterative:
for ($i = 2; $i <= $n; $i++) - Memoized: Static cache
- Generator: Yield sequence
<?php
// Fibonacci
function fibonacci($n) {
if ($n <= 1) {
return $n;
}
return fibonacci($n - 1) + fibonacci($n - 2);
}
function fibonacciIterative($n) {
if ($n <= 1) {
return $n;
}
$a = 0;
$b = 1;
for ($i = 2; $i <= $n; $i++) {
$c = $a + $b;
$a = $b;
$b = $c;
}
return $b;
}
function fibonacciMemoized($n) {
static $cache = [];
if ($n <= 1) {
return $n;
}
if (!isset($cache[$n])) {
$cache[$n] = fibonacciMemoized($n - 1) + fibonacciMemoized($n - 2);
}
return $cache[$n];
}
function fibonacciGenerator($n) {
$a = 0;
$b = 1;
for ($i = 0; $i < $n; $i++) {
yield $a;
$c = $a + $b;
$a = $b;
$b = $c;
}
}
$n = 10;
echo "Fibonacci of $n:\n";
echo "Recursive: " . fibonacci($n) . "\n";
echo "Iterative: " . fibonacciIterative($n) . "\n";
echo "Memoized: " . fibonacciMemoized($n) . "\n";
echo "First 10 Fibonacci numbers: ";
foreach (fibonacciGenerator(10) as $num) {
echo $num . " ";
}
echo "\n";
?>Print numbers with FizzBuzz logic using conditional statements or match expression.
- If-else:
if ($i % 15 == 0) - Match: PHP 8.0+ match expression
- Array:
fizzbuzzArray - Edge cases: n >= 1
<?php
// FizzBuzz
function fizzbuzz($n) {
for ($i = 1; $i <= $n; $i++) {
if ($i % 15 == 0) {
echo "FizzBuzz\n";
} elseif ($i % 3 == 0) {
echo "Fizz\n";
} elseif ($i % 5 == 0) {
echo "Buzz\n";
} else {
echo "$i\n";
}
}
}
function fizzbuzzArray($n) {
$result = [];
for ($i = 1; $i <= $n; $i++) {
if ($i % 15 == 0) {
$result[] = "FizzBuzz";
} elseif ($i % 3 == 0) {
$result[] = "Fizz";
} elseif ($i % 5 == 0) {
$result[] = "Buzz";
} else {
$result[] = (string)$i;
}
}
return $result;
}
function fizzbuzzMatch($n) {
for ($i = 1; $i <= $n; $i++) {
echo match(($i % 3 == 0 ? 1 : 0) + ($i % 5 == 0 ? 2 : 0)) {
0 => (string)$i,
1 => "Fizz",
2 => "Buzz",
3 => "FizzBuzz"
} . "\n";
}
}
echo "FizzBuzz for 15:\n";
fizzbuzz(15);
echo "FizzBuzz array:\n";
print_r(fizzbuzzArray(15));
echo "FizzBuzz match:\n";
fizzbuzzMatch(15);
?>Find missing number using sum formula or XOR operation.
- Sum:
($n * ($n + 1) / 2) - array_sum($arr) - XOR:
$xor_all ^ $xor_arr - Edge cases: Empty array
- Time: O(n)
<?php
// Find missing number
function findMissing($arr) {
$n = count($arr) + 1;
$total = $n * ($n + 1) / 2;
$sum = array_sum($arr);
return $total - $sum;
}
function findMissingXOR($arr) {
$n = count($arr) + 1;
$xor_all = 0;
for ($i = 1; $i <= $n; $i++) {
$xor_all ^= $i;
}
$xor_arr = 0;
foreach ($arr as $value) {
$xor_arr ^= $value;
}
return $xor_all ^ $xor_arr;
}
$arr = [1, 2, 4, 5, 6];
echo "Missing number: " . findMissing($arr) . "\n";
echo "Missing number (XOR): " . findMissingXOR($arr) . "\n";
?>Find duplicates using array_count_values, array_filter, or manual tracking.
- Count:
array_count_values - Manual:
in_arraycheck - Set: Array keys
- Time: O(n)
<?php
// Find duplicates
function findDuplicates($arr) {
$seen = [];
$duplicates = [];
foreach ($arr as $value) {
if (in_array($value, $seen)) {
if (!in_array($value, $duplicates)) {
$duplicates[] = $value;
}
} else {
$seen[] = $value;
}
}
return $duplicates;
}
function findDuplicatesSet($arr) {
$seen = [];
$duplicates = [];
foreach ($arr as $value) {
if (isset($seen[$value])) {
$duplicates[$value] = true;
} else {
$seen[$value] = true;
}
}
return array_keys($duplicates);
}
function findDuplicatesCount($arr) {
$counts = array_count_values($arr);
return array_keys(array_filter($counts, fn($count) => $count > 1));
}
$arr = [1, 2, 3, 2, 4, 3, 5, 6, 5];
echo "Original: " . implode(', ', $arr) . "\n";
echo "Duplicates: " . implode(', ', findDuplicates($arr)) . "\n";
echo "Duplicates (set): " . implode(', ', findDuplicatesSet($arr)) . "\n";
echo "Duplicates (count): " . implode(', ', findDuplicatesCount($arr)) . "\n";
?>Sum array elements using array_sum, manual loop, or reduce.
- Built-in:
array_sum($arr) - Manual:
foreach ($arr as $v) $sum += $v - Reduce:
array_reduce($arr, fn($c, $v) => $c + $v, 0) - Empty array: Returns 0
<?php
// Sum of array
function sumArray($arr) {
return array_sum($arr);
}
function sumArrayManual($arr) {
$sum = 0;
foreach ($arr as $value) {
$sum += $value;
}
return $sum;
}
function sumArrayReduce($arr) {
return array_reduce($arr, fn($carry, $item) => $carry + $item, 0);
}
$arr = [1, 2, 3, 4, 5];
echo "Array: " . implode(', ', $arr) . "\n";
echo "Sum: " . sumArray($arr) . "\n";
echo "Sum (manual): " . sumArrayManual($arr) . "\n";
echo "Sum (reduce): " . sumArrayReduce($arr) . "\n";
?>Calculate average by dividing sum by count. Handle empty arrays.
- Method:
array_sum($arr) / count($arr) - Float:
array_sum($arr) / count($arr) - Integer:
intdiv(array_sum($arr), count($arr)) - Empty: Return 0
<?php
// Average of array
function averageArray($arr) {
return empty($arr) ? 0 : array_sum($arr) / count($arr);
}
function averageArrayFloat($arr) {
return empty($arr) ? 0.0 : array_sum($arr) / count($arr);
}
function averageInteger($arr) {
return empty($arr) ? 0 : intdiv(array_sum($arr), count($arr));
}
$int_arr = [1, 2, 3, 4, 5];
$float_arr = [1.0, 2.0, 3.0, 4.0, 5.0];
echo "Average (int array): " . averageArray($int_arr) . "\n";
echo "Average (float array): " . averageArrayFloat($float_arr) . "\n";
echo "Average (integer): " . averageInteger($int_arr) . "\n";
?>Sort arrays using sort or custom usort.
- Non-mutating: Copy then sort
- Mutating:
sort($arr) - Custom:
usort($arr, fn($a, $b) => $a <=> $b) - Associative:
asortfor values
<?php
// Sort array ascending
function sortAscending($arr) {
$sorted = $arr;
sort($sorted);
return $sorted;
}
function sortAscendingInPlace(&$arr) {
sort($arr);
}
function sortAscendingCustom($arr) {
usort($arr, fn($a, $b) => $a <=> $b);
return $arr;
}
$arr = [5, 2, 8, 1, 9, 3];
echo "Original: " . implode(', ', $arr) . "\n";
echo "Sorted ascending: " . implode(', ', sortAscending($arr)) . "\n";
sortAscendingInPlace($arr);
echo "Sorted in-place: " . implode(', ', $arr) . "\n";
?>Sort descending using rsort or custom comparator.
- Non-mutating: Copy then
rsort - Mutating:
rsort($arr) - Custom:
usort($arr, fn($a, $b) => $b <=> $a) - Associative:
arsort
<?php
// Sort array descending
function sortDescending($arr) {
$sorted = $arr;
rsort($sorted);
return $sorted;
}
function sortDescendingInPlace(&$arr) {
rsort($arr);
}
function sortDescendingCustom($arr) {
usort($arr, fn($a, $b) => $b <=> $a);
return $arr;
}
$arr = [5, 2, 8, 1, 9, 3];
echo "Original: " . implode(', ', $arr) . "\n";
echo "Sorted descending: " . implode(', ', sortDescending($arr)) . "\n";
sortDescendingInPlace($arr);
echo "Sorted in-place: " . implode(', ', $arr) . "\n";
?>Flatten nested arrays using recursion or iterative stack approach.
- Recursive:
function flatten($arr) { ... } - Iterative: Stack-based
- One level:
array_merge(...$arr) - Depth: Handle arbitrary depth
<?php
// Flatten nested array
function flatten($arr) {
$result = [];
foreach ($arr as $item) {
if (is_array($item)) {
$result = array_merge($result, flatten($item));
} else {
$result[] = $item;
}
}
return $result;
}
function flattenIterative($arr) {
$result = [];
$stack = array_reverse($arr);
while (!empty($stack)) {
$item = array_pop($stack);
if (is_array($item)) {
foreach (array_reverse($item) as $subItem) {
$stack[] = $subItem;
}
} else {
$result[] = $item;
}
}
return $result;
}
function flattenOneLevel($arr) {
return array_merge(...$arr);
}
$nested = [[1, 2], [3, 4, 5], [6], [7, 8, 9, 10]];
$deeper = [[1, 2], [3, [4, 5]]];
echo "Nested: " . json_encode($nested) . "\n";
echo "Flatten: " . implode(', ', flatten($nested)) . "\n";
echo "Flatten one level: " . implode(', ', flattenOneLevel($nested)) . "\n";
echo "Deeper: " . json_encode($deeper) . "\n";
echo "Flatten deeper: " . implode(', ', flatten($deeper)) . "\n";
?>Split array into chunks using array_chunk or manual slicing.
- Built-in:
array_chunk($arr, $size) - Manual:
array_slicein loop - Predicate:
chunkByPredicate - Use case: Batch processing
<?php
// Chunk array
function chunkArray($arr, $size) {
return array_chunk($arr, $size);
}
function chunkArrayManual($arr, $size) {
$result = [];
$i = 0;
while ($i < count($arr)) {
$result[] = array_slice($arr, $i, $size);
$i += $size;
}
return $result;
}
function chunkByPredicate($arr, $predicate) {
$result = [];
$current = [];
foreach ($arr as $item) {
if ($predicate($item)) {
if (!empty($current)) {
$result[] = $current;
$current = [];
}
$result[] = [$item];
} else {
$current[] = $item;
}
}
if (!empty($current)) {
$result[] = $current;
}
return $result;
}
$arr = range(1, 10);
echo "Original: " . implode(', ', $arr) . "\n";
echo "Chunk (size 3):\n";
$chunks = chunkArray($arr, 3);
foreach ($chunks as $chunk) {
echo "[" . implode(', ', $chunk) . "] ";
}
echo "\n";
?>Implement binary search on sorted array using while loop or recursion.
- Iterative:
while ($left <= $right) - Recursive:
binarySearchRecursive - First occurrence:
binarySearchFirst - Time: O(log n)
<?php
// Binary search
function binarySearch($arr, $target) {
$left = 0;
$right = count($arr) - 1;
while ($left <= $right) {
$mid = intdiv($left + $right, 2);
if ($arr[$mid] == $target) {
return $mid;
} elseif ($arr[$mid] < $target) {
$left = $mid + 1;
} else {
$right = $mid - 1;
}
}
return -1;
}
function binarySearchRecursive($arr, $target, $left = null, $right = null) {
if ($left === null) {
$left = 0;
$right = count($arr) - 1;
}
if ($left > $right) {
return -1;
}
$mid = intdiv($left + $right, 2);
if ($arr[$mid] == $target) {
return $mid;
} elseif ($arr[$mid] < $target) {
return binarySearchRecursive($arr, $target, $mid + 1, $right);
} else {
return binarySearchRecursive($arr, $target, $left, $mid - 1);
}
}
function binarySearchFirst($arr, $target) {
$left = 0;
$right = count($arr) - 1;
$result = -1;
while ($left <= $right) {
$mid = intdiv($left + $right, 2);
if ($arr[$mid] == $target) {
$result = $mid;
$right = $mid - 1;
} elseif ($arr[$mid] < $target) {
$left = $mid + 1;
} else {
$right = $mid - 1;
}
}
return $result;
}
$arr = [1, 2, 3, 4, 5, 6, 7];
$target = 5;
$index = binarySearch($arr, $target);
echo "Found $target at index: $index\n";
$target2 = 8;
$index2 = binarySearch($arr, $target2);
echo "Found $target2 at index: $index2\n";
?>Implement quick sort with partitioning and recursion.
- Recursive:
quickSort - In-place:
quickSortInPlace - Pivot: Last element
- Time: O(n log n) average
<?php
// Quick sort
function quickSort($arr) {
if (count($arr) <= 1) {
return $arr;
}
$pivot = $arr[0];
$left = [];
$right = [];
for ($i = 1; $i < count($arr); $i++) {
if ($arr[$i] < $pivot) {
$left[] = $arr[$i];
} else {
$right[] = $arr[$i];
}
}
return array_merge(quickSort($left), [$pivot], quickSort($right));
}
function quickSortInPlace(&$arr, $low = null, $high = null) {
if ($low === null) {
$low = 0;
$high = count($arr) - 1;
}
if ($low < $high) {
$pi = partition($arr, $low, $high);
quickSortInPlace($arr, $low, $pi - 1);
quickSortInPlace($arr, $pi + 1, $high);
}
}
function partition(&$arr, $low, $high) {
$pivot = $arr[$high];
$i = $low - 1;
for ($j = $low; $j < $high; $j++) {
if ($arr[$j] <= $pivot) {
$i++;
[$arr[$i], $arr[$j]] = [$arr[$j], $arr[$i]];
}
}
[$arr[$i + 1], $arr[$high]] = [$arr[$high], $arr[$i + 1]];
return $i + 1;
}
function quickSortOptimized($arr) {
if (count($arr) <= 1) {
return $arr;
}
$pivot = $arr[count($arr) - 1];
$left = array_filter($arr, fn($x) => $x < $pivot);
$equal = array_filter($arr, fn($x) => $x == $pivot);
$right = array_filter($arr, fn($x) => $x > $pivot);
return array_merge(
quickSortOptimized($left),
$equal,
quickSortOptimized($right)
);
}
$arr = [5, 3, 8, 4, 2, 7, 1, 6];
echo "Original: " . implode(', ', $arr) . "\n";
echo "Quick sort: " . implode(', ', quickSort($arr)) . "\n";
quickSortInPlace($arr);
echo "Quick sort (in-place): " . implode(', ', $arr) . "\n";
?>Implement merge sort with divide and conquer approach.
- Divide:
array_slice - Merge:
mergefunction - In-place:
mergeSortInPlace - Time: O(n log n)
<?php
// Merge sort
function mergeSort($arr) {
if (count($arr) <= 1) {
return $arr;
}
$mid = intdiv(count($arr), 2);
$left = mergeSort(array_slice($arr, 0, $mid));
$right = mergeSort(array_slice($arr, $mid));
return merge($left, $right);
}
function merge($left, $right) {
$result = [];
$i = 0;
$j = 0;
while ($i < count($left) && $j < count($right)) {
if ($left[$i] <= $right[$j]) {
$result[] = $left[$i];
$i++;
} else {
$result[] = $right[$j];
$j++;
}
}
while ($i < count($left)) {
$result[] = $left[$i];
$i++;
}
while ($j < count($right)) {
$result[] = $right[$j];
$j++;
}
return $result;
}
function mergeSortInPlace(&$arr, $low = null, $high = null, &$temp = null) {
if ($low === null) {
$low = 0;
$high = count($arr) - 1;
$temp = array_fill(0, count($arr), 0);
}
if ($low < $high) {
$mid = intdiv($low + $high, 2);
mergeSortInPlace($arr, $low, $mid, $temp);
mergeSortInPlace($arr, $mid + 1, $high, $temp);
mergeInPlace($arr, $low, $mid, $high, $temp);
}
}
function mergeInPlace(&$arr, $low, $mid, $high, &$temp) {
for ($i = $low; $i <= $high; $i++) {
$temp[$i] = $arr[$i];
}
$i = $low;
$j = $mid + 1;
$k = $low;
while ($i <= $mid && $j <= $high) {
if ($temp[$i] <= $temp[$j]) {
$arr[$k] = $temp[$i];
$i++;
} else {
$arr[$k] = $temp[$j];
$j++;
}
$k++;
}
while ($i <= $mid) {
$arr[$k] = $temp[$i];
$i++;
$k++;
}
}
$arr = [5, 3, 8, 4, 2, 7, 1, 6];
echo "Original: " . implode(', ', $arr) . "\n";
echo "Merge sort: " . implode(', ', mergeSort($arr)) . "\n";
mergeSortInPlace($arr);
echo "Merge sort (in-place): " . implode(', ', $arr) . "\n";
?>Implement bubble sort with optimization to stop early if no swaps occur.
- Basic:
for ($i = 0; $i < $n-1; $i++) - Optimized:
$swappedflag - Time: O(n²) worst case
- Use case: Small datasets
<?php
// Bubble sort
function bubbleSort($arr) {
$n = count($arr);
for ($i = 0; $i < $n - 1; $i++) {
for ($j = 0; $j < $n - $i - 1; $j++) {
if ($arr[$j] > $arr[$j + 1]) {
[$arr[$j], $arr[$j + 1]] = [$arr[$j + 1], $arr[$j]];
}
}
}
return $arr;
}
function bubbleSortOptimized($arr) {
$n = count($arr);
for ($i = 0; $i < $n - 1; $i++) {
$swapped = false;
for ($j = 0; $j < $n - $i - 1; $j++) {
if ($arr[$j] > $arr[$j + 1]) {
[$arr[$j], $arr[$j + 1]] = [$arr[$j + 1], $arr[$j]];
$swapped = true;
}
}
if (!$swapped) {
break;
}
}
return $arr;
}
$arr = [5, 3, 8, 4, 2, 7, 1, 6];
echo "Original: " . implode(', ', $arr) . "\n";
echo "Bubble sort: " . implode(', ', bubbleSort($arr)) . "\n";
echo "Bubble sort optimized: " . implode(', ', bubbleSortOptimized($arr)) . "\n";
?>Find intersection using array_intersect or manual filtering.
- Built-in:
array_intersect($arr1, $arr2) - Manual:
in_arraycheck - Set:
array_flipfor lookup - Multiple:
array_intersectwith multiple
<?php
// Intersection of arrays
function intersection($arr1, $arr2) {
return array_values(array_intersect($arr1, $arr2));
}
function intersectionManual($arr1, $arr2) {
$result = [];
foreach ($arr1 as $value) {
if (in_array($value, $arr2) && !in_array($value, $result)) {
$result[] = $value;
}
}
return $result;
}
function intersectionSet($arr1, $arr2) {
$set = array_flip($arr2);
$result = [];
foreach ($arr1 as $value) {
if (isset($set[$value])) {
$result[$value] = true;
}
}
return array_keys($result);
}
function intersectionMultiple(...$arrays) {
if (empty($arrays)) {
return [];
}
$result = $arrays[0];
for ($i = 1; $i < count($arrays); $i++) {
$result = array_intersect($result, $arrays[$i]);
}
return array_values($result);
}
$arr1 = ['apple', 'banana', 'orange', 'grape', 'kiwi'];
$arr2 = ['banana', 'kiwi', 'mango', 'grape'];
echo "Intersection: " . implode(', ', intersection($arr1, $arr2)) . "\n";
echo "Intersection (manual): " . implode(', ', intersectionManual($arr1, $arr2)) . "\n";
$ints1 = [1, 2, 3, 4, 5];
$ints2 = [4, 5, 6, 7, 8];
echo "Intersection (ints): " . implode(', ', intersection($ints1, $ints2)) . "\n";
?>Union arrays using array_merge with array_unique.
- Built-in:
array_unique(array_merge($arr1, $arr2)) - Manual:
in_arraycheck - Set:
array_flip - Preserve keys:
array_mergewith keys
<?php
// Union of arrays
function union($arr1, $arr2) {
return array_values(array_unique(array_merge($arr1, $arr2)));
}
function unionManual($arr1, $arr2) {
$result = $arr1;
foreach ($arr2 as $value) {
if (!in_array($value, $result)) {
$result[] = $value;
}
}
return $result;
}
function unionSet($arr1, $arr2) {
$set = array_flip($arr1);
foreach ($arr2 as $value) {
$set[$value] = true;
}
return array_keys($set);
}
$arr1 = ['apple', 'banana', 'orange'];
$arr2 = ['orange', 'grape', 'kiwi'];
echo "Union: " . implode(', ', union($arr1, $arr2)) . "\n";
echo "Union (manual): " . implode(', ', unionManual($arr1, $arr2)) . "\n";
$ints1 = [1, 2, 3, 4];
$ints2 = [4, 5, 6, 7];
echo "Union (ints): " . implode(', ', union($ints1, $ints2)) . "\n";
?>Find difference using array_diff or manual filtering.
- Built-in:
array_diff($arr1, $arr2) - Symmetric:
array_diffboth ways - Manual:
in_arraycheck - Multiple:
array_diffwith multiple
<?php
// Difference of arrays
function difference($arr1, $arr2) {
return array_values(array_diff($arr1, $arr2));
}
function differenceManual($arr1, $arr2) {
$result = [];
foreach ($arr1 as $value) {
if (!in_array($value, $arr2)) {
$result[] = $value;
}
}
return $result;
}
function symmetricDifference($arr1, $arr2) {
$diff1 = array_diff($arr1, $arr2);
$diff2 = array_diff($arr2, $arr1);
return array_merge($diff1, $diff2);
}
$arr1 = ['apple', 'banana', 'orange', 'grape'];
$arr2 = ['banana', 'kiwi', 'grape'];
echo "Difference: " . implode(', ', difference($arr1, $arr2)) . "\n";
echo "Symmetric difference: " . implode(', ', symmetricDifference($arr1, $arr2)) . "\n";
$ints1 = [1, 2, 3, 4, 5];
$ints2 = [4, 5, 6, 7, 8];
echo "Difference (ints): " . implode(', ', difference($ints1, $ints2)) . "\n";
?>Group array elements by a property using loops and arrays.
- Method:
groupBy($arr, $key) - Callback:
groupByCallback($arr, $callback) - Aggregation:
groupAndSum - Use case: Data aggregation
<?php
// Group by property
function groupBy($arr, $key) {
$groups = [];
foreach ($arr as $item) {
$groupKey = is_array($item) ? $item[$key] : $item->$key;
if (!isset($groups[$groupKey])) {
$groups[$groupKey] = [];
}
$groups[$groupKey][] = $item;
}
return $groups;
}
function groupByCallback($arr, $callback) {
$groups = [];
foreach ($arr as $item) {
$groupKey = $callback($item);
if (!isset($groups[$groupKey])) {
$groups[$groupKey] = [];
}
$groups[$groupKey][] = $item;
}
return $groups;
}
function groupAndSum($arr, $groupKey, $sumKey) {
$groups = [];
foreach ($arr as $item) {
$group = is_array($item) ? $item[$groupKey] : $item->$groupKey;
$value = is_array($item) ? $item[$sumKey] : $item->$sumKey;
if (!isset($groups[$group])) {
$groups[$group] = 0;
}
$groups[$group] += $value;
}
return $groups;
}
// Example data
$people = [
['name' => 'Alice', 'age' => 25, 'city' => 'NYC'],
['name' => 'Bob', 'age' => 30, 'city' => 'LA'],
['name' => 'Charlie', 'age' => 25, 'city' => 'NYC'],
['name' => 'David', 'age' => 35, 'city' => 'Chicago'],
['name' => 'Eve', 'age' => 30, 'city' => 'LA']
];
echo "Group by age:\n";
$byAge = groupBy($people, 'age');
foreach ($byAge as $age => $persons) {
echo "Age $age: ";
$names = array_column($persons, 'name');
echo implode(', ', $names) . "\n";
}
echo "Group by city:\n";
$byCity = groupBy($people, 'city');
foreach ($byCity as $city => $persons) {
echo "City $city: ";
$names = array_column($persons, 'name');
echo implode(', ', $names) . "\n";
}
?>Create deep copies of objects using recursion to clone nested structures.
- Method:
deepClone - Objects:
clone $obj - Arrays: Recursive copy
- Custom:
deepCloneObject
<?php
// Deep clone object
function deepClone($obj) {
if (is_array($obj)) {
$result = [];
foreach ($obj as $key => $value) {
$result[$key] = deepClone($value);
}
return $result;
} elseif (is_object($obj)) {
return clone $obj;
} else {
return $obj;
}
}
function deepCloneObject($obj) {
$cloned = clone $obj;
foreach (get_object_vars($cloned) as $key => $value) {
if (is_object($value) || is_array($value)) {
$cloned->$key = deepClone($value);
}
}
return $cloned;
}
class Person {
public $name;
public $address;
public function __construct($name, $address) {
$this->name = $name;
$this->address = $address;
}
}
class Address {
public $street;
public $city;
public function __construct($street, $city) {
$this->street = $street;
$this->city = $city;
}
}
$address = new Address('123 Main St', 'NYC');
$person = new Person('Alice', $address);
$cloned = deepCloneObject($person);
$cloned->address->street = '456 Oak St';
echo "Original: " . $person->address->street . "\n";
echo "Cloned: " . $cloned->address->street . "\n";
?>Perform immutable updates on nested data structures using path-based updates.
- Method:
updateImmutable($array, $path, $value) - Path: Dot notation
- Recursive: Helper function
- Use case: State management
<?php
// Immutable update
function updateImmutable($array, $path, $value) {
$parts = explode('.', $path);
if (count($parts) == 1) {
$result = $array;
$result[$parts[0]] = $value;
return $result;
}
$first = $parts[0];
$rest = implode('.', array_slice($parts, 1));
$result = $array;
if (isset($result[$first])) {
$result[$first] = updateImmutable($result[$first], $rest, $value);
} else {
$result[$first] = updateImmutable([], $rest, $value);
}
return $result;
}
$state = ['user' => ['name' => 'Alice', 'age' => 25]];
$newState = updateImmutable($state, 'user.age', 26);
echo "Original: " . $state['user']['age'] . "\n";
echo "Updated: " . $newState['user']['age'] . "\n";
?>Implement pipe function for left-to-right function composition.
- Method:
pipe(...$fns) - Implementation:
array_reduce - Direction: Left to right
- Use case: Function chaining
<?php
// Pipe function
function pipe(...$fns) {
return function($value) use ($fns) {
$result = $value;
foreach ($fns as $fn) {
$result = $fn($result);
}
return $result;
};
}
function compose(...$fns) {
return function($value) use ($fns) {
$result = $value;
foreach (array_reverse($fns) as $fn) {
$result = $fn($result);
}
return $result;
};
}
$double = fn($x) => $x * 2;
$addTen = fn($x) => $x + 10;
$square = fn($x) => $x * $x;
$process = pipe($double, $addTen, $square);
echo "Pipe: " . $process(5) . "\n"; // (5*2+10)^2 = 400
$process2 = compose($square, $addTen, $double);
echo "Compose: " . $process2(5) . "\n"; // (5*2+10)^2 = 400
?>Implement compose function for right-to-left function composition.
- Method:
compose(...$fns) - Implementation:
array_reducewith reversed order - Direction: Right to left
- Use case: Function composition
<?php
// Compose function
function composeAlt(...$fns) {
return array_reduce(array_reverse($fns), function($carry, $fn) {
return function($x) use ($carry, $fn) {
return $fn($carry($x));
};
}, function($x) { return $x; });
}
function pipeAlt(...$fns) {
return array_reduce($fns, function($carry, $fn) {
return function($x) use ($carry, $fn) {
return $fn($carry($x));
};
}, function($x) { return $x; });
}
$double = fn($x) => $x * 2;
$addTen = fn($x) => $x + 10;
$square = fn($x) => $x * $x;
$composed = composeAlt($double, $addTen, $square);
echo "Composed alt: " . $composed(5) . "\n";
$piped = pipeAlt($double, $addTen, $square);
echo "Piped alt: " . $piped(5) . "\n";
?>Implement memoization to cache function results based on arguments.
- Method:
memoize($fn) - Cache:
array - Limit:
memoizeWithLimit - Multiple args:
memoizeMultiple
<?php
// Memoization
function memoize($fn) {
$cache = [];
return function($arg) use ($fn, &$cache) {
if (!isset($cache[$arg])) {
$cache[$arg] = $fn($arg);
}
return $cache[$arg];
};
}
function memoizeMultiple($fn) {
$cache = [];
return function(...$args) use ($fn, &$cache) {
$key = serialize($args);
if (!isset($cache[$key])) {
$cache[$key] = $fn(...$args);
}
return $cache[$key];
};
}
function memoizeWithLimit($fn, $limit) {
$cache = [];
$keys = [];
return function($arg) use ($fn, &$cache, &$keys, $limit) {
if (!isset($cache[$arg])) {
if (count($keys) >= $limit) {
$oldest = array_shift($keys);
unset($cache[$oldest]);
}
$cache[$arg] = $fn($arg);
$keys[] = $arg;
}
return $cache[$arg];
};
}
// Example: Fibonacci with memoization
$fib = memoize(function($n) use (&$fib) {
if ($n <= 1) return $n;
return $fib($n - 1) + $fib($n - 2);
});
$start = microtime(true);
echo "Fibonacci(35): " . $fib(35) . "\n";
echo "Time: " . (microtime(true) - $start) . "s\n";
$start2 = microtime(true);
echo "Fibonacci(35) again: " . $fib(35) . "\n";
echo "Time: " . (microtime(true) - $start2) . "s\n";
?>Implement once function that ensures a function is called only once.
- Method:
once($fn) - Flag:
$called - Reset:
onceWithReset - Result: Cached result
<?php
// Once function
function once($fn) {
$called = false;
$result = null;
return function(...$args) use ($fn, &$called, &$result) {
if (!$called) {
$called = true;
$result = $fn(...$args);
}
return $result;
};
}
function onceWithReset($fn) {
$called = false;
$result = null;
$reset = function() use (&$called, &$result) {
$called = false;
$result = null;
};
$fnOnce = function(...$args) use ($fn, &$called, &$result) {
if (!$called) {
$called = true;
$result = $fn(...$args);
}
return $result;
};
return [$fnOnce, $reset];
}
$initialize = once(function($value) {
echo "Initialized with $value\n";
return $value * 2;
});
echo "First call: " . $initialize(10) . "\n";
echo "Second call: " . $initialize(20) . "\n";
[$init, $reset] = onceWithReset(function($value) {
echo "Initialized with $value\n";
return $value * 2;
});
echo "First with reset: " . $init(10) . "\n";
$reset();
echo "After reset: " . $init(20) . "\n";
?>Implement debounce with leading edge execution using timers.
- Method:
debounceLeading - State:
$lastCall - Timer:
usleeporsleep - Use case: Rate limiting
<?php
// Debounce with leading edge
function debounceLeading($fn, $delay) {
$lastCall = 0;
$timeout = null;
return function(...$args) use ($fn, $delay, &$lastCall, &$timeout) {
$now = microtime(true);
if ($now - $lastCall >= $delay) {
$lastCall = $now;
return $fn(...$args);
}
if ($timeout === null) {
$timeout = [
'start' => $now,
'args' => $args
];
register_shutdown_function(function() use ($fn, $delay, &$lastCall, &$timeout) {
if ($timeout !== null) {
$elapsed = microtime(true) - $timeout['start'];
$remaining = $delay - $elapsed;
if ($remaining > 0) {
usleep((int)($remaining * 1000000));
}
$lastCall = microtime(true);
$fn(...$timeout['args']);
$timeout = null;
}
});
}
};
}
// Simplified version using pcntl for actual PHP implementation
function debounceLeadingSimple($fn, $delay) {
$lastCall = 0;
return function(...$args) use ($fn, $delay, &$lastCall) {
$now = microtime(true);
if ($now - $lastCall >= $delay) {
$lastCall = $now;
return $fn(...$args);
}
// In a real implementation, you'd use a timer
return null;
};
}
$debounced = debounceLeadingSimple(function($value) {
echo "Processing: $value\n";
}, 2);
echo "Call 1: " . $debounced(1) . "\n";
echo "Call 2: " . $debounced(2) . "\n";
sleep(3);
echo "Call 3: " . $debounced(3) . "\n";
?>Implement throttle with leading edge execution based on time since last call.
- Method:
throttleLeading - State:
$lastCall - Skipped: Track skipped calls
- Trailing:
throttleWithTrailing
<?php
// Throttle with leading edge
function throttleLeading($fn, $delay) {
$lastCall = 0;
return function(...$args) use ($fn, $delay, &$lastCall) {
$now = microtime(true);
if ($now - $lastCall >= $delay) {
$lastCall = $now;
return $fn(...$args);
}
return null;
};
}
function throttleLeadingWithSkipped($fn, $delay) {
$lastCall = 0;
$skipped = 0;
return function(...$args) use ($fn, $delay, &$lastCall, &$skipped) {
$now = microtime(true);
if ($now - $lastCall >= $delay) {
if ($skipped > 0) {
echo "Skipped $skipped calls\n";
$skipped = 0;
}
$lastCall = $now;
return $fn(...$args);
}
$skipped++;
return null;
};
}
function throttleWithTrailing($fn, $delay) {
$lastCall = 0;
$pending = null;
$timer = null;
return function(...$args) use ($fn, $delay, &$lastCall, &$pending, &$timer) {
$now = microtime(true);
if ($now - $lastCall >= $delay) {
$lastCall = $now;
return $fn(...$args);
}
$pending = $args;
if ($timer === null) {
$remaining = $delay - ($now - $lastCall);
if ($remaining > 0) {
usleep((int)($remaining * 1000000));
}
$lastCall = microtime(true);
if ($pending !== null) {
$fn(...$pending);
$pending = null;
}
$timer = null;
}
};
}
$throttled = throttleLeading(function($value) {
echo "Processing: $value\n";
}, 2);
echo "Call 1: " . $throttled(1) . "\n";
echo "Call 2: " . $throttled(2) . "\n";
sleep(3);
echo "Call 3: " . $throttled(3) . "\n";
?>Implement deep equality comparison for nested structures.
- Method:
deepEqual($obj1, $obj2) - Primitive:
=== - Arrays: Recursive compare
- Objects: Compare properties
<?php
// Deep equal
function deepEqual($obj1, $obj2) {
if ($obj1 === $obj2) {
return true;
}
if (gettype($obj1) !== gettype($obj2)) {
return false;
}
if (is_array($obj1) && is_array($obj2)) {
if (count($obj1) !== count($obj2)) {
return false;
}
foreach ($obj1 as $key => $value) {
if (!array_key_exists($key, $obj2)) {
return false;
}
if (!deepEqual($value, $obj2[$key])) {
return false;
}
}
return true;
}
if (is_object($obj1) && is_object($obj2)) {
if (get_class($obj1) !== get_class($obj2)) {
return false;
}
$props1 = get_object_vars($obj1);
$props2 = get_object_vars($obj2);
if (count($props1) !== count($props2)) {
return false;
}
foreach ($props1 as $key => $value) {
if (!property_exists($obj2, $key)) {
return false;
}
if (!deepEqual($value, $obj2->$key)) {
return false;
}
}
return true;
}
return $obj1 == $obj2;
}
$obj1 = (object)['a' => 1, 'b' => ['c' => 2]];
$obj2 = (object)['a' => 1, 'b' => ['c' => 2]];
$obj3 = (object)['a' => 1, 'b' => ['c' => 3]];
echo "obj1 == obj2: " . var_export(deepEqual($obj1, $obj2), true) . "\n";
echo "obj1 == obj3: " . var_export(deepEqual($obj1, $obj3), true) . "\n";
?>Implement observable pattern with subscription and notification.
- Observable:
Observableclass - Subscribe:
subscribe($callback) - Notify:
notify($data) - Stateful:
StatefulObservable
<?php
// Observable pattern
class Observable {
private $subscribers = [];
public function subscribe($callback) {
$id = spl_object_hash($callback);
$this->subscribers[$id] = $callback;
return $id;
}
public function unsubscribe($id) {
unset($this->subscribers[$id]);
}
public function notify($data) {
foreach ($this->subscribers as $callback) {
$callback($data);
}
}
public function clear() {
$this->subscribers = [];
}
}
class StatefulObservable extends Observable {
private $state;
public function __construct($initialState) {
parent::__construct();
$this->state = $initialState;
}
public function setState($newState) {
$this->state = $newState;
$this->notify($newState);
}
public function getState() {
return $this->state;
}
}
$observable = new Observable();
$id1 = $observable->subscribe(function($data) {
echo "Observer1: $data\n";
});
$id2 = $observable->subscribe(function($data) {
echo "Observer2: $data\n";
});
echo "Notifying observers:\n";
$observable->notify("Hello, World!");
$observable->unsubscribe($id1);
echo "After unsubscribing observer1:\n";
$observable->notify("Hello again!");
$stateful = new StatefulObservable(0);
$stateful->subscribe(function($state) {
echo "State changed to: $state\n";
});
echo "Current state: " . $stateful->getState() . "\n";
$stateful->setState(10);
$stateful->setState(20);
?>Implement singleton pattern to ensure only one instance exists.
- Class:
Singletonclass - Instance:
static $instance - Private: Constructor, clone, wakeup
- Closure:
createSingleton
<?php
// Singleton pattern
class Singleton {
private static $instance = null;
private $data = [];
private function __construct() {}
private function __clone() {}
private function __wakeup() {}
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function set($key, $value) {
$this->data[$key] = $value;
}
public function get($key) {
return $this->data[$key] ?? null;
}
}
// Alternative singleton using closure
function createSingleton($init) {
static $instance = null;
return function() use (&$instance, $init) {
if ($instance === null) {
$instance = $init();
}
return $instance;
};
}
$getConfig = createSingleton(function() {
echo "Initializing singleton\n";
return ['name' => 'App', 'version' => 1.0];
});
$config1 = $getConfig();
$config2 = $getConfig();
echo "config1 === config2: " . var_export($config1 === $config2, true) . "\n";
echo "config1 name: " . $config1['name'] . "\n";
$singleton1 = Singleton::getInstance();
$singleton2 = Singleton::getInstance();
echo "singleton1 === singleton2: " . var_export($singleton1 === $singleton2, true) . "\n";
$singleton1->set('key', 'value');
echo "singleton2 get: " . $singleton2->get('key') . "\n";
?>Implement factory pattern for creating objects without specifying concrete classes.
- Interface:
User - Factory:
UserFactory - Create:
create($type, $name) - Specific:
createAdmin,createGuest
<?php
// Factory pattern
interface User {
public function getName(): string;
public function getType(): string;
}
class Admin implements User {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName(): string {
return $this->name;
}
public function getType(): string {
return 'admin';
}
}
class Guest implements User {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName(): string {
return $this->name;
}
public function getType(): string {
return 'guest';
}
}
class RegularUser implements User {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName(): string {
return $this->name;
}
public function getType(): string {
return 'regular';
}
}
class UserFactory {
public static function create($type, $name): User {
switch ($type) {
case 'admin':
return new Admin($name);
case 'guest':
return new Guest($name);
default:
return new RegularUser($name);
}
}
public static function createAdmin($name): Admin {
return new Admin($name);
}
public static function createGuest($name): Guest {
return new Guest($name);
}
public static function createRegular($name): RegularUser {
return new RegularUser($name);
}
}
$user1 = UserFactory::create('admin', 'Alice');
$user2 = UserFactory::create('guest', 'Bob');
$user3 = UserFactory::create('regular', 'Charlie');
echo $user1->getName() . " is " . $user1->getType() . "\n";
echo $user2->getName() . " is " . $user2->getType() . "\n";
echo $user3->getName() . " is " . $user3->getType() . "\n";
?>Implement strategy pattern with interchangeable payment methods.
- Strategy:
PaymentStrategy - Context:
PaymentContext - Execute:
executePayment - Decorator:
DiscountDecorator
<?php
// Strategy pattern
interface PaymentStrategy {
public function pay(float $amount): void;
}
class CreditCardStrategy implements PaymentStrategy {
public function pay(float $amount): void {
echo "Paid $amount with Credit Card\n";
}
}
class PayPalStrategy implements PaymentStrategy {
public function pay(float $amount): void {
echo "Paid $amount with PayPal\n";
}
}
class CryptoStrategy implements PaymentStrategy {
public function pay(float $amount): void {
echo "Paid $amount with Crypto\n";
}
}
class PaymentContext {
private $strategy;
public function __construct(PaymentStrategy $strategy) {
$this->strategy = $strategy;
}
public function setStrategy(PaymentStrategy $strategy): void {
$this->strategy = $strategy;
}
public function executePayment(float $amount): void {
$this->strategy->pay($amount);
}
}
// Usage
$context = new PaymentContext(new CreditCardStrategy());
$context->executePayment(100.0);
$context->setStrategy(new PayPalStrategy());
$context->executePayment(50.0);
$context->setStrategy(new CryptoStrategy());
$context->executePayment(75.0);
// With discount decorator
class DiscountDecorator implements PaymentStrategy {
private $strategy;
private $discount;
public function __construct(PaymentStrategy $strategy, float $discount) {
$this->strategy = $strategy;
$this->discount = $discount;
}
public function pay(float $amount): void {
$discounted = $amount * (1 - $this->discount);
echo "Applied discount of " . ($this->discount * 100) . "%\n";
$this->strategy->pay($discounted);
}
}
$discounted = new DiscountDecorator(new PayPalStrategy(), 0.1);
$discounted->pay(100.0);
?>Implement observer pattern with subject and observer interfaces.
- Subject:
ConcreteSubject - Observer:
ConcreteObserver - Attach:
attach($observer) - Notify:
setState($state)
<?php
// Observer pattern
interface Observer {
public function update($data): void;
}
interface Subject {
public function attach(Observer $observer): void;
public function detach(Observer $observer): void;
public function notify(): void;
}
class ConcreteSubject implements Subject {
private $observers = [];
private $state;
public function attach(Observer $observer): void {
$this->observers[] = $observer;
}
public function detach(Observer $observer): void {
$this->observers = array_filter($this->observers, function($obs) use ($observer) {
return $obs !== $observer;
});
}
public function notify(): void {
foreach ($this->observers as $observer) {
$observer->update($this->state);
}
}
public function setState($state): void {
$this->state = $state;
$this->notify();
}
public function getState() {
return $this->state;
}
}
class ConcreteObserver implements Observer {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function update($data): void {
echo "Observer {$this->name} received: $data\n";
}
}
class DerivedObserver implements Observer {
private $subject;
private $transform;
public function __construct(Subject $subject, callable $transform) {
$this->subject = $subject;
$this->transform = $transform;
}
public function update($data): void {
$transformed = ($this->transform)($data);
echo "Derived observer: $transformed\n";
}
}
// Usage
$subject = new ConcreteSubject();
$observer1 = new ConcreteObserver('1');
$observer2 = new ConcreteObserver('2');
$observer3 = new DerivedObserver($subject, function($data) {
return strtoupper($data);
});
$subject->attach($observer1);
$subject->attach($observer2);
$subject->attach($observer3);
echo "Setting state:\n";
$subject->setState("Hello, World!");
$subject->setState("Another update");
$subject->detach($observer1);
echo "After detaching observer1:\n";
$subject->setState("Final state");
?>Implement decorator pattern for adding features to coffee.
- Component:
BasicCoffee - Decorator:
CoffeeDecorator - Additions:
MilkDecorator,SugarDecorator - Chaining: Nested decorators
<?php
// Decorator pattern
interface Coffee {
public function getCost(): float;
public function getDescription(): string;
}
class BasicCoffee implements Coffee {
public function getCost(): float {
return 5.0;
}
public function getDescription(): string {
return "Coffee";
}
}
abstract class CoffeeDecorator implements Coffee {
protected $coffee;
public function __construct(Coffee $coffee) {
$this->coffee = $coffee;
}
}
class MilkDecorator extends CoffeeDecorator {
public function getCost(): float {
return $this->coffee->getCost() + 2.0;
}
public function getDescription(): string {
return $this->coffee->getDescription() . ", Milk";
}
}
class SugarDecorator extends CoffeeDecorator {
public function getCost(): float {
return $this->coffee->getCost() + 1.0;
}
public function getDescription(): string {
return $this->coffee->getDescription() . ", Sugar";
}
}
class CaramelDecorator extends CoffeeDecorator {
public function getCost(): float {
return $this->coffee->getCost() + 2.5;
}
public function getDescription(): string {
return $this->coffee->getDescription() . ", Caramel";
}
}
class WhippedCreamDecorator extends CoffeeDecorator {
public function getCost(): float {
return $this->coffee->getCost() + 1.5;
}
public function getDescription(): string {
return $this->coffee->getDescription() . ", Whipped Cream";
}
}
// Usage
$coffee = new BasicCoffee();
echo $coffee->getDescription() . " ($" . $coffee->getCost() . ")\n";
$withMilk = new MilkDecorator($coffee);
echo $withMilk->getDescription() . " ($" . $withMilk->getCost() . ")\n";
$withSugar = new SugarDecorator($coffee);
echo $withSugar->getDescription() . " ($" . $withSugar->getCost() . ")\n";
$withMilkSugar = new SugarDecorator(new MilkDecorator($coffee));
echo $withMilkSugar->getDescription() . " ($" . $withMilkSugar->getCost() . ")\n";
$fullyDecorated = new CaramelDecorator(
new WhippedCreamDecorator(
new SugarDecorator(
new MilkDecorator($coffee)
)
)
);
echo $fullyDecorated->getDescription() . " ($" . $fullyDecorated->getCost() . ")\n";
?>Implement command pattern with execute, undo, and redo operations.
- Command:
AddCommand,SubtractCommand - History:
CommandHistory - Macro:
MacroCommand - Operations:
execute,undo,redo
<?php
// Command pattern
interface Command {
public function execute(): void;
public function undo(): void;
public function redo(): void;
}
class AddCommand implements Command {
private $receiver;
private $value;
public function __construct(&$receiver, int $value) {
$this->receiver = &$receiver;
$this->value = $value;
}
public function execute(): void {
$this->receiver += $this->value;
}
public function undo(): void {
$this->receiver -= $this->value;
}
public function redo(): void {
$this->execute();
}
}
class SubtractCommand implements Command {
private $receiver;
private $value;
public function __construct(&$receiver, int $value) {
$this->receiver = &$receiver;
$this->value = $value;
}
public function execute(): void {
$this->receiver -= $this->value;
}
public function undo(): void {
$this->receiver += $this->value;
}
public function redo(): void {
$this->execute();
}
}
class MacroCommand implements Command {
private $commands = [];
public function __construct(array $commands) {
$this->commands = $commands;
}
public function execute(): void {
foreach ($this->commands as $command) {
$command->execute();
}
}
public function undo(): void {
foreach (array_reverse($this->commands) as $command) {
$command->undo();
}
}
public function redo(): void {
$this->execute();
}
}
class CommandHistory {
private $history = [];
private $current = 0;
public function execute(Command $command): void {
$command->execute();
$this->history = array_slice($this->history, 0, $this->current);
$this->history[] = $command;
$this->current++;
}
public function undo(): bool {
if ($this->current > 0) {
$this->current--;
$this->history[$this->current]->undo();
return true;
}
return false;
}
public function redo(): bool {
if ($this->current < count($this->history)) {
$this->history[$this->current]->redo();
$this->current++;
return true;
}
return false;
}
}
// Usage
$counter = 0;
$history = new CommandHistory();
$add5 = new AddCommand($counter, 5);
$sub3 = new SubtractCommand($counter, 3);
echo "Initial: $counter\n";
$history->execute($add5);
echo "After add: $counter\n";
$history->execute($sub3);
echo "After sub: $counter\n";
$history->undo();
echo "After undo: $counter\n";
$history->redo();
echo "After redo: $counter\n";
$macro = new MacroCommand([$add5, $add5, $sub3]);
$history->execute($macro);
echo "After macro: $counter\n";
?>Implement memento pattern for state capture and restoration.
- Originator:
Originator - Memento:
Memento - Caretaker:
Caretaker - Undo/Redo:
undo,redo
<?php
// Memento pattern
class Memento {
private $state;
public function __construct($state) {
$this->state = $state;
}
public function getState() {
return $this->state;
}
}
class Originator {
private $state;
public function __construct($state) {
$this->state = $state;
}
public function save(): Memento {
return new Memento($this->state);
}
public function restore(Memento $memento): void {
$this->state = $memento->getState();
}
public function setState($state): void {
$this->state = $state;
}
public function getState() {
return $this->state;
}
}
class Caretaker {
private $mementos = [];
private $current = 0;
public function save(Memento $memento): void {
$this->mementos = array_slice($this->mementos, 0, $this->current);
$this->mementos[] = $memento;
$this->current++;
}
public function undo(): ?Memento {
if ($this->current > 0) {
$this->current--;
return $this->mementos[$this->current];
}
return null;
}
public function redo(): ?Memento {
if ($this->current < count($this->mementos)) {
$memento = $this->mementos[$this->current];
$this->current++;
return $memento;
}
return null;
}
}
// Usage
$originator = new Originator(['value' => 0]);
$caretaker = new Caretaker();
$caretaker->save($originator->save());
$originator->setState(['value' => 1]);
$caretaker->save($originator->save());
$originator->setState(['value' => 2]);
$caretaker->save($originator->save());
$originator->setState(['value' => 3]);
echo "Current: " . $originator->getState()['value'] . "\n";
$memento = $caretaker->undo();
if ($memento) {
$originator->restore($memento);
echo "After undo: " . $originator->getState()['value'] . "\n";
}
$memento = $caretaker->redo();
if ($memento) {
$originator->restore($memento);
echo "After redo: " . $originator->getState()['value'] . "\n";
}
?>Implement mediator pattern for centralized communication between colleagues.
- Mediator:
ConcreteMediator - Colleague:
User - Send:
send($message) - Register:
register($colleague)
<?php
// Mediator pattern
interface Mediator {
public function send(string $message, Colleague $sender): void;
public function register(Colleague $colleague): void;
}
abstract class Colleague {
protected $mediator;
protected $name;
public function __construct(string $name, Mediator $mediator) {
$this->name = $name;
$this->mediator = $mediator;
}
public function send(string $message): void {
$this->mediator->send($message, $this);
}
public abstract function receive(string $message): void;
}
class ConcreteMediator implements Mediator {
private $colleagues = [];
public function register(Colleague $colleague): void {
$this->colleagues[] = $colleague;
}
public function send(string $message, Colleague $sender): void {
foreach ($this->colleagues as $colleague) {
if ($colleague !== $sender) {
$colleague->receive($message);
}
}
}
}
class User extends Colleague {
public function receive(string $message): void {
echo "{$this->name} received: $message\n";
}
}
class StatefulUser extends Colleague {
private $state;
public function __construct(string $name, Mediator $mediator, $state) {
parent::__construct($name, $mediator);
$this->state = $state;
}
public function receive(string $message): void {
echo "{$this->name} (state {$this->state}) received: $message\n";
}
public function setState($state): void {
$this->state = $state;
}
}
// Usage
$mediator = new ConcreteMediator();
$alice = new User('Alice', $mediator);
$bob = new User('Bob', $mediator);
$charlie = new User('Charlie', $mediator);
$mediator->register($alice);
$mediator->register($bob);
$mediator->register($charlie);
echo "Sending messages:\n";
$alice->send("Hello everyone!");
$bob->send("Meeting at 3pm");
$mediator2 = new ConcreteMediator();
$alice2 = new StatefulUser('Alice', $mediator2, 0);
$bob2 = new StatefulUser('Bob', $mediator2, 1);
$mediator2->register($alice2);
$mediator2->register($bob2);
$alice2->send("Custom message for stateful colleagues");
?>Implement chain of responsibility with linked handlers.
- Handler:
Handlerabstract class - Chain:
setNext($handler) - Processing:
handle($request) - Concrete:
AuthHandler,LoggerHandler
<?php
// Chain of Responsibility
abstract class Handler {
protected $next = null;
public function setNext(Handler $handler): Handler {
$this->next = $handler;
return $handler;
}
public abstract function handle($request): bool;
}
class AuthHandler extends Handler {
public function handle($request): bool {
if (isset($request['token'])) {
echo "Authentication passed\n";
if ($this->next !== null) {
return $this->next->handle($request);
}
return true;
}
echo "Authentication failed\n";
return false;
}
}
class LoggerHandler extends Handler {
public function handle($request): bool {
$url = $request['url'] ?? 'unknown';
echo "Logging request: $url\n";
if ($this->next !== null) {
return $this->next->handle($request);
}
return true;
}
}
class ValidationHandler extends Handler {
public function handle($request): bool {
if (isset($request['data'])) {
echo "Validation passed\n";
if ($this->next !== null) {
return $this->next->handle($request);
}
return true;
}
echo "Validation failed\n";
return false;
}
}
class RateLimitHandler extends Handler {
private $lastCall = 0;
private $limit = 5; // seconds
public function handle($request): bool {
$now = microtime(true);
if ($now - $this->lastCall >= $this->limit) {
$this->lastCall = $now;
echo "Rate limit passed\n";
if ($this->next !== null) {
return $this->next->handle($request);
}
return true;
}
echo "Rate limit exceeded\n";
return false;
}
}
// Usage
$auth = new AuthHandler();
$logger = new LoggerHandler();
$validator = new ValidationHandler();
$rateLimiter = new RateLimitHandler();
$auth->setNext($logger)->setNext($validator)->setNext($rateLimiter);
$request = ['token' => 'valid', 'url' => '/api', 'data' => 'payload'];
echo "Processing valid request:\n";
$auth->handle($request);
$request2 = ['url' => '/public'];
echo "Processing invalid request:\n";
$auth->handle($request2);
?>Implement state pattern with context and state transitions.
- State:
Stateinterface - Context:
Context - Transitions:
handle($context) - Data:
StatefulContext
<?php
// State pattern
interface State {
public function handle(Context $context): void;
}
class ReadyState implements State {
public function handle(Context $context): void {
echo "Ready: Waiting for input\n";
$context->setState(new ProcessingState());
}
}
class ProcessingState implements State {
public function handle(Context $context): void {
echo "Processing: Working on task\n";
$context->setState(new CompletedState());
}
}
class CompletedState implements State {
public function handle(Context $context): void {
echo "Completed: Task finished\n";
$context->setState(new ReadyState());
}
}
class ErrorState implements State {
public function handle(Context $context): void {
echo "Error: Something went wrong\n";
$context->setState(new ReadyState());
}
}
class Context {
private $state;
private $data;
public function __construct(State $state) {
$this->state = $state;
$this->data = [];
}
public function setState(State $state): void {
$this->state = $state;
}
public function request(): void {
$this->state->handle($this);
}
public function setData($key, $value): void {
$this->data[$key] = $value;
}
public function getData($key) {
return $this->data[$key] ?? null;
}
}
class StatefulContext extends Context {
public function request(): void {
$this->state->handle($this);
$this->setData('last_state', get_class($this->state));
}
}
// Usage
$context = new Context(new ReadyState());
for ($i = 0; $i < 5; $i++) {
echo "Step " . ($i + 1) . ": ";
$context->request();
}
echo "\nWith data:\n";
$context2 = new StatefulContext(new ReadyState());
for ($i = 0; $i < 5; $i++) {
$context2->setData('step', $i + 1);
$context2->request();
echo "Data: " . json_encode($context2->getData('last_state')) . "\n";
}
?>Implement proxy pattern for access control and lazy initialization.
- Subject:
RealSubject - Proxy:
Proxy - Logging:
LoggingProxy - Auth:
AuthProxy
<?php
// Proxy pattern
interface Subject {
public function request(): string;
}
class RealSubject implements Subject {
public function request(): string {
return "RealSubject: Handling request";
}
}
class Proxy implements Subject {
private $realSubject = null;
public function request(): string {
if ($this->realSubject === null) {
echo "Proxy: Creating real subject\n";
$this->realSubject = new RealSubject();
}
echo "Proxy: Using cached real subject\n";
return $this->realSubject->request();
}
}
class LoggingProxy implements Subject {
private $subject;
public function __construct(Subject $subject) {
$this->subject = $subject;
}
public function request(): string {
echo "Logging: Request started\n";
$result = $this->subject->request();
echo "Logging: Request completed\n";
return $result;
}
}
class AuthProxy implements Subject {
private $subject;
private $user;
public function __construct(Subject $subject, $user) {
$this->subject = $subject;
$this->user = $user;
}
public function request(): string {
if ($this->authenticate()) {
echo "Auth: Access granted\n";
return $this->subject->request();
}
echo "Auth: Access denied\n";
return "Unauthorized";
}
private function authenticate(): bool {
// Simple authentication check
return $this->user === 'admin';
}
}
// Usage
$proxy = new Proxy();
echo $proxy->request() . "\n";
echo $proxy->request() . "\n";
$real = new RealSubject();
$loggingProxy = new LoggingProxy($real);
echo $loggingProxy->request() . "\n";
$authProxy = new AuthProxy($real, 'admin');
echo $authProxy->request() . "\n";
$authProxy2 = new AuthProxy($real, 'guest');
echo $authProxy2->request() . "\n";
?>Implement flyweight pattern for sharing objects to save memory.
- Flyweight:
Flyweight - Factory:
FlyweightFactory - Get:
getFlyweight($sharedState) - Operation:
operation($uniqueState)
<?php
// Flyweight pattern
class Flyweight {
private $sharedState;
public function __construct(string $sharedState) {
$this->sharedState = $sharedState;
}
public function operation(string $uniqueState): string {
return "Shared: {$this->sharedState}, Unique: $uniqueState";
}
}
class FlyweightFactory {
private $flyweights = [];
public function getFlyweight(string $sharedState): Flyweight {
if (!isset($this->flyweights[$sharedState])) {
$this->flyweights[$sharedState] = new Flyweight($sharedState);
}
return $this->flyweights[$sharedState];
}
public function getCount(): int {
return count($this->flyweights);
}
}
// Usage
$factory = new FlyweightFactory();
$fw1 = $factory->getFlyweight('state1');
$fw2 = $factory->getFlyweight('state1');
$fw3 = $factory->getFlyweight('state2');
echo "fw1 and fw2 are same: " . var_export($fw1 === $fw2, true) . "\n";
echo "fw1 and fw3 are same: " . var_export($fw1 === $fw3, true) . "\n";
echo $fw1->operation('unique1') . "\n";
echo $fw2->operation('unique2') . "\n";
echo $fw3->operation('unique3') . "\n";
echo "Number of flyweights: " . $factory->getCount() . "\n";
?>Implement bridge pattern for separating abstraction from implementation.
- Implementation:
ConcreteImplementationA - Abstraction:
ExtendedAbstraction - Alternative:
AlternativeAbstraction - Operation:
operation()
<?php
// Bridge pattern
interface Implementation {
public function operation(): string;
}
class ConcreteImplementationA implements Implementation {
public function operation(): string {
return "ConcreteImplementationA: Operation";
}
}
class ConcreteImplementationB implements Implementation {
public function operation(): string {
return "ConcreteImplementationB: Operation";
}
}
abstract class Abstraction {
protected $implementation;
public function __construct(Implementation $implementation) {
$this->implementation = $implementation;
}
abstract public function operation(): string;
}
class ExtendedAbstraction extends Abstraction {
public function operation(): string {
return "ExtendedAbstraction: " . $this->implementation->operation();
}
}
class AlternativeAbstraction extends Abstraction {
public function operation(): string {
return "AlternativeAbstraction: " . $this->implementation->operation();
}
}
// Usage
$implA = new ConcreteImplementationA();
$implB = new ConcreteImplementationB();
$abstraction1 = new ExtendedAbstraction($implA);
$abstraction2 = new ExtendedAbstraction($implB);
$abstraction3 = new AlternativeAbstraction($implA);
echo $abstraction1->operation() . "\n";
echo $abstraction2->operation() . "\n";
echo $abstraction3->operation() . "\n";
?>Implement adapter pattern for converting interfaces.
- Target:
Target - Adaptee:
Adaptee - Adapter:
Adapter - Logging:
LoggingAdapter
<?php
// Adapter pattern
class Target {
public function request(): string {
return "Target: Request";
}
}
class Adaptee {
public function specificRequest(): string {
return "Adaptee: Specific Request";
}
}
class Adapter extends Target {
private $adaptee;
public function __construct(Adaptee $adaptee) {
$this->adaptee = $adaptee;
}
public function request(): string {
return $this->adaptee->specificRequest();
}
}
class LoggingAdapter extends Adapter {
public function request(): string {
echo "Adapter: Logging request\n";
return parent::request();
}
}
// Usage
$target = new Target();
$adaptee = new Adaptee();
$adapter = new Adapter($adaptee);
echo $target->request() . "\n";
echo $adapter->request() . "\n";
$loggingAdapter = new LoggingAdapter($adaptee);
echo $loggingAdapter->request() . "\n";
?>Implement facade pattern for simplifying complex subsystems.
- Subsystems:
SubsystemA,SubsystemB - Facade:
Facade - Operations:
simpleOperation,complexOperation - Interface: Simplified API
<?php
// Facade pattern
class SubsystemA {
public function operationA(): string {
return "SubsystemA: Operation";
}
}
class SubsystemB {
public function operationB(): string {
return "SubsystemB: Operation";
}
}
class SubsystemC {
public function operationC(): string {
return "SubsystemC: Operation";
}
}
class Facade {
private $subsystemA;
private $subsystemB;
private $subsystemC;
public function __construct() {
$this->subsystemA = new SubsystemA();
$this->subsystemB = new SubsystemB();
$this->subsystemC = new SubsystemC();
}
public function simpleOperation(): string {
return $this->subsystemA->operationA();
}
public function complexOperation(): string {
return implode("
", [
$this->subsystemA->operationA(),
$this->subsystemB->operationB(),
$this->subsystemC->operationC()
]);
}
}
// Usage
$facade = new Facade();
echo "Simple operation:
" . $facade->simpleOperation() . "
";
echo "Complex operation:
" . $facade->complexOperation() . "
";
?>Implement composite pattern for tree structures.
- Component:
Componentinterface - Leaf:
Leaf - Composite:
Composite - Operation:
operation()
<?php
// Composite pattern
interface Component {
public function operation(): string;
public function add(Component $component): void;
public function remove(Component $component): void;
public function getChildren(): array;
}
class Leaf implements Component {
private $name;
public function __construct(string $name) {
$this->name = $name;
}
public function operation(): string {
return "Leaf {$this->name}: Operation";
}
public function add(Component $component): void {
throw new Exception("Cannot add to leaf");
}
public function remove(Component $component): void {
throw new Exception("Cannot remove from leaf");
}
public function getChildren(): array {
return [];
}
}
class Composite implements Component {
private $name;
private $children = [];
public function __construct(string $name) {
$this->name = $name;
}
public function operation(): string {
$result = "Composite {$this->name}: Operation
";
foreach ($this->children as $child) {
$result .= $child->operation() . "
";
}
return $result;
}
public function add(Component $component): void {
$this->children[] = $component;
}
public function remove(Component $component): void {
$this->children = array_filter($this->children, function($child) use ($component) {
return $child !== $component;
});
}
public function getChildren(): array {
return $this->children;
}
public function countLeaves(): int {
$count = 0;
foreach ($this->children as $child) {
if ($child instanceof Leaf) {
$count++;
} else {
$count += $child->countLeaves();
}
}
return $count;
}
}
// Usage
$leaf1 = new Leaf('A');
$leaf2 = new Leaf('B');
$leaf3 = new Leaf('C');
$leaf4 = new Leaf('D');
$composite1 = new Composite('Comp1');
$composite1->add($leaf1);
$composite1->add($leaf2);
$composite2 = new Composite('Comp2');
$composite2->add($leaf3);
$composite2->add($composite1);
$root = new Composite('Root');
$root->add($leaf4);
$root->add($composite2);
echo $root->operation();
echo "Number of leaves: " . $root->countLeaves() . "
";
?>Implement visitor pattern for adding operations to objects.
- Visitor:
Visitorinterface - Element:
ElementA,ElementB - Accept:
accept($visitor) - Counting:
CountingVisitor
<?php
// Visitor pattern
interface Element {
public function accept(Visitor $visitor): string;
}
class ElementA implements Element {
private $data;
public function __construct(string $data) {
$this->data = $data;
}
public function accept(Visitor $visitor): string {
return $visitor->visitA($this);
}
public function getData(): string {
return $this->data;
}
}
class ElementB implements Element {
private $data;
public function __construct(string $data) {
$this->data = $data;
}
public function accept(Visitor $visitor): string {
return $visitor->visitB($this);
}
public function getData(): string {
return $this->data;
}
}
interface Visitor {
public function visitA(ElementA $element): string;
public function visitB(ElementB $element): string;
}
class ConcreteVisitor implements Visitor {
public function visitA(ElementA $element): string {
return "Visiting ElementA: " . $element->getData();
}
public function visitB(ElementB $element): string {
return "Visiting ElementB: " . $element->getData();
}
}
class CountingVisitor implements Visitor {
private $countA = 0;
private $countB = 0;
public function visitA(ElementA $element): string {
$this->countA++;
return "Visiting ElementA (" . $this->countA . "): " . $element->getData();
}
public function visitB(ElementB $element): string {
$this->countB++;
return "Visiting ElementB (" . $this->countB . "): " . $element->getData();
}
public function getCounts(): array {
return ['A' => $this->countA, 'B' => $this->countB];
}
}
class ExtendedVisitor implements Visitor {
public function visitA(ElementA $element): string {
return "Extended: " . $element->getData() . " (A)";
}
public function visitB(ElementB $element): string {
return "Extended: " . $element->getData() . " (B)";
}
}
// Usage
$elements = [
new ElementA('Hello'),
new ElementB('World'),
new ElementA('OCaml'),
new ElementB('Visitor')
];
$visitor = new ConcreteVisitor();
$countingVisitor = new CountingVisitor();
$extendedVisitor = new ExtendedVisitor();
echo "Using standard visitor:
";
foreach ($elements as $element) {
echo $element->accept($visitor) . "
";
}
echo "
Using counting visitor:
";
foreach ($elements as $element) {
echo $element->accept($countingVisitor) . "
";
}
print_r($countingVisitor->getCounts());
echo "
Using extended visitor:
";
foreach ($elements as $element) {
echo $element->accept($extendedVisitor) . "
";
}
?>Implement iterator pattern for sequential access.
- Iterator:
Iteratorclass - Reverse:
ReverseIterator - Filter:
FilteredIterator - Skip:
SkipIterator
<?php
// Iterator pattern
class Iterator implements \Iterator {
private $collection;
private $position = 0;
public function __construct($collection) {
$this->collection = $collection;
}
public function current() {
return $this->collection[$this->position] ?? null;
}
public function key() {
return $this->position;
}
public function next() {
$this->position++;
}
public function rewind() {
$this->position = 0;
}
public function valid() {
return isset($this->collection[$this->position]);
}
}
class ReverseIterator implements \Iterator {
private $collection;
private $position;
public function __construct($collection) {
$this->collection = $collection;
$this->position = count($collection) - 1;
}
public function current() {
return $this->collection[$this->position] ?? null;
}
public function key() {
return $this->position;
}
public function next() {
$this->position--;
}
public function rewind() {
$this->position = count($this->collection) - 1;
}
public function valid() {
return isset($this->collection[$this->position]);
}
}
class FilteredIterator extends Iterator {
private $predicate;
public function __construct($collection, callable $predicate) {
parent::__construct(array_filter($collection, $predicate));
$this->predicate = $predicate;
}
}
class SkipIterator extends Iterator {
public function __construct($collection, $n) {
parent::__construct(array_slice($collection, $n));
}
}
class Collection implements \IteratorAggregate {
private $items;
public function __construct($items) {
$this->items = $items;
}
public function getIterator() {
return new Iterator($this->items);
}
public function getReverseIterator() {
return new ReverseIterator($this->items);
}
}
// Usage
$collection = ['A', 'B', 'C', 'D', 'E'];
$iterator = new Iterator($collection);
echo "Forward iteration:
";
foreach ($iterator as $item) {
echo $item . " ";
}
echo "
";
$reverseIterator = new ReverseIterator($collection);
echo "Reverse iteration:
";
foreach ($reverseIterator as $item) {
echo $item . " ";
}
echo "
";
$filteredIterator = new FilteredIterator($collection, function($item) {
return strlen($item) <= 1;
});
echo "Filtered iteration:
";
foreach ($filteredIterator as $item) {
echo $item . " ";
}
echo "
";
?>Implement template method with customizable steps.
- Template:
Templateabstract class - Method:
templateMethod() - Default:
DefaultTemplate - Logging:
LoggingTemplate
<?php
// Template Method pattern
abstract class Template {
public final function templateMethod(): void {
echo $this->step1() . "
";
echo $this->step2() . "
";
echo $this->step3() . "
";
}
abstract protected function step1(): string;
abstract protected function step2(): string;
abstract protected function step3(): string;
}
class DefaultTemplate extends Template {
protected function step1(): string {
return "Step 1";
}
protected function step2(): string {
return "Step 2";
}
protected function step3(): string {
return "Step 3";
}
}
class LoggingTemplate extends Template {
private $template;
public function __construct(Template $template) {
$this->template = $template;
}
protected function step1(): string {
$result = $this->template->step1();
echo "Logging: $result
";
return $result;
}
protected function step2(): string {
$result = $this->template->step2();
echo "Logging: $result
";
return $result;
}
protected function step3(): string {
$result = $this->template->step3();
echo "Logging: $result
";
return $result;
}
}
class DataProcessingTemplate extends Template {
private $data;
public function __construct(string $data) {
$this->data = $data;
}
protected function step1(): string {
return "Processing data: {$this->data} - Step 1";
}
protected function step2(): string {
return "Processing data: {$this->data} - Step 2";
}
protected function step3(): string {
return "Processing data: {$this->data} - Step 3";
}
}
// Usage
echo "Using default template:
";
$default = new DefaultTemplate();
$default->templateMethod();
echo "
Using logging template:
";
$logging = new LoggingTemplate($default);
$logging->templateMethod();
echo "
Using data processing template:
";
$dataTemplate = new DataProcessingTemplate('example');
$dataTemplate->templateMethod();
?>Implement builder pattern for constructing complex objects.
- Builder:
ConcreteBuilder - Director:
Director - Product:
Product - Build:
buildMinimal,buildFull
<?php
// Builder pattern
class Product {
private $parts = [];
public function addPart(string $part): void {
$this->parts[] = $part;
}
public function listParts(): void {
echo implode(', ', $this->parts) . "
";
}
public function getParts(): array {
return $this->parts;
}
}
interface Builder {
public function reset(): void;
public function buildStepA(): void;
public function buildStepB(): void;
public function buildStepC(): void;
public function getResult(): Product;
}
class ConcreteBuilder implements Builder {
private $product;
public function __construct() {
$this->reset();
}
public function reset(): void {
$this->product = new Product();
}
public function buildStepA(): void {
$this->product->addPart('Part A');
}
public function buildStepB(): void {
$this->product->addPart('Part B');
}
public function buildStepC(): void {
$this->product->addPart('Part C');
}
public function getResult(): Product {
$result = $this->product;
$this->reset();
return $result;
}
}
class Director {
private $builder;
public function __construct(Builder $builder) {
$this->builder = $builder;
}
public function buildMinimal(): void {
$this->builder->buildStepA();
}
public function buildFull(): void {
$this->builder->buildStepA();
$this->builder->buildStepB();
$this->builder->buildStepC();
}
public function buildCustom(array $steps): void {
$this->builder->reset();
foreach ($steps as $step) {
switch ($step) {
case 'A':
$this->builder->buildStepA();
break;
case 'B':
$this->builder->buildStepB();
break;
case 'C':
$this->builder->buildStepC();
break;
}
}
}
}
// Usage
$builder = new ConcreteBuilder();
$director = new Director($builder);
echo "Minimal product:
";
$director->buildMinimal();
$builder->getResult()->listParts();
echo "Full product:
";
$director->buildFull();
$builder->getResult()->listParts();
echo "Custom product:
";
$builder->buildStepC();
$builder->buildStepA();
$builder->getResult()->listParts();
echo "Director custom:
";
$director->buildCustom(['C', 'A', 'B']);
$builder->getResult()->listParts();
?>Implement prototype pattern for cloning objects.
- Prototype:
Prototype - Clone:
clone() - Deep clone:
deepClone() - Mutable:
MutablePrototype
<?php
// Prototype pattern
class Prototype {
public $data;
public function __construct($data) {
$this->data = $data;
}
public function clone(): Prototype {
return new Prototype($this->data);
}
public function deepClone(): Prototype {
return new Prototype($this->deepCopy($this->data));
}
private function deepCopy($value) {
if (is_array($value)) {
$result = [];
foreach ($value as $key => $item) {
$result[$key] = $this->deepCopy($item);
}
return $result;
}
if (is_object($value)) {
return clone $value;
}
return $value;
}
}
class MutablePrototype {
private $data;
public function __construct($data) {
$this->data = $data;
}
public function clone(): MutablePrototype {
return new MutablePrototype($this->data);
}
public function deepClone(): MutablePrototype {
return new MutablePrototype($this->deepCopy($this->data));
}
private function deepCopy($value) {
if (is_array($value)) {
$result = [];
foreach ($value as $key => $item) {
$result[$key] = $this->deepCopy($item);
}
return $result;
}
if (is_object($value)) {
return clone $value;
}
return $value;
}
public function setData($data): void {
$this->data = $data;
}
public function getData() {
return $this->data;
}
}
// Usage
$original = new Prototype(['name' => 'Original', 'value' => 42]);
$copy = $original->clone();
$deepCopy = $original->deepClone();
echo "Original: " . json_encode($original->data) . "
";
echo "Copy: " . json_encode($copy->data) . "
";
echo "Deep copy: " . json_encode($deepCopy->data) . "
";
$mutable = new MutablePrototype([1, 2, 3]);
echo "Original data: " . implode(', ', $mutable->getData()) . "
";
$mutable->setData([4, 5, 6]);
echo "Modified data: " . implode(', ', $mutable->getData()) . "
";
$clonedMutable = $mutable->clone();
echo "Clone data: " . implode(', ', $clonedMutable->getData()) . "
";
?>