Many functions store a callback: usort() on each comparison, spl_autoload_register() on each unknown class (Autoloading), set_error_handler() on each warning (Custom Error Handlers). register_shutdown_function($cb, ...$args) runs $cb when the script ends, normally or through exit(), in registration order and before object destructors. The old create_function() was removed in PHP 8.0; pass a closure instead.
<?php
declare(strict_types=1);
final class Db { public function __destruct() { echo "3. destructor: db closed\n"; } }
$db = new Db();
register_shutdown_function(fn(string $who) => print("2. shutdown: bye $who\n"), 'Ana');
$books = [['SQL Workbook', 18.0], ['PHP Pocket Guide', 12.5], ['Linux Basics', 21.0]];
usort($books, fn(array $a, array $b): int => $a[1] <=> $b[1]); // a sort callback
echo '1. cheapest: ', $books[0][0], "\n";
exit(0); // shutdown functions still run1. cheapest: PHP Pocket Guide 2. shutdown: bye Ana 3. destructor: db closed
Shutdown functions also run after a fatal error, when destructors do not, so one that reads error_get_last() is how you log crashes (Uncaught Exceptions). They do not run if the process is killed with SIGTERM or SIGKILL, and under Apache 129 the working directory may change, so use absolute paths inside them.