Background Workers & Queues (`Core\Task`)
Performance FirstTo keep your API responses under a few milliseconds (`Performance First`), never perform heavy tasks synchronously inside request routes (like sending massive emails, resizing images, or processing CSV files). `Core\Task` automatically dispatches them to background worker processes without blocking API throughput.
How `Task::dispatch()` Works Under the Hood
`Core\Task` dynamically detects your deployment environment:
- Distributed Redis Mode (Default in Docker Prod): If Redis (`6379`) is active in `.env`, the task payload (`json`) is pushed into the `lilaphp:jobs` queue (`Redis::lPush`). Background CLI workers consume it asynchronously.
- Standalone Fallback Mode (`proc_open` / detached process): If Redis is disabled or unavailable, `Task::dispatch()` executes a detached OS background process, instantly releasing your HTTP worker.
1. Dispatching a Task from an API Route
use Core\Task;
use Core\Response;
Task::dispatch('send_invoice_email', [
'user_id' => 123,
'invoice_id' => 'INV-2026-8891',
'amount' => 149.99
]);
Response::json(['status' => 'order_placed', 'invoice_id' => 'INV-2026-8891']);
2. Creating the Job Processor (`app/jobs/*.php`)
When a job is processed, `Core\Task` automatically includes your PHP script from the `app/jobs/` folder matching the job name (e.g., `app/jobs/send_invoice_email.php`). Inside the script, `$jobName` and `$payload` are injected into scope:
<?php
use Core\Logger;
$userId = $payload['user_id'] ?? 0;
$amount = $payload['amount'] ?? 0.0;
Logger::info("Processing invoice job for User #{$userId} (${amount})...");
return true;
3. Running the Worker Process (`php cli.php task:work`)
In production or high-concurrency environments, run one or more worker daemons using our `cli.php` entry point:
# Start continuous worker daemon consuming Redis job queue
php cli.php task:work
# Run worker inside Docker container
php cli.php docker exec-php
php cli.php task:work
Anti-Malware File Upload (`Core\Upload`)
Security Shield
Handling user file uploads securely is one of the most critical parts of any web API. Core\Upload provides automated multi-layer security checks to protect your application from malicious uploads, remote code execution (RCE), MIME spoofing, and double-extension exploits.
🔍 Binary MIME Inspection
Uses PHP's finfo_file(FILEINFO_MIME_TYPE) to verify real file magic bytes, rejecting client-provided extension spoofing.
🛡️ Embedded Script Scanner
Scans initial byte chunks for embedded <?php, <?=, and <script payloads hiding inside images or PDFs.
🎲 Cryptographic Random Filenames
Generates 32-character hexadecimal filenames via bin2hex(random_bytes(16)) to prevent directory traversal or file overwrites.
📏 Strict File Size Enforcement
Enforces custom byte boundaries per route (defaults to 10 MB) before processing or moving files.
Handling File Uploads in API Routes
use Core\Request;
use Core\Response;
use Core\Upload;
Request::POST(function() {
if (!isset($_FILES['avatar'])) {
Response::error('No avatar file provided in upload', 422);
}
// 1. Process and save with allowed MIME whitelist (images only)
$savedFilename = Upload::save($_FILES['avatar'], null, [
'image/jpeg' => 'jpg',
'image/png' => 'png',
'image/webp' => 'webp'
], maxSizeMax: 5 * 1024 * 1024); // 5 MB limit
if (!$savedFilename) {
Response::error('Invalid or malicious file detected', 400);
}
// 2. Return public URL or filename
Response::json([
'status' => 'success',
'filename' => $savedFilename,
'url' => '/uploads/' . $savedFilename
], 201);
});
Deleting Uploaded Files
use Core\Upload;
$deleted = Upload::delete('e9f8a1b2c3d4e5f678901234567890ab.webp');
Real-Time WebSockets & Redis Pub/Sub (`Core\Ws`)
Real-time EngineLilaPHP includes a high-performance **Socket.IO style real-time engine** powered by **Workerman (`workerman/workerman`)** and **Redis Pub/Sub**. Your PHP-FPM API routes (`POST /api/items`) can broadcast messages directly to connected frontend browsers in `< 1ms` without keeping heavy FPM worker connections open!
1. Broadcasting from PHP-FPM API Routes (`Core\Ws::publish`)
use Core\Ws;
use Core\Response;
Ws::publish('item_created', [
'id' => 105,
'name' => 'Mechanical Keyboard',
'price' => 129.99
], 'products_room');
Response::json(['status' => 'success', 'message' => 'Item created and broadcasted live']);
2. Frontend Client Wrapper (`public/js/ws.js`)
// Join a room
ws.join('products_room', { password: 'room_password_if_needed' });
// Listen for live events broadcasted by Core\Ws::publish or clients
ws.on('item_created', (data, room) => {
console.log(`Live notification in room [${room}]:`, data);
});
// Emit event to others in the room (excludes sender socket)
ws.emit('chat_message', { text: 'Hello others!' }, 'products_room');
// Emit event to ALL clients in the room (including the sender socket)
ws.broadcastAll('chat_message', { text: 'Hello everyone including me!' }, 'products_room');
3. Running the WebSocket Server (`php cli.php ws:serve`)
# Start WebSocket server on port 8001
php cli.php ws:serve 8001
# Start in background daemon mode (-d)
php cli.php ws:serve 8001 -d
# Stop or restart daemon
php cli.php ws:serve stop 8001
php cli.php ws:serve restart 8001 -d
API Client & Multi-cURL Client (`Core\Http`)
HTTP Suite
Need to call external microservices, payment gateways (Stripe/PayPal), LLM APIs, or webhooks? Core\Http
provides an ultra-lightweight cURL wrapper with connection pooling, automatic JSON encoding/decoding, and high-speed asynchronous batch execution via curl_multi_* without requiring Guzzle or heavy external dependencies.
1. Synchronous Requests (`Http::get` & `Http::post`)
use Core\Http;
use Core\Response;
// 1. Send GET request with headers
$response = Http::get('https://api.github.com/users/seip25', [
'User-Agent: LilaPHP-Engine/3.0',
'Accept: application/vnd.github.v3+json'
]);
// 2. Send POST JSON request automatically
$postResult = Http::post('https://api.stripe.com/v1/charges', [
'amount' => 2000,
'currency' => 'usd'
], [
'Authorization: Bearer sk_test_xxxxxx'
]);
// Check status codes and parse JSON response directly
if ($postResult['status'] === 200) {
Response::json(['payment' => 'success', 'data' => $postResult['json']]);
} else {
Response::json(['error' => 'Gateway rejected transaction'], 502);
}
2. High-Speed Concurrent Batch Requests (`Http::multi`)
Execute multiple HTTP requests simultaneously in parallel TCP sockets using asynchronous curl_multi_*:
use Core\Http;
use Core\Response;
// Dispatch 3 external API calls in parallel:
$results = Http::multi([
'weather' => ['url' => 'https://api.weather.com/v1/current', 'method' => 'GET', 'timeout' => 5],
'rates' => ['url' => 'https://api.exchange.com/rates', 'method' => 'GET', 'timeout' => 5],
'analytics'=> ['url' => 'https://analytics.internal/event', 'method' => 'POST', 'payload' => ['event' => 'page_view']]
]);
// Access each response directly by key
$weatherData = $results['weather']['json'];
$ratesData = $results['rates']['json'];
Response::json([
'weather' => $weatherData,
'rates' => $ratesData
]);
Built-in Debug & Benchmark CLI Engine
CLI Suite
LilaPHP features a zero-overhead interactive Debug & Benchmark CLI Engine built into php cli.php. It enables real-time system diagnostics, debug stream inspection, and OS-level asynchronous HTTP stress testing for high concurrencies directly from your terminal.
Configuring Debug Environment (`.env`)
Debug logging to Redis is disabled by default (DEBUG_LOGGING_ENABLED=false) to
guarantee zero performance overhead. Enable it in development or staging to capture live request streams:
DEBUG_LOGGING_ENABLED=false
When deploying to production via php cli.php docker prod, if
DEBUG_LOGGING_ENABLED is set to true, the CLI will display an
interactive warning asking for confirmation before proceeding.
Server-Side Load Test Runner (`curl_multi`)
LilaPHP features a built-in OS-level benchmark engine powered by asynchronous curl_multi_exec sockets. It executes real concurrent TCP connections and outputs live performance metrics directly to your terminal.
php cli.php benchmark --url=/api/health --concurrency=1000 --duration=30
- Req/Sec (RPS): Exact throughput measurement.
- Latency Percentiles: Calculates P50, P95, and P99 distribution.
- Terminal Metrics: Live progress reporting and comprehensive summary stats.
Running High-Concurrency Benchmark Tests (Bypassing Rate Limiters)
To run synthetic load testing at high concurrencies (100, 1000, 2000, 3000, 4000) without triggering rate limiters:
- Set
RATE_LIMIT=0in `.env` (disables PHP rate limiter). - Comment out Nginx C-level rate limiting in
docker/nginx/nginx.conf:
# limit_req_zone $binary_remote_addr zone=api_limit:10m rate=60r/s;
location ^~ /api/ {
# limit_req zone=api_limit burst=30 nodelay;
# limit_req_status 429;
include fastcgi_params;
fastcgi_pass php:9000;
...
}
Stats in real time with cli (optional)
#Execute docker stats with cli
php cli.php docker stats