1. Go to this page and download the library: Download rcalicdan/defer library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
rcalicdan / defer example snippets
use Rcalicdan\Defer\Defer;
function processFile($filename) {
$file = fopen($filename, 'r');
// Defer cleanup - executes when function ends
$defer = Defer::scope();
$defer->task(fn() => fclose($file));
// Your file processing logic here
$data = fread($file, 1024);
// File automatically closed when function returns
return $data;
}
use Rcalicdan\Defer\Defer;
function databaseTransaction() {
$pdo = new PDO($dsn, $user, $pass);
$pdo->beginTransaction();
$defer = Defer::scope();
$defer->task(fn() => $pdo->rollback()); // Safety rollback
// Perform operations
$stmt = $pdo->prepare("INSERT INTO users (name) VALUES (?)");
$stmt->execute(['John']);
$pdo->commit();
// Defer cleanup executes here (though rollback is harmless after commit)
}
function processMultipleFiles(array $filenames) {
$defer = Defer::scope();
$handles = [];
foreach ($filenames as $filename) {
$handle = fopen($filename, 'r');
$handles[] = $handle;
// Each file gets its own cleanup defer
$defer->task(fn() => fclose($handle));
}
// Process all files
foreach ($handles as $handle) {
// ... process file
}
// All files automatically closed when function ends (LIFO order)
}
use Rcalicdan\Defer\Defer;
Defer::global(function() {
echo "First registered\n";
});
Defer::global(function() {
echo "Second registered\n";
});
Defer::global(function() {
echo "Third registered\n";
});
// Output on shutdown (LIFO order):
// Third registered
// Second registered
// First registered
// Opt in once, early in your entry point
Defer::enableSignals();
Defer::global(function() {
file_put_contents('/tmp/shutdown.log', 'Clean shutdown: ' . date('Y-m-d H:i:s'));
});
// Your long-running process
while (true) {
// ... do work
sleep(1);
}
// Without enableSignals(): cleanup runs on normal exit only
// With enableSignals(): cleanup also runs on Ctrl+C, SIGTERM, SIGHUP, etc.
use Rcalicdan\Defer\Defer;
function handleRequest($request) {
$response = processRequest($request);
// Background tasks execute in FIFO order after response is sent
Defer::terminate(function() use ($request) {
logAnalytics($request->getUri(), $request->getUserAgent());
});
Defer::terminate(function() use ($request) {
sendWelcomeEmail($request->get('email'));
});
return $response;
}
// Only runs on successful responses (2xx, 3xx)
Defer::terminate(fn() => incrementSuccessCounter());
// Always runs, regardless of status code
Defer::terminate(function() {
logRequestCompletion();
}, always: true);
// Function-scoped - manual execution in LIFO order
$defer = Defer::scope();
$defer->task(fn() => echo "Second\n");
$defer->task(fn() => echo "First\n");
$defer->executeAll();
// Global - manual execution in LIFO order
Defer::global(fn() => echo "Global cleanup\n");
Defer::getHandler()->executeAll();
// Terminate - manual execution in FIFO order
Defer::terminate(fn() => echo "First task\n");
Defer::terminate(fn() => echo "Second task\n");
Defer::getHandler()->executeTerminate();
// Check pending defer count
$defer = Defer::scope();
$defer->task(fn() => cleanup1());
$defer->task(fn() => cleanup2());
echo $defer->count(); // 2
// Check whether signal handling is active
var_dump(Defer::signalsEnabled()); // bool(false) by default
// Inspect signal handling capabilities
$info = Defer::getHandler()->getSignalHandlingInfo();
print_r($info);
// Run the built-in capability test (outputs platform/method details)
Defer::getHandler()->testSignalHandling();
$info = Defer::getHandler()->getHandler()->getEnvironmentInfo();
if ($info['fastcgi'] && $info['fastcgi_finish_request']) {
echo "✅ Optimal terminate defer support available\n";
} else {
echo "⚠️ Using fallback terminate handling\n";
}
$defer = Defer::scope()
->task(function() {
throw new Exception("This won't stop other defers");
})
->task(function() {
echo "This will still execute\n";
});
// Exception is logged via error_log(), execution continues in LIFO order
function transferFunds($fromAccount, $toAccount, $amount) {
$pdo = new PDO($dsn, $user, $pass);
$pdo->beginTransaction();
$defer = Defer::scope()
->task(fn() => auditLog("Transaction attempt completed")) // Runs first (LIFO)
->task(fn() => $pdo->rollback()); // Runs second - safety net
$stmt = $pdo->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?");
$stmt->execute([$amount, $fromAccount]);
$stmt = $pdo->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?");
$stmt->execute([$amount, $toAccount]);
$pdo->commit();
// LIFO: audit log, then rollback (harmless after commit)
}
function processOrder($orderData) {
$order = createOrder($orderData);
// Background tasks execute in FIFO order after response is sent
Defer::terminate(function() use ($order) {
updateInventory($order); // Runs first
});
Defer::terminate(function() use ($order) {
sendConfirmationEmail($order); // Runs second
});
Defer::terminate(function() use ($order) {
logOrderCompletion($order); // Runs third
});
return ['success' => true, 'order_id' => $order->id];
}
// Opt in to signal handling for graceful interruption
Defer::enableSignals();
// Register cleanup in LIFO order
Defer::global(fn() => echo "Shutdown complete\n");
Defer::global(function() {
file_put_contents('/var/log/worker.log', "Worker stopped: " . date('c') . "\n", FILE_APPEND);
});
Defer::global(fn() => echo "Starting shutdown sequence...\n");
while (true) {
$job = getNextJob();
if (!$job) {
sleep(1);
continue;
}
processJob($job);
}
// LIFO cleanup runs on normal exit AND on Ctrl+C / SIGTERM (because enableSignals() was called)
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.