Understanding the Request Lifecycle, Service Container, and Facades
Tags: laravel, php, beginners
Published: 2023-09-09 23:50:47

This topic may seem a bit advanced to me, but I believe it's crucial to grasp how a Laravel application works. This article provides an overview of the official documentation, emphasizing the simplification of essential concepts for better understanding.

**Glossary**
**Bootstrap**: Refers to the process of starting up a computer or software application. It often implies the initial setup or starting point for a system or program to become functional.
**Kernel**: A vital OS component that acts as a bridge between hardware and software, allowing multiple applications to share and access computer resources like CPU, memory, storage, and networking.

**Request Lifecycle**

> The application instance is created, the service providers are registered, and the request is handed to the bootstraped application.
[Laravel](https://laravel.com/docs/10.x/lifecycle)

The entry point of a Laravel application is the `public/index.php` file.

```
<?php

use Illuminate\Contracts\Http\Kernel;
use Illuminate\Http\Request;

define('LARAVEL_START', microtime(true));

/*
|--------------------------------------------------------------------------
| Check If The Application Is Under Maintenance
|--------------------------------------------------------------------------
|
| If the application is in maintenance / demo mode via the "down" command
| we will load this file so that any pre-rendered content can be shown
| instead of starting the framework, which could cause an exception.
|
*/

if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {
    require $maintenance;
}

/*
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader for
| this application. We just need to utilize it! We'll simply require it
| into the script here so we don't need to manually load our classes.
|
*/

require __DIR__.'/../vendor/autoload.php';

/*
|--------------------------------------------------------------------------
| Run The Application
|--------------------------------------------------------------------------
|
| Once we have the application, we can handle the incoming request using
| the application's HTTP kernel. Then, we will send the response back
| to this client's browser, allowing them to enjoy our application.
|
*/

$app = require_once __DIR__.'/../bootstrap/app.php';

$kernel = $app->make(Kernel::class);

$response = $kernel->handle(
    $request = Request::capture()
)->send();

$kernel->terminate($request, $response);

```

First, the `public/index.php` file loads Composer, which provides a convenient, automatically generated class loader for the application, and retrieves an instance of the Laravel application from `bootstrap/app.php`.

Next, the incoming request is sent to either the HTTP kernel or the console kernel. These kernels serve as central locations through which all requests flow. The HTTP kernel, in particular, executes bootstrappers that handle tasks necessary before handling requests and defines all the middleware.

HTTP/Kernel.php

```
<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array<int, class-string|string>
     */
    protected $middleware = [
        // \App\Http\Middleware\TrustHosts::class,
        \App\Http\Middleware\TrustProxies::class,
        \Illuminate\Http\Middleware\HandleCors::class,
        \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array<string, array<int, class-string|string>>
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];

    /**
     * The application's middleware aliases.
     *
     * Aliases may be used instead of class names to conveniently assign middleware to routes and groups.
     *
     * @var array<string, class-string|string>
     */
    protected $middlewareAliases = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
        'precognitive' => \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
        'signed' => \App\Http\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    ];
}
```

Service providers are loaded. Service providers play a crucial role as they bootstrap various components of the framework.

The `App\Providers\RouteServiceProvider` is vital for routing in Laravel. It loads route files, defines how requests are handled and runs middleware. Middleware checks incoming requests (e.g., user authentication) and directs them accordingly. If a request passes middleware, it triggers the associated route or controller method, and the response goes through more middleware before reaching the client.

```
<?php

namespace App\Providers;

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;

class RouteServiceProvider extends ServiceProvider
{
    /**
     * The path to your application's "home" route.
     *
     * Typically, users are redirected here after authentication.
     *
     * @var string
     */
    public const HOME = '/home';

    /**
     * Define your route model bindings, pattern filters, and other route configuration.
     */
    public function boot(): void
    {
        RateLimiter::for('api', function (Request $request) {
            return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
        });

        $this->routes(function () {
            Route::middleware('api')
                ->prefix('api')
                ->group(base_path('routes/api.php'));

            Route::middleware('web')
                ->group(base_path('routes/web.php'));
        });
    }
}

```

**Service Container**
The Laravel service container is a class instance that automatically manages class dependencies and performs dependency injection without the need for manual binding. 

**Service Provider**
 To add our own service providers in Laravel, we typically include them in the `config/app.php` file within the provider's array. 

**Facades**
Facades are built-in classes in Laravel that provide a convenient and expressive way to access services from the service container. To use a facade, we typically import it using the use statement at the top of our class or component.

routes/web.php

```
use Illuminate\Support\Facades\Route;

Route::get('/', fn () => view('landing'))->name('landing');
```

There's more to delve into to understand the inner workings of a Laravel application. However, as the documentation states, 'When you understand how your development tools function, you feel more comfortable and confident using them.' With this knowledge, I'm well-equipped to move forward and enjoy creating applications.