이 글은 Laravel의 작동 방식을 완전히 이해하는 데 도움이 될 것입니다!
튜토리얼 칼럼에서 Laravel의 실행 원리를 소개하는 내용입니다. 도움이 필요한 친구들에게 도움이 되길 바랍니다! 머리말
알다시피, 프레임워크를 처음 접할 때 대부분의 사람들은 특정 기본 지식이 없으면 구현 방법을 모릅니다. , 프레임워크의 소스 코드로 이동하면 바로 종료할 수 있습니다. Laravel
프레임워크는 매우 뛰어난 PHP
프레임워크입니다. 인터뷰를 준비할 수 있도록 프레임워크의 작동 원리를 철저히 이해하세요. 그 과정에서 약간의 대화(자랑)가 있습니다. 우수한 프레임워크의 소스 코드를 배우고 연구하는 것도 우리 자신의 기술을 향상시키는 데 도움이 될 것입니다. 벨트, 숙련된 운전자가 곧 운전을 시작합니다! ! !
지식 준비Laravel
框架是一款非常优秀的 PHP
框架,这篇文章就是带你彻底搞懂框架的运行原理,好让你在面试的过程中有些谈资(吹牛),学习和研究优秀框架的源码也有助于我们自身技术的提升,接下来系好安全带,老司机要开始开车了!!!
准备知识
- 熟悉 php 基本知识,如常见的数组方法,闭包函数的使用,魔术方法的使用
- 熟悉 php 的反射机制和依赖注入
- 熟悉 php 命名空间概念和 compose 自动加载
- 熟悉常见的设计模式,包括但是不限于单例模式,工厂模式,门面模式,注册树模式,装饰者模式等
运行原理概述
Laravel
框架的入口文件 index.php
1、引入自动加载 autoload.php
文件
2、创建应用实例,并同时完成了
基本绑定($this、容器类Container等等)、 基本服务提供者的注册(Event、log、routing)、 核心类别名的注册(比如db、auth、config、router等)
3、开始 Http
请求的处理
make 方法从容器中解析指定的值为实际的类,比如 $app->make(Illuminate\Contracts\Http\Kernel::class); 解析出来 App\Http\Kernel handle 方法对 http 请求进行处理 实际上是 handle 中 sendRequestThroughRouter 处理 http 的请求 首先,将 request 绑定到共享实例 然后执行 bootstarp 方法,运行给定的引导类数组 $bootstrappers,这里是重点,包括了加载配置文件、环境变量、服务提供者、门面、异常处理、引导提供者等 之后,进入管道模式,经过中间件的处理过滤后,再进行用户请求的分发 在请求分发时,首先,查找与给定请求匹配的路由,然后执行 runRoute 方法,实际处理请求的时候 runRoute 中的 runRouteWithinStack 最后,经过 runRouteWithinStack 中的 run 方法,将请求分配到实际的控制器中,执行闭包或者方法,并得到响应结果
4、 将处理结果返回
详细源码分析
1、注册自动加载类,实现文件的自动加载
require __DIR__.'/../vendor/autoload.php';
2、创建应用容器实例 Application
(该实例继承自容器类 Container
),并绑定核心(web、命令行、异常),方便在需要的时候解析它们
$app = require_once __DIR__.'/../bootstrap/app.php';
app.php
文件如下:
<?php // 创建Laravel实例 【3】 $app = new Illuminate\Foundation\Application( $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__) ); // 绑定Web端kernel $app->singleton( Illuminate\Contracts\Http\Kernel::class, App\Http\Kernel::class); // 绑定命令行kernel $app->singleton( Illuminate\Contracts\Console\Kernel::class, App\Console\Kernel::class); // 绑定异常处理 $app->singleton( Illuminate\Contracts\Debug\ExceptionHandler::class, App\Exceptions\Handler::class); // 返回应用实例 return $app;
3、在创建应用实例(Application.php
)的构造函数中,将基本绑定注册到容器中,并注册了所有的基本服务提供者,以及在容器中注册核心类别名
3.1、将基本绑定注册到容器中
/** * Register the basic bindings into the container. * * @return void */ protected function registerBaseBindings() { static::setInstance($this); $this->instance('app', $this); $this->instance(Container::class, $this); $this->singleton(Mix::class); $this->instance(PackageManifest::class, new PackageManifest( new Filesystem, $this->basePath(), $this->getCachedPackagesPath() )); # 注:instance方法为将...注册为共享实例,singleton方法为将...注册为共享绑定 }
3.2、注册所有基本服务提供者(事件,日志,路由)
protected function registerBaseServiceProviders() { $this->register(new EventServiceProvider($this)); $this->register(new LogServiceProvider($this)); $this->register(new RoutingServiceProvider($this)); }
3.3、在容器中注册核心类别名
4、上面完成了类的自动加载、服务提供者注册、核心类的绑定、以及基本注册的绑定
5、开始解析 http
的请求
index.php //5.1 $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); //5.2 $response = $kernel->handle( $request = Illuminate\Http\Request::capture());
5.1、make方法是从容器解析给定值
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); 中的Illuminate\Contracts\Http\Kernel::class 是在index.php 中的$app = require_once __DIR__.'/../bootstrap/app.php';这里面进行绑定的,实际指向的就是App\Http\Kernel::class这个类
5.2、这里对 http 请求进行处理
$response = $kernel->handle( $request = Illuminate\Http\Request::capture());
进入 $kernel
所代表的类 AppHttpKernel.php
中,我们可以看到其实里面只是定义了一些中间件相关的内容,并没有 handle 方法
我们再到它的父类 use IlluminateFoundationHttpKernel as HttpKernel
; 中找 handle 方法,可以看到 handle 方法是这样的
public function handle($request){ try { $request->enableHttpMethodParameterOverride(); // 最核心的处理http请求的地方【6】 $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;}
6、处理 Http
请求(将 request
绑定到共享实例,并使用管道模式处理用户请求)
vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php的handle方法// 最核心的处理http请求的地方$response = $this->sendRequestThroughRouter($request);protected function sendRequestThroughRouter($request){ // 将请求$request绑定到共享实例 $this->app->instance('request', $request); // 将请求request从已解析的门面实例中清除(因为已经绑定到共享实例中了,没必要再浪费资源了) Facade::clearResolvedInstance('request'); // 引导应用程序进行HTTP请求 $this->bootstrap();【7、8】 // 进入管道模式,经过中间件,然后处理用户的请求【9、10】 return (new Pipeline($this->app)) ->send($request) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) ->then($this->dispatchToRouter());}
7、在 bootstrap
方法中,运行给定的 引导类数组 $bootstrappers
,加载配置文件、环境变量、服务提供者、门面、异常处理、引导提供者,非常重要的一步,位置在 vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php
/** * Bootstrap the application for HTTP requests. * * @return void */public function bootstrap(){ if (! $this->app->hasBeenBootstrapped()) { $this->app->bootstrapWith($this->bootstrappers()); }}
/** * 运行给定的引导类数组 * * @param string[] $bootstrappers * @return void */public function bootstrapWith(array $bootstrappers){ $this->hasBeenBootstrapped = true; foreach ($bootstrappers as $bootstrapper) { $this['events']->dispatch('bootstrapping: '.$bootstrapper, [$this]); $this->make($bootstrapper)->bootstrap($this); $this['events']->dispatch('bootstrapped: '.$bootstrapper, [$this]); }}/** * Get the bootstrap classes for the application. * * @return array */protected function bootstrappers(){ return $this->bootstrappers;}/** * 应用程序的引导类 * * @var array */protected $bootstrappers = [ // 加载环境变量 \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class, // 加载config配置文件【重点】 \Illuminate\Foundation\Bootstrap\LoadConfiguration::class, // 加载异常处理 \Illuminate\Foundation\Bootstrap\HandleExceptions::class, // 加载门面注册 \Illuminate\Foundation\Bootstrap\RegisterFacades::class, // 加载在config/app.php中的providers数组里所定义的服务【8 重点】 \Illuminate\Foundation\Bootstrap\RegisterProviders::class, // 记载引导提供者 \Illuminate\Foundation\Bootstrap\BootProviders::class,];
8、加载 config/app.php
中的 providers
数组里定义的服务
Illuminate\Auth\AuthServiceProvider::class,Illuminate\Broadcasting\BroadcastServiceProvider::class,....../** * 自己添加的服务提供者 */\App\Providers\HelperServiceProvider::class,
可以看到,关于常用的 Redis、session、queue、auth、database、Route
等服务都是在这里进行加载的
9、使用管道模式处理用户请求,先经过中间件进行处理和过滤
return (new Pipeline($this->app)) ->send($request) // 如果没有为程序禁用中间件,则加载中间件(位置在app/Http/Kernel.php的$middleware属性) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) ->then($this->dispatchToRouter());}
app/Http/Kernel.php
/** * 应用程序的全局HTTP中间件 * * These middleware are run during every request to your application. * * @var array */protected $middleware = [ \App\Http\Middleware\TrustProxies::class, \App\Http\Middleware\CheckForMaintenanceMode::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,];
10、经过中间件处理后,再进行请求分发(包括查找匹配路由)
/** * 10.1 通过中间件/路由器发送给定的请求 * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ protected function sendRequestThroughRouter($request){ ... return (new Pipeline($this->app)) ... // 进行请求分发 ->then($this->dispatchToRouter());}
/** * 10.2 获取路由调度程序回调 * * @return \Closure */protected function dispatchToRouter(){ return function ($request) { $this->app->instance('request', $request); // 将请求发送到应用程序 return $this->router->dispatch($request); };}
/** * 10.3 将请求发送到应用程序 * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse */ public function dispatch(Request $request){ $this->currentRequest = $request; return $this->dispatchToRoute($request);}
/** * 10.4 将请求分派到路由并返回响应【重点在runRoute方法】 * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse */public function dispatchToRoute(Request $request){ return $this->runRoute($request, $this->findRoute($request));}
/** * 10.5 查找与给定请求匹配的路由 * * @param \Illuminate\Http\Request $request * @return \Illuminate\Routing\Route */protected function findRoute($request){ $this->current = $route = $this->routes->match($request); $this->container->instance(Route::class, $route); return $route;}
/** * 10.6 查找与给定请求匹配的第一条路由 * * @param \Illuminate\Http\Request $request * @return \Illuminate\Routing\Route * * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */public function match(Request $request){ // 获取用户的请求类型(get、post、delete、put),然后根据请求类型选择对应的路由 $routes = $this->get($request->getMethod()); // 匹配路由 $route = $this->matchAgainstRoutes($routes, $request); if (! is_null($route)) { return $route->bind($request); } $others = $this->checkForAlternateVerbs($request); if (count($others) > 0) { return $this->getRouteForMethods($request, $others); } throw new NotFoundHttpException;}
到现在,已经找到与请求相匹配的路由了,之后将运行了,也就是 10.4 中的 runRoute 方法
/** * 10.7 返回给定路线的响应 * * @param \Illuminate\Http\Request $request * @param \Illuminate\Routing\Route $route * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse */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) );}
/** * Run the given route within a Stack "onion" instance. * 10.8 在栈中运行路由,先检查有没有控制器中间件,如果有先运行控制器中间件 * * @param \Illuminate\Routing\Route $route * @param \Illuminate\Http\Request $request * @return mixed */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 the route action and return the response. * 10.9 最后一步,运行控制器的方法,处理数据 * @return mixed */ public function run() { $this->container = $this->container ?: new Container; try { if ($this->isControllerAction()) { return $this->runController(); } return $this->runCallable(); } catch (HttpResponseException $e) { return $e->getResponse(); } }
11、运行路由并返回响应(重点)
可以看到,10.7 中有一个方法是 prepareResponse
,该方法是从给定值创建响应实例,而 runRouteWithinStack
方法则是在栈中运行路由,也就是说,http
- 일반적인 배열 메소드, 클로저 함수 사용, 매직 메소드 사용 등 PHP에 대한 기본 지식이 익숙함
- PHP의 리플렉션 메커니즘 및 종속성 주입에 익숙함
- PHP 네임스페이스 개념에 익숙하고 자동 로딩 구성
- 싱글톤 패턴, 팩토리 패턴, 파사드 패턴, 등록 트리 패턴, 데코레이터 패턴을 포함하되 이에 국한되지 않는 일반적인 디자인 패턴에 익숙합니다.
Laravel
프레임워크 index.php
🎜🎜1의 항목 파일 자동 로딩을 소개합니다. autoload.php
파일🎜🎜2. 애플리케이션 인스턴스를 생성하고 동시에 완료합니다🎜rrreee🎜3. Http
요청 처리를 시작합니다🎜rrreee🎜4. 결과🎜🎜🎜🎜상세 소스 코드 분석🎜🎜1. 자동 로딩 클래스를 등록하여 파일 자동 로딩🎜rrreee🎜2. 애플리케이션 컨테이너 인스턴스 Application
을 생성합니다(이 인스턴스는 컨테이너에서 상속됩니다). 클래스 컨테이너
), 필요할 때 구문 분석을 용이하게 하기 위해 코어(웹, 명령줄, 예외)를 바인딩합니다🎜rrreee🎜app.php
파일은 다음과 같습니다.🎜rrreee 🎜3. 애플리케이션 인스턴스(Application.php
) 생성 시 기본 바인딩을 컨테이너에 등록하고, 기본 서비스 제공자를 모두 등록하고, 컨테이너에 핵심 카테고리 이름을 등록합니다🎜🎜3.1. 컨테이너에 기본 바인딩 🎜rrreee🎜3.2. 모든 기본 서비스 제공자(이벤트, 로그, 라우팅) 등록 🎜rrreee🎜3.3. 컨테이너에 핵심 카테고리 이름 등록🎜🎜
http
🎜rrreee🎜5.1의 요청 구문 분석을 시작합니다. make 메소드는 컨테이너🎜rrreee🎜5.2에서 주어진 값을 구문 분석하는 것입니다. http 요청은 여기에서 처리됩니다🎜rrreee🎜 $kernel code>로 표현되는 <code>AppHttpKernel.php
클래스에서는 일부 미들웨어 관련 내용만 정의하고 핸들 메소드는 없다는 것을 알 수 있습니다🎜🎜부모 클래스 IlluminateFoundationHttpKernel을 HttpKernel로 사용하여 핸들 메소드를 찾으면 핸들 메소드가 다음과 같은 것을 볼 수 있습니다🎜rrreee🎜6. code>를 사용하여 인스턴스를 공유하고 파이프라인 모드를 사용하여 사용자 요청 처리) 🎜rrreee🎜7. bootstrap
메서드에서 지정된 부팅 클래스 배열 $bootstrappers
를 실행하고 구성을 로드합니다. 파일 및 환경 변수, 서비스 제공자, 파사드, 예외 처리, 지침 제공자, vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php
🎜rrreeerrreee🎜에 있는 매우 중요한 단계입니다. 8, config/app.php
🎜rrreee🎜의 providers
배열에 정의된 서비스를 로드합니다. 일반적으로 사용되는 Redis, 세션, 대기열, auth, Database, Route
및 기타 서비스는 여기에 로드됩니다🎜🎜9. 파이프라인 모드를 사용하여 미들웨어🎜rrreee🎜app/Http/Kernel.php🎜rrreee🎜10에 의해 먼저 처리되고 필터링됩니다. 미들웨어 처리 후 요청 배포(일치하는 경로 찾기 포함)🎜rrreeerrreeerrreeerrreeerrreeerrreee🎜지금까지는 요청과 일치하는 경로를 찾았으며 나중에 실행될 예정인데, 이는 10.4🎜rrreeerrreeerrreee🎜11의 runRoute 메소드입니다. 응답 반환(강조)보시다시피 10.7에는 주어진 값에서 응답 인스턴스를 생성하는
prepareResponse
메소드와 runRouteWithinStack
이 있습니다. > 방법은 스택에서 라우팅을 실행하는 것입니다. 즉, http
의 요청과 응답이 여기에서 완료됩니다. 🎜요약
글의 가독성을 위해 전체 Laravel
框架的运行流程就分析完毕了,揭开了 Laravel
프레임워크의 미스터리가 드러났습니다. 글과 함께 핵심 코드만 직접 읽어야 합니다. 당신이 배운 준비 지식은 프레임워크의 소스 코드를 읽기 위한 전제이자 기초입니다. ! ! ㅋㅋㅋ
위 내용은 이 글은 Laravel의 작동 방식을 완전히 이해하는 데 도움이 될 것입니다!의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Laravel 9 및 CodeIgniter 4의 최신 버전은 업데이트된 기능과 개선 사항을 제공합니다. Laravel9은 MVC 아키텍처를 채택하여 데이터베이스 마이그레이션, 인증, 템플릿 엔진 등의 기능을 제공합니다. CodeIgniter4는 HMVC 아키텍처를 사용하여 라우팅, ORM 및 캐싱을 제공합니다. 성능면에서는 Laravel9의 서비스 제공자 기반 디자인 패턴과 CodeIgniter4의 경량 프레임워크가 뛰어난 성능을 제공합니다. 실제 애플리케이션에서 Laravel9은 유연성과 강력한 기능이 필요한 복잡한 프로젝트에 적합한 반면, CodeIgniter4는 빠른 개발 및 소규모 애플리케이션에 적합합니다.

Laravel과 CodeIgniter의 데이터 처리 기능을 비교해 보세요. ORM: Laravel은 클래스-객체 관계형 매핑을 제공하는 EloquentORM을 사용하는 반면, CodeIgniter는 데이터베이스 모델을 PHP 클래스의 하위 클래스로 표현하기 위해 ActiveRecord를 사용합니다. 쿼리 빌더: Laravel에는 유연한 체인 쿼리 API가 있는 반면, CodeIgniter의 쿼리 빌더는 더 간단하고 배열 기반입니다. 데이터 검증: Laravel은 사용자 정의 검증 규칙을 지원하는 Validator 클래스를 제공하는 반면, CodeIgniter는 내장된 검증 기능이 적고 사용자 정의 규칙을 수동으로 코딩해야 합니다. 실제 사례: 사용자 등록 예시에서는 Lar를 보여줍니다.

초보자의 경우 CodeIgniter는 학습 곡선이 더 완만하고 기능이 적지만 기본적인 요구 사항을 충족합니다. Laravel은 더 넓은 기능 세트를 제공하지만 학습 곡선이 약간 더 가파릅니다. 성능면에서는 Laravel과 CodeIgniter 모두 좋은 성능을 보입니다. Laravel은 보다 광범위한 문서와 적극적인 커뮤니티 지원을 제공하는 반면 CodeIgniter는 더 간단하고 가벼우며 강력한 보안 기능을 갖추고 있습니다. 블로그 애플리케이션을 구축하는 실제 사례에서 Laravel의 EloquentORM은 데이터 조작을 단순화하는 반면 CodeIgniter는 더 많은 수동 구성이 필요합니다.

대규모 프로젝트를 위한 프레임워크를 선택할 때 Laravel과 CodeIgniter는 각각 고유한 장점을 가지고 있습니다. Laravel은 엔터프라이즈급 애플리케이션을 위해 설계되었으며 모듈식 디자인, 종속성 주입 및 강력한 기능 세트를 제공합니다. CodeIgniter는 속도와 사용 편의성을 강조하여 중소 규모 프로젝트에 더 적합한 경량 프레임워크입니다. 요구 사항이 복잡하고 사용자 수가 많은 대규모 프로젝트의 경우 Laravel의 성능과 확장성이 더 적합합니다. 간단한 프로젝트나 리소스가 제한된 상황에서는 CodeIgniter의 가볍고 빠른 개발 기능이 더 이상적입니다.

Laravel - Artisan Commands - Laravel 5.7은 새로운 명령을 처리하고 테스트하는 새로운 방법을 제공합니다. 여기에는 장인 명령을 테스트하는 새로운 기능이 포함되어 있으며 데모는 아래에 언급되어 있습니다.

소규모 프로젝트의 경우 Laravel은 강력한 기능과 보안이 필요한 대규모 프로젝트에 적합합니다. CodeIgniter는 가볍고 사용하기 쉬운 매우 작은 프로젝트에 적합합니다.

Laravel의 Blade와 CodeIgniter의 Twig 템플릿 엔진을 비교해 보면 프로젝트 요구 사항과 개인 선호도에 따라 선택하십시오. Blade는 MVC 구문을 기반으로 하므로 좋은 코드 구성과 템플릿 상속을 장려합니다. Twig는 유연한 구문, 강력한 필터, 확장된 지원 및 보안 샌드박스를 제공하는 타사 라이브러리입니다.

Laravel - Artisan Console - Laravel 프레임워크는 명령줄을 통한 상호 작용을 위한 세 가지 기본 도구인 Artisan, Ticker 및 REPL을 제공합니다. 이번 장에서는 Artisan에 대해 자세히 설명합니다.
