Life Cycle and Principle Analysis of Laravel Framework

  • 2021-10-16 01:18:52
  • OfStack

This paper describes the life cycle and principle of Laravel framework with examples. Share it for your reference, as follows:

Introduction:

If you know the principle of using a tool like the back of your hand, you will be full of confidence when using this tool!

Text:

Once the user (browser) sends an HTTP request, our apache or nginx1 goes to index. php, so the next 1 series of steps start from index. php. Let's look at this file code first.


<?php
require __DIR__.'/../bootstrap/autoload.php';
$app = require_once __DIR__.'/../bootstrap/app.php';
/*
|--------------------------------------------------------------------------
| Run The Application
|--------------------------------------------------------------------------
|
| Once we have the application, we can handle the incoming request
| through the kernel, and send the associated response back to
| the client's browser allowing them to enjoy the creative
| and wonderful application we have prepared for them.
|
*/
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$response = $kernel->handle(
  $request = Illuminate\Http\Request::capture()
);
$response->send();
$kernel->terminate($request, $response);

In the annotation, the author talks about the role of kernel, the role of kernel, and the role of kernel in handling visiting requests and sending them back to the user's browser.

There is another app object involved, so we attach app object, so we attach the source code of app object, which is\ bootstrap\ app. php


<?php
/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| The first thing we will do is create a new Laravel application instance
| which serves as the "glue" for all the components of Laravel, and is
| the IoC container for the system binding all of the various parts.
|
*/
$app = new Illuminate\Foundation\Application(
  realpath(__DIR__.'/../')
);
/*
|--------------------------------------------------------------------------
| Bind Important Interfaces
|--------------------------------------------------------------------------
|
| Next, we need to bind some important interfaces into the container so
| we will be able to resolve them when needed. The kernels serve the
| incoming requests to this application from both the web and CLI.
|
*/
$app->singleton(
  Illuminate\Contracts\Http\Kernel::class,
  App\Http\Kernel::class
);
$app->singleton(
  Illuminate\Contracts\Console\Kernel::class,
  App\Console\Kernel::class
);
$app->singleton(
  Illuminate\Contracts\Debug\ExceptionHandler::class,
  App\Exceptions\Handler::class
);
/*
|--------------------------------------------------------------------------
| Return The Application
|--------------------------------------------------------------------------
|
| This script returns the application instance. The instance is given to
| the calling script so we can separate the building of the instances
| from the actual running of the application and sending responses.
|
*/
return $app;

Please see that the app variable is an object of the Illuminate\ Foundation\ Application class, so the constructor of this class is called. We look at the source code for what we did.


public function __construct($basePath = null)
{
  if ($basePath) {
    $this->setBasePath($basePath);
  }
  $this->registerBaseBindings();
  $this->registerBaseServiceProviders();
  $this->registerCoreContainerAliases();
}

Constructor did 3 things, the first two things are easy to understand, create Container, registered ServiceProvider, look at the code


/**
 * Register the basic bindings into the container.
 *
 * @return void
 */
protected function registerBaseBindings()
{
  static::setInstance($this);
  $this->instance('app', $this);
  $this->instance(Container::class, $this);
}
/**
 * Register all of the base service providers.
 *
 * @return void
 */
protected function registerBaseServiceProviders()
{
  $this->register(new EventServiceProvider($this));
  $this->register(new LogServiceProvider($this));
  $this->register(new RoutingServiceProvider($this));
}

The last thing is to make a large array and define a large number of aliases, which shows that programmers are smart lazy people.


/**
 * Register the core class aliases in the container.
 *
 * @return void
 */
public function registerCoreContainerAliases()
{
  $aliases = [
    'app'         => [\Illuminate\Foundation\Application::class, \Illuminate\Contracts\Container\Container::class, \Illuminate\Contracts\Foundation\Application::class],
    'auth'         => [\Illuminate\Auth\AuthManager::class, \Illuminate\Contracts\Auth\Factory::class],
    'auth.driver'     => [\Illuminate\Contracts\Auth\Guard::class],
    'blade.compiler'    => [\Illuminate\View\Compilers\BladeCompiler::class],
    'cache'        => [\Illuminate\Cache\CacheManager::class, \Illuminate\Contracts\Cache\Factory::class],
    'cache.store'     => [\Illuminate\Cache\Repository::class, \Illuminate\Contracts\Cache\Repository::class],
    'config'        => [\Illuminate\Config\Repository::class, \Illuminate\Contracts\Config\Repository::class],
    'cookie'        => [\Illuminate\Cookie\CookieJar::class, \Illuminate\Contracts\Cookie\Factory::class, \Illuminate\Contracts\Cookie\QueueingFactory::class],
    'encrypter'      => [\Illuminate\Encryption\Encrypter::class, \Illuminate\Contracts\Encryption\Encrypter::class],
    'db'          => [\Illuminate\Database\DatabaseManager::class],
    'db.connection'    => [\Illuminate\Database\Connection::class, \Illuminate\Database\ConnectionInterface::class],
    'events'        => [\Illuminate\Events\Dispatcher::class, \Illuminate\Contracts\Events\Dispatcher::class],
    'files'        => [\Illuminate\Filesystem\Filesystem::class],
    'filesystem'      => [\Illuminate\Filesystem\FilesystemManager::class, \Illuminate\Contracts\Filesystem\Factory::class],
    'filesystem.disk'   => [\Illuminate\Contracts\Filesystem\Filesystem::class],
    'filesystem.cloud'   => [\Illuminate\Contracts\Filesystem\Cloud::class],
    'hash'         => [\Illuminate\Contracts\Hashing\Hasher::class],
    'translator'      => [\Illuminate\Translation\Translator::class, \Illuminate\Contracts\Translation\Translator::class],
    'log'         => [\Illuminate\Log\Writer::class, \Illuminate\Contracts\Logging\Log::class, \Psr\Log\LoggerInterface::class],
    'mailer'        => [\Illuminate\Mail\Mailer::class, \Illuminate\Contracts\Mail\Mailer::class, \Illuminate\Contracts\Mail\MailQueue::class],
    'auth.password'    => [\Illuminate\Auth\Passwords\PasswordBrokerManager::class, \Illuminate\Contracts\Auth\PasswordBrokerFactory::class],
    'auth.password.broker' => [\Illuminate\Auth\Passwords\PasswordBroker::class, \Illuminate\Contracts\Auth\PasswordBroker::class],
    'queue'        => [\Illuminate\Queue\QueueManager::class, \Illuminate\Contracts\Queue\Factory::class, \Illuminate\Contracts\Queue\Monitor::class],
    'queue.connection'   => [\Illuminate\Contracts\Queue\Queue::class],
    'queue.failer'     => [\Illuminate\Queue\Failed\FailedJobProviderInterface::class],
    'redirect'       => [\Illuminate\Routing\Redirector::class],
    'redis'        => [\Illuminate\Redis\RedisManager::class, \Illuminate\Contracts\Redis\Factory::class],
    'request'       => [\Illuminate\Http\Request::class, \Symfony\Component\HttpFoundation\Request::class],
    'router'        => [\Illuminate\Routing\Router::class, \Illuminate\Contracts\Routing\Registrar::class, \Illuminate\Contracts\Routing\BindingRegistrar::class],
    'session'       => [\Illuminate\Session\SessionManager::class],
    'session.store'    => [\Illuminate\Session\Store::class, \Illuminate\Contracts\Session\Session::class],
    'url'         => [\Illuminate\Routing\UrlGenerator::class, \Illuminate\Contracts\Routing\UrlGenerator::class],
    'validator'      => [\Illuminate\Validation\Factory::class, \Illuminate\Contracts\Validation\Factory::class],
    'view'         => [\Illuminate\View\Factory::class, \Illuminate\Contracts\View\Factory::class],
  ];
  foreach ($aliases as $key => $aliases) {
    foreach ($aliases as $alias) {
      $this->alias($key, $alias);
    }
  }
}

There is an instance function, which is not a function of Application class, but a function of Container class, the parent class of Application class


/**
 * Register an existing instance as shared in the container.
 *
 * @param string $abstract
 * @param mixed  $instance
 * @return void
 */
public function instance($abstract, $instance)
{
  $this->removeAbstractAlias($abstract);
  unset($this->aliases[$abstract]);
  // We'll check to determine if this type has been bound before, and if it has
  // we will fire the rebound callbacks registered with the container and it
  // can be updated with consuming classes that have gotten resolved here.
  $this->instances[$abstract] = $instance;
  if ($this->bound($abstract)) {
    $this->rebound($abstract);
  }
}

Application is a subclass of Container, so $app Not only Application class object, or Container object, so the new singleton function we can look in the source code file of Container class. See this blog post for the difference between bind function and singleton function.

singleton, the first argument is the actual class name, and the last argument is the "alias" of the class.

$app Object declares three singleton model objects, which are HttpKernel, ConsoleKernel and ExceptionHandler. Please note that there is no object created here, only declaration, and only an "alias" is given.

Have you noticed that there is also a $kernel variable in index. php, but only the HttpKernel variable from make is saved, so this article will not discuss ConsoleKernel and ExceptionHandler. . .

Continue to find App\ Http\ Kernel. php in the folder. Since we write everything that the actual HttpKernel does in this php file, let's see what we did in this code.


<?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
   */
  protected $middleware = [
    \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
    //\App\Http\Middleware\MyMiddleware::class,
  ];
  /**
   * The application's route middleware groups.
   *
   * @var array
   */
  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,
    ],
    'api' => [
      'throttle:60,1',
    ],
  ];
  /**
   * The application's route middleware.
   *
   * These middleware may be assigned to groups or used individually.
   *
   * @var array
   */
  protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
  'mymiddleware'=>\App\Http\Middleware\MyMiddleware::class,
  ];
}

1 clearly, HttpKernel defines middleware array.

When what should be done is done, the request-to-response process begins, see index. php


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

Finally, after abort, all resources are released.


/**
* Call the terminate method on any terminable middleware.
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Http\Response $response
* @return void
*/
public function terminate($request, $response)
{
    $this->terminateMiddleware($request, $response);
    $this->app->terminate();
}

In summary 1, simply summarize the whole process as follows:

1. index. php loads\ bootstrap\ app. php, creates Container in the constructor of the Application class, registers ServiceProvider, defines an alias array, and then saves the object constructed by the constructor with the app variable.

2. Using the object app, we create a singleton object HttpKernel. When we create HttpKernel, we call the constructor and complete the declaration of middleware.

3. All of this is done before you request a visit, and then you start waiting for the request, and then you accept the request- > Processing requests-- > Send a response-- > Abort app variable

For more readers interested in Laravel related content, please check the topics on this site: "Introduction and Advanced Tutorial of Laravel Framework", "Summary of Excellent Development Framework of php", "Introduction Tutorial of php Object-Oriented Programming", "Introduction Tutorial of php+mysql Database Operation" and "Summary of Common Database Operation Skills of php"

I hope this article is helpful to PHP programming based on Laravel framework.


Related articles: