Laravel 4 Request/Response Lifecycle

Laravel encapsulates HTTP requests and responses within PHP objects. As you likely know, the HTTP core of Laravel revolves around Symfony's HTTPFoundation component.

I was curious about how Laravel creates a request, and finally how this gets turned into a response behind the scenes. Here's an (uncomprehensive) overview of what happens.

Bootstrap

First, unsuprisingly, the Application object is created. This is located at [Illuminate\Foundation\Application](https://github.com/laravel/framework/blob/master/src/Illuminate/Foundation/Application.php).

Simply enough, the Request object is created in the __constructor method of the Application class.

/**
 * Create a new Illuminate application instance.
 *
 * @return void
 */
public function __construct()
{
	$this['request'] = Request::createFromGlobals();

	// The exception handler class takes care of determining which of the bound
	// exception handler Closures should be called for a given exception and
	// gets the response from them. We'll bind it here to allow overrides.
	$this->register(new ExceptionServiceProvider($this));

	$this->register(new RoutingServiceProvider($this));

	$this->register(new EventServiceProvider($this));
}

The Illuminate\Http\Request object extends Symfony\Component\HttpFoundation\Request.

The static method createFromGlobals is called, which uses the $_GET, $_POST, $_COOKIES, $_FILES and $_SERVER globals to create a populated Request object.

/**
 * Creates a new request with values from PHP's super globals.
 *
 * @return Request A new request
 *
 * @api
 */
public static function createFromGlobals()
{
    $request = new static($_GET, $_POST, array(), $_COOKIE, $_FILES, $_SERVER);

    if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded')
        && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH'))
    ) {
        parse_str($request->getContent(), $data);
        $request->request = new ParameterBag($data);
    }

    return $request;
}

App::Run()

After bootstrap, the application runs. At this stage, we have a Request object populated and ready. Next, the request is dispatched; The application determines the route, does defined requested logic, and returns the appropriate output to the browser or console.

App::run() is called, which first dispatches the created request object ($app['request']). Illuminate\Routing\Router does the dispatching. It matches and runs a Illuminate\Routing\Route, and ultimately returns a Response object.

The Response object is generated at a call to Router::prepare(). This method takes a string of output returned from a route (Usually the output of a View), and passes that into a new Response object.

Lastly (almost), App::run() calls Response::send, which outputs the content to the browser or console.

public function send()
{
    $this->sendHeaders();
    $this->sendContent();

    if (function_exists('fastcgi_finish_request')) {
        fastcgi_finish_request();
    } elseif ('cli' !== PHP_SAPI) {
        // ob_get_level() never returns 0 on some Windows configurations, so if
        // the level is the same two times in a row, the loop should be stopped.
        $previous = null;
        $obStatus = ob_get_status(1);
        while (($level = ob_get_level()) > 0 && $level !== $previous) {
            $previous = $level;
            if ($obStatus[$level - 1] && isset($obStatus[$level - 1]['del']) && $obStatus[$level - 1]['del']) {
                ob_end_flush();
            }
        }
        flush();
    }

    return $this;
}