/** * Initialize a new session for a user, such as for a login. * Registers a listener for the `error` event to reset the session to its initial state. */ public static function start() { session_start(); self::$reset = $_SESSION; E::listen('error', function () { self::reset(); }); }
/** * Bootstraps a few INI settings, error handling, and enables direct output. * * - `session.serialize_handler` is set to `php_serialize` * * - `session.cookie_httpOnly` is enabled. * * - `display_errors` and `display_startup_errors` is set to boolean of whether we are running in the CLI server. * * - `log_errors` is enabled. * * - PHP's internal output buffer is disabled. * All content is sent directly over the wire unless buffering functions are used. * This means that views ({@link \H\V}) and other dynamic content will have no `Content-Length` header unless explicitly set (see {@link \H\O}). * * - [error_reporting()](http://php.net/error-reporting) is set to non-informational errors and warnings. `E_STRICT` is ignored. * * - [set_error_handler()](http://php.net/set-error-handler) to throw an [ErrorException](http://php.net/ErrorException) * for errors in [error_reporting()](http://php.net/error-reporting), thus "reporting" becomes synonymous with "throwing". * All uncaught exceptions find their way to the `error` event (see below). * Excluded error levels are not thrown, but do get sent to the `log` event (see below), unless silenced with `@`. * * - [set_exception_handler()](http://php.net/set-exception-handler) to notify the `log` and `error` events (see below). * {@link \H\X} is not given to the `log` event, as it is intended for error slippage and can contain potentially large payloads for the user. * * - Puts a listener on the `error` event. The listener sets a response code and **exits gracefully**. * This event should *only* be notified by the global exception handler, you should not notify it manually. * Because event listeners are called in LIFO order (see {@link \H\E}), this listener is always called last, * so you can pile on additional listeners and exit *more* gracefully. * The listener behaves as follows: * If the exception is {@link \H\X} then its code and message are used for the response. * Otherwise the response code is set to `503` and a generic message is used including the request ID * so the user at least has a reference for the failure (see {@link \H\I::id()}). * If you attach a listener to the `error` event you can expect an `Exception` as the only argument, or a `Throwable` if in PHP 7. * {@link \H\X} must be treated as a JSON encoded HTTP error for the user, and *not* as a server error. * You can simply `return` from your listener if you encounter {@link \H\X} so it can find its way to this listener. * * - Puts a listener on the `log` event. * The listener formats a message including the error code, client IP, request method, and request URI, and gives it to [error_log()](php.net/function.error-log). * The listener can be trumped by attaching a new listener and returning `false` from it (see {@link \H\E::notify()}). * * The `log` event can be manually notified with the following arguments: * * - `string $message` * - `int $type` (optional) * * As a rule of thumb, HTTP status codes can be used for custom log types, since they don't collide with any * [error constants](http://php.net/errorfunc.constants) (powers of 2), * and the numeric categories of HTTP codes provide context for the nature of the log. * * Listeners should assume the type is `100` (informational/verbose) if not given. * The framework doesn't notify the `log` event except for error reporting. * * The `log` event is for broadcasting logs only and should **not** output user content or exit. */ public static function init() { error_reporting(E_ALL); // in case of problems with init. made quieter below. ini_set('log_errors', true); ob_implicit_flush(); // directly output header('X-Request-ID: ' . I::id()); $dev = php_sapi_name() === 'cli-server'; ini_set('display_errors', $dev); ini_set('display_startup_errors', $dev); ini_set('session.cookie_httpOnly', true); ini_set('session.serialize_handler', 'php_serialize'); E::listen('error', function ($thrown) { self::onError($thrown); }); E::listen('log', function ($message, $type = 100) { self::onLog($message, $type); }); set_error_handler(function ($code, $message, $file, $line) { self::phpErrorHandler($code, $message, $file, $line); }); set_exception_handler(function ($thrown) { self::phpExceptionHandler($thrown); }); error_reporting(E_RECOVERABLE_ERROR | E_WARNING | E_USER_ERROR | E_USER_WARNING); }