Рубрики
Uncategorized

Процесс запуска Laravel

Автор оригинала: David Wong.

Последнее изменение: 10 мая 2019 16:19:07

Laravel 5.5 Весь этап выполнения от запроса до ответа сводится к четырем:

  1. Процедура Начала Подготовительного Этапа

    • Автоматическая Загрузка Файлов
    • Создание экземпляра контейнера службы
    • Регистрация основных поставщиков услуг
    • Экземпляр основных классов
  2. Этап создания экземпляра запроса

    • Создать экземпляр запроса
  3. Этап обработки запроса

    • Среда для подготовки обработки запросов
    • Обработка экземпляров запросов с помощью промежуточного программного обеспечения и контроль распространения через маршрутизаторы и контроллеры
  4. Этапы отправки ответа и завершения программы

    • Верните содержимое ответа клиенту
    • Записывайте информацию, связанную с клиентом, и т.д.

Запись в программе находится в индексе. php в

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

$app = require_once_ DIR_.'/. / bootstrap / app. php'; Get the service container instance

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

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

$response->send();

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

Создание экземпляров контейнеров служб

Создание сервисных контейнеров в bootstrap\app.php В процессе.

$app = new Illuminate\Foundation\Application(
    realpath(__DIR__.'/../')
);

1.1 Конфигурация фундамента Контейнера

контейнер Приложение Конструктор:

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

    $this->registerBaseBindings();

    $this->registerBaseServiceProviders();

    $this->registerCoreContainerAliases();
}

Конструктор в основном выполняет следующие основные конфигурации:

  • Пути к каталогам (привязка к контейнерам и предоставление методов класса для получения подкаталогов)

  • Свяжите сам контейнер

  • Регистрация Базовой Услуги (Событие, Журнал, Маршрут)

  • Регистрация псевдонима

    Несколько имен интерфейса соответствуют короткому псевдониму, и впоследствии их необходимо привязывать только к псевдониму при регистрации службы (а не к определенному имени интерфейса).

1.2 Привязка к Основному Классу

$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
);

Привязка Важных Интерфейсов:

  • Основной Класс Http
  • Базовый класс командной строки
  • Класс обработки исключений

1.3 Экземпляр основных классов Http

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

Конструктор базового класса Http

public function __construct(Application $app, Router $router)
{
    $this->app = $app;
    $this->router = $router;

    $router->middlewarePriority = $this->middlewarePriority;

    foreach ($this->middlewareGroups as $key => $middleware) {
        $router->middlewareGroup($key, $middleware);
    }

    foreach ($this->routeMiddleware as $key => $middleware) {
        $router->aliasMiddleware($key, $middleware);
    }
}

Основной задачей описанного выше процесса является назначение промежуточного программного обеспечения для маршрутизации

  • Список последовательных приоритетов промежуточного программного обеспечения
  • Группа промежуточного программного обеспечения
  • Псевдонимы промежуточного программного обеспечения

Основные категории app/Http/Kernel.php

laravel-China.org/docs/5.5/configuration#maintenance-mode
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,

        // Check if the requested data is too large
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,

        // PHP function `trim ()` processes submitted request parameters
        \App\Http\Middleware\TrimStrings::class,

        // Converting hollow substrings of submission request parameters to null
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,

        // Server parameters after proxy server modification
        \App\Http\Middleware\TrustProxies::class,
    ];

    // Defining middleware groups
    protected $middlewareGroups = [

        // Web middleware group for routes/web.php routing files
        'web' => [
            // Cookie Encryption and Decryption
            \App\Http\Middleware\EncryptCookies::class,

            // Add Cookie to the response
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,

            // Open a conversation
            \Illuminate\Session\Middleware\StartSession::class,

            // Authenticate the user and the Auth class will not take effect until the middleware is authenticated
            // See: https://d.laravel-China.org/docs/5.5/authentication
            \Illuminate\Session\Middleware\AuthenticateSession::class,

            // Inject system error data into view variable $errors
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,

            // Check CSRF to prevent security threats from forgery of cross-station requests
            // See: https://d.laravel-China.org/docs/5.5/csrf
            \App\Http\Middleware\VerifyCsrfToken::class,

            // Handling routing bindings
            // See: https://d.laravel-China.org/docs/5.5/routing#route-model-binding
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        // API middleware group for routes/api.php routing files
        'api' => [
            // Use aliases to invoke Middleware
            // See: https://d.laravel-China.org/docs/5.5/middleware# Assign Middleware for Routing
            'throttle:60,1',
            'bindings',
        ],
    ];

    // Middleware alias settings allow you to call middleware using aliases, such as the API middleware group call above
    protected $routeMiddleware = [

        // Only logged-in users can access it, and we use it extensively in the construction of controllers.
        'auth' => \Illuminate\Auth\Middleware\Authenticate::class,

        // HTTP Basic Auth Authentication
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,

        // Handling routing bindings
        // See: https://d.laravel-China.org/docs/5.5/routing#route-model-binding
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,

        // User Authorization Function
        'can' => \Illuminate\Auth\Middleware\Authorize::class,

        // Only visitors can access these pages, used in registers and login requests, and only unregistered users can access these pages.
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,

        // Access throttling, similar to the requirement that requests can only be made 10 times per minute, is commonly used in APIs
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    ];
}

Возьмем в качестве примера обработку Http-запросов

index.php Файл ввода

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

Запрос выполняется Illuminate\Http\Request::capture() Экземпляр в основном предназначен для выражения информации о запросе в форме объекта.

Файл записи:

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

$ядро->обработка(...) Процесс обработки запроса

Осветить\Фундамент\Http\Ядро

public function handle($request)
{
    try {
        $request->enableHttpMethodParameterOverride();

        $response = $this->sendRequestThroughRouter($request);
    } catch (Exception $e) {
        $this->reportException($e);

        $response = $this->renderException($request, $e);
    } catch (Throwable $e) {
        $this->reportException($e = new FatalThrowableError($e));

        $response = $this->renderException($request, $e);
    }

    $this->app['events']->dispatch(
        new Events\RequestHandled($request, $response)
    );

    return $response;
}


protected function sendRequestThroughRouter($request)
{
    $this->app->instance('request', $request);

    Facade::clearResolvedInstance('request');

    $this - > bootstrap ();  Core class initialization

    return (new Pipeline($this->app))
        ->send($request)
        ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
        ->then($this->dispatchToRouter());
}


protected function dispatchToRouter()
{
    return function ($request) {
        $this->app->instance('request', $request);

        return $this->router->dispatch($request);
    };
}

Фактическая логика обработки запроса в основном основана на sendRequestThroughRouter В методе, он в основном делает:

  • Инициализация основных классов
  • После фильтрации через промежуточное программное обеспечение запрос, наконец, отправляется в Маршрутизатор Дескриптор

    Для обработки Http-запросов промежуточное программное обеспечение включает:

    Массив промежуточного программного обеспечения определяется в основном классе Http и передается конструктору основного класса. Маршрутизатор класс

3.1 Инициализация среды обработки запросов

Инициализация основных классов начальная загрузка()

protected $bootstrappers = [
    \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
    \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
    \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
    \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
    \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
    \Illuminate\Foundation\Bootstrap\BootProviders::class,
];

# Initialization
public function bootstrap()
{
    if (! $this->app->hasBeenBootstrapped()) {
        $this->app->bootstrapWith($this->bootstrappers());
    }
}

protected function bootstrappers()
{
    return $this->bootstrappers;
}

В Сервисном контейнере Приложение В классе

public function bootstrapWith(array $bootstrappers)
{
    $this->hasBeenBootstrapped = true;

    foreach ($bootstrappers as $bootstrapper) {
        $this['events']->fire('bootstrapping: '.$bootstrapper, [$this]);

        $this->make($bootstrapper)->bootstrap($this);

        $this['events']->fire('bootstrapped: '.$bootstrapper, [$this]);
    }
}

Этот шаг в основном определен в основном классе. $загрузчики Инициализация элемента массива (загрузочного класса).

Процесс начальной загрузки реализуется в контейнере службы, который вызывается основным классом и передается в класс, подлежащий инициализации.

По умолчанию класс Http core содержит следующие шесть служб запуска:

1. Мониторинг окружающей среды\Освещение\Фундамент\Начальная загрузка\Переменные среды загрузки::класс

из .env Разрешите переменные среды в get even() , $_ENV , |/$_SERVER

полагайтесь на vlucas/phpdotenv Пакет расширений

2. Загрузка конфигурации\Подсветка\Основа\Начальная загрузка\Конфигурация загрузки::класс

загрузить конфигурация Все файлы конфигурации PHP в каталоге и свяжите созданные классы хранилища конфигурации с контейнером службы $app['config']

Настройка часового пояса и многобайтового формата (utf 8)

3. Частое лечение\Осветление\Основа\Начальная загрузка\Рекомендации::класс

Все сообщения об ошибках error_report(E_ALL)

Обеспечивает глобальную обработку обнаруженных исключений и ошибок set_error_handler , set_exception_handler , register_shutdown_function

4. Регистрация внешнего вида\Подсветка\Основа\Начальная загрузка\RegisterFacades::класс

из app.псевдонимы Прочитайте массив конфигурации внешнего вида

'aliases' => [

        'App' => Illuminate\Support\Facades\App::class,
        'Artisan' => Illuminate\Support\Facades\Artisan::class,
        'Auth' => Illuminate\Support\Facades\Auth::class,
        'Blade' => Illuminate\Support\Facades\Blade::class,
        'Broadcast' => Illuminate\Support\Facades\Broadcast::class,
        'Bus' => Illuminate\Support\Facades\Bus::class,
        'Cache' => Illuminate\Support\Facades\Cache::class,
        'Config' => Illuminate\Support\Facades\Config::class,
        'Cookie' => Illuminate\Support\Facades\Cookie::class,
        'Crypt' => Illuminate\Support\Facades\Crypt::class,
        'DB' => Illuminate\Support\Facades\DB::class,
        'Eloquent' => Illuminate\Database\Eloquent\Model::class,
        'Event' => Illuminate\Support\Facades\Event::class,
        'File' => Illuminate\Support\Facades\File::class,
        'Gate' => Illuminate\Support\Facades\Gate::class,
        'Hash' => Illuminate\Support\Facades\Hash::class,
        'Lang' => Illuminate\Support\Facades\Lang::class,
        'Log' => Illuminate\Support\Facades\Log::class,
        'Mail' => Illuminate\Support\Facades\Mail::class,
        'Notification' => Illuminate\Support\Facades\Notification::class,
        'Password' => Illuminate\Support\Facades\Password::class,
        'Queue' => Illuminate\Support\Facades\Queue::class,
        'Redirect' => Illuminate\Support\Facades\Redirect::class,
        'Redis' => Illuminate\Support\Facades\Redis::class,
        'Request' => Illuminate\Support\Facades\Request::class,
        'Response' => Illuminate\Support\Facades\Response::class,
        'Route' => Illuminate\Support\Facades\Route::class,
        'Schema' => Illuminate\Support\Facades\Schema::class,
        'Session' => Illuminate\Support\Facades\Session::class,
        'Storage' => Illuminate\Support\Facades\Storage::class,
        'URL' => Illuminate\Support\Facades\URL::class,
        'Validator' => Illuminate\Support\Facades\Validator::class,
        'View' => Illuminate\Support\Facades\View::class,

    ],

Используйте spl_autoload_register(...) Обработка загрузки классов, Координация class_alias() Предоставление вызовов псевдонимов классов

Фасад Класс внешнего вида зависимость от базового класса Методы вызова _ callStatic (создание экземпляров соответствующих классов с использованием контейнеров служб)

5. Регистрация поставщиков услуг\Illuminate\Foundation\Bootstrap\RegisterProviders::класс

от app.провайдеров Прочитайте всех поставщиков услуг

'providers' => [

        /*
         * Laravel Framework Service Providers...
         */
        Illuminate\Auth\AuthServiceProvider::class,
        Illuminate\Broadcasting\BroadcastServiceProvider::class,
        Illuminate\Bus\BusServiceProvider::class,
        Illuminate\Cache\CacheServiceProvider::class,
        Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
        Illuminate\Cookie\CookieServiceProvider::class,
        Illuminate\Database\DatabaseServiceProvider::class,
        Illuminate\Encryption\EncryptionServiceProvider::class,
        Illuminate\Filesystem\FilesystemServiceProvider::class,
        Illuminate\Foundation\Providers\FoundationServiceProvider::class,
        Illuminate\Hashing\HashServiceProvider::class,
        Illuminate\Mail\MailServiceProvider::class,
        Illuminate\Notifications\NotificationServiceProvider::class,
        Illuminate\Pagination\PaginationServiceProvider::class,
        Illuminate\Pipeline\PipelineServiceProvider::class,
        Illuminate\Queue\QueueServiceProvider::class,
        Illuminate\Redis\RedisServiceProvider::class,
        Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
        Illuminate\Session\SessionServiceProvider::class,
        Illuminate\Translation\TranslationServiceProvider::class,
        Illuminate\Validation\ValidationServiceProvider::class,
        Illuminate\View\ViewServiceProvider::class,

        /*
         * Package Service Providers...
         */

        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App Providers RouteService Provider:: class,  routing table generation
    ],

После анализа поставщики услуг делятся на три типа поставщиков услуг:

  • Нетерпеливый тип

    Звоните немедленно зарегистрируйтесь зарегистрируйтесь

  • Отложенный тип

    Запишите, что соответствующий поставщик услуг зарегистрирован только тогда, когда контейнер службы анализирует соответствующую службу

  • Когда тип

    Запишите регистрацию соответствующего поставщика услуг, когда запускается соответствующее событие

6. Запустите поставщика\Осветите\Фундамент\Загрузчик\Загрузчики::класс

Вызов контейнера службы boot() Метод, вызываемый по очереди в контейнере службы регистрация всех поставщиков услуг boot() Метод

3.2 Запрос На Обработку Маршрутизации

В ядре экземпляр запроса обрабатывается через промежуточное программное обеспечение, и запрос передается маршрутизатору для распространения.

Ядро Http

protected function dispatchToRouter()
{
    return function ($request) {
        $this->app->instance('request', $request);

        return $this->router->dispatch($request);
    };
}

Описание структуры хранилища таблиц маршрутизации

Осветить\Маршрутизацию\Маршрут Единая маршрутизация хранилища

Осветить\Маршрутизацию\Коллекцию маршрутов Сохранить все Маршрут Примеры для формирования таблиц маршрутизации

Осветите\Маршрутизацию\Маршрутизатор Запасы экземпляров классов Коллекцию маршрутов Экземпляр таблицы маршрутизации.

То есть один Маршрутизатор Удерживающий один Сбор маршрутов И Коллекция маршрутов Есть N Маршрут

оставайтесь Маршрутизатор Обработка запросов также проходит через ряд промежуточного программного обеспечения Маршрутизации

# Storage of routing processing requests
public function dispatchToRoute(Request $request)
{
    return $this->runRoute($request, $this->findRoute($request));
}

# Find the corresponding route based on the requested URL and method
protected function findRoute($request)
{
    $this->current = $route = $this->routes->match($request);

    $this->container->instance(Route::class, $route);

    return $route;
}

# Returns the corresponding $response based on the corresponding request and routing entry
protected function runRoute(Request $request, Route $route)
{
    $request->setRouteResolver(function () use ($route) {
        return $route;
    });

    $this->events->dispatch(new Events\RouteMatched($route, $request));

    return $this->prepareResponse($request,
                                  $this->runRouteWithinStack($route, $request)
                                 );
}

# After the request is filtered by routing middleware, it is handled by run () method of route.
protected function runRouteWithinStack(Route $route, Request $request)
{
    $shouldSkipMiddleware = $this->container->bound('middleware.disable') &&
        $this->container->make('middleware.disable') === true;

    $middleware = $shouldSkipMiddleware ? [] : $this->gatherRouteMiddleware($route);

    return (new Pipeline($this->container))
        ->send($request)
        ->through($middleware)
        ->then(function ($request) use ($route) {
            return $this->prepareResponse(
                $request, $route->run()
            );
        });
}

маршрут метода run() в конечном итоге передает запрос в Осветить\Маршрутизацию\Контроллер диспетчера::отправка Дескриптор

public function dispatch(Route $route, $controller, $method)
{
    $parameters = $this->resolveClassMethodDependencies(
        $route->parametersWithoutNulls(), $controller, $method
    );

    if (method_exists($controller, 'callAction')) {
            return $controller->callAction($method, $parameters);
    }

    return $controller->{$method}(...array_values($parameters));
}

Остальное-контроллер контроллера.

3.3 Обработка возвращенного ответа

оставайтесь Маршрутизатором Есть способ возврата $ответа Обработки

public function prepareResponse($request, $response)
{
    return static::toResponse($request, $response);
}

/**
* @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse
*/
public static function toResponse($request, $response)
{
    if ($response instanceof Responsable) {
        $response = $response->toResponse($request);
    }

    if ($response instanceof PsrResponseInterface) {
        $response = (new HttpFoundationFactory)->createResponse($response);
    } elseif (! $response instanceof SymfonyResponse &&
              ($response instanceof Arrayable ||
               $response instanceof Jsonable ||
               $response instanceof ArrayObject ||
               $response instanceof JsonSerializable ||
               is_array($response))) {
        $response = new JsonResponse($response);
    } elseif (! $response instanceof SymfonyResponse) {
        $response = new Response($response);
    }

    if ($response->getStatusCode() === Response::HTTP_NOT_MODIFIED) {
        $response->setNotModified();
    }

    Return $response - > prepare ($request); final processing
}

В процессе возврата $ответа Окончательная обработка была проведена ранее. $ответ->подготовка($запрос)

Процесс Symfony\Компонент\HttpFoundation\Ответ::подготовка() Выполняется

Инкапсуляция ответа осуществляется через Illuminate\Http\Response Завершение класса, в нижней части которого находится класс ответа платформы Symfony

То есть Symfony\Компонент\HttpFoundation\Ответ

public function prepare(Request $request)
{
    $headers = $this->headers;

    if ($this->isInformational() || $this->isEmpty()) {
        $this->setContent(null);
        $headers->remove('Content-Type');
        $headers->remove('Content-Length');
    } else {
        // Content-type based on the Request
        if (!$headers->has('Content-Type')) {
            $format = $request->getRequestFormat();
            if (null !== $format && $mimeType = $request->getMimeType($format)) {
                $headers->set('Content-Type', $mimeType);
            }
        }

        // Fix Content-Type
        $charset = $this->charset ?: 'UTF-8';
        if (!$headers->has('Content-Type')) {
            $headers->set('Content-Type', 'text/html; charset='.$charset);
        } elseif (0 === stripos($headers->get('Content-Type'), 'text/') && false === stripos($headers->get('Content-Type'), 'charset')) {
            // add the charset
            $headers->set('Content-Type', $headers->get('Content-Type').'; charset='.$charset);
        }

        // Fix Content-Length
        if ($headers->has('Transfer-Encoding')) {
            $headers->remove('Content-Length');
        }

        if ($request->isMethod('HEAD')) {
            // cf. RFC2616 14.13
            $length = $headers->get('Content-Length');
            $this->setContent(null);
            if ($length) {
                $headers->set('Content-Length', $length);
            }
        }
    }

    // Fix protocol
    if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) {
        $this->setProtocolVersion('1.1');
    }

    // Check if we need to send extra expire info headers
    if ('1.0' == $this->getProtocolVersion() && false !== strpos($this->headers->get('Cache-Control'), 'no-cache')) {
        $this->headers->set('pragma', 'no-cache');
        $this->headers->set('expires', -1);
    }

    $this->ensureIEOverSSLCompatibility($request);

    return $this;
}

4.1 Отправка Ответа

останься index.php Конец файла ввода предназначен для возврата ответа клиенту

$response->send();

Symfony\Компонент\HttpFoundation\Ответ

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

    if (function_exists('fastcgi_finish_request')) {
        fastcgi_finish_request();
    } elseif (!\in_array(PHP_SAPI, array('cli', 'phpdbg'), true)) {
        static::closeOutputBuffers(0, true);
    }

    return $this;
}

public function sendHeaders()
{
    // headers have already been sent by the developer
    if (headers_sent()) {
        return $this;
    }

    // headers
    foreach ($this->headers->allPreserveCase() as $name => $values) {
        foreach ($values as $value) {
            header($name.': '.$value, false, $this->statusCode);
        }
    }

    // status
    header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode);

    return $this;
}

public function sendContent()
{
    echo $this->content;

    return $this;
}

4.2 Приостановление запроса

останься index.php В конце файла ввода:

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

Все еще возьмите ядро Http в качестве примера:

public function terminate($request, $response)
{
    This - > terminate Middleware ($request, $response); # Middleware abort processing

    $this - > app - > terminate ();  service container's interruption handler
}

protected function terminateMiddleware($request, $response)
{
    $middlewares = $this->app->shouldSkipMiddleware() ? [] : array_merge(
        $this->gatherRouteMiddleware($request),
        $this->middleware
    );

    foreach ($middlewares as $middleware) {
        if (! is_string($middleware)) {
            continue;
        }

        list($name) = $this->parseMiddleware($middleware);

        $instance = $this->app->make($name);

        if (method_exists($instance, 'terminate')) {
            $instance->terminate($request, $response);
        }
    }
}

Промежуточное программное обеспечение здесь относится к промежуточному программному обеспечению, определенному в ядре $промежуточное программное обеспечение Список массивов промежуточного программного обеспечения, исключая промежуточное программное обеспечение маршрутизации.

Laravel 5.1 Примечание. По умолчанию только промежуточное программное обеспечение сеанса содержит функцию завершения()

Применение Функция обработки прерываний в Сервисном контейнере

public function terminate()
{
    foreach ($this->terminatingCallbacks as $terminating) {
        $this->call($terminating);
    }
}