index.php 入口文件
<?php
/**
* Laravel - A PHP Framework For Web Artisans
*
* @package Laravel
* @author Taylor Otwell <taylor@laravel.com>
*/
/*
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader for
| our application. We just need to utilize it! We'll simply require it
| into the script here so that we don't have to worry about manual
| loading any of our classes later on. It feels great to relax.
|
*/
# 自动加载 更多需要配合参考 composer.json 文件 和 源代码
require __DIR__.'/../bootstrap/autoload.php';
/*
|--------------------------------------------------------------------------
| Turn On The Lights
|--------------------------------------------------------------------------
|
| We need to illuminate PHP development, so let us turn on the lights.
| This bootstraps the framework and gets it ready for use, then it
| will load up this application so that we can run it and send
| the responses back to the browser and delight our users.
|
*/
# 框架启动 返回一个 Application 实例对象 (包括注入容器等)
$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.
|
*/
# 从容器中解析http请求实例(聚焦make解析容器实例--反射相关知识)
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
# 处理中间件、路由到控制器、注入服务器提供等操作 返回一个响应实例(这里是启动整个框架最重要地方)
$response = $kernel->handle(
# 请求数据处理 注入$request
$request = Illuminate\Http\Request::capture()
);
# 发送响应到客户端
$response->send();
# 响应结束,调用中间件的terminate方法处理部分事情
$kernel->terminate($request, $response);
自动加载初窥
- 自动加载最主要代码(来自vendor/composer目录下的自动加载文件里)
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit4b1cb372bdf84554786fa050e282ae68
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
# 自动加载首先被调用的方法 (注入自动加载器等)
public static function getLoader()
{
# 如果当前自动加载实例对象已被创建就返回该对象
if (null !== self::$loader) {
return self::$loader;
}
# apl_autoload_register 自动加载器 加载指定类的指定方法(参数一)
# 注入失败抛出异常(参数二)
# 添加到队列之首(参数三)
spl_autoload_register(array('ComposerAutoloaderInit4b1cb372bdf84554786fa050e282ae68', 'loadClassLoader'), true, true);
# 创建一个ClassLoader实例,会调用已注册的loadClassLoader方法加载对应的类文件
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
# 注销自动加载器指定方法
spl_autoload_unregister(array('ComposerAutoloaderInit4b1cb372bdf84554786fa050e282ae68', 'loadClassLoader'));
# 判断当前系统环境
# PHP_VERSION 当前php版本5.6或以上
# 当前是否HHVM中
# zend_loader_file_encoded() 当前文件是否zend加密(就是当前问价是否被编译成二进制码)
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
# 自动加载
if ($useStaticLoader) {
# 引入autoload_static.php 文件
# 该文件主要是管理需要加载类的所在位置的一些配置文件信息
# 部分属性配置由composer install执行时,被追加或写入到指定属性中
require_once __DIR__ . '/autoload_static.php';
# 执行一个回调函数调用(主要:ClassLoader生成的一个实例对象属性添加值)
call_user_func(\Composer\Autoload\ComposerStaticInit4b1cb372bdf84554786fa050e282ae68::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
# 自动加载注册 这里是最核心代码(类的加载参看源码)
$loader->register(true);
# 引入files属性里面的辅助文件 使辅助方法可用
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit4b1cb372bdf84554786fa050e282ae68::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire4b1cb372bdf84554786fa050e282ae68($fileIdentifier, $file);
}
# 上面辅助函数文件引入就能调用app()类型的函数了 虽然里面什么都没有
return $loader;
}
}
function composerRequire4b1cb372bdf84554786fa050e282ae68($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
}
}
- 参看一下ComposerStaticInit4b1cb372bdf84554786fa050e282ae68类文件
# 由于文件数据较多,不做详细粘贴
files 属性:里面存储加载包时,所自定义的一些函数文件(如:laravel自带的辅助函数文件一样)
prefixLengthsPsr4 属性:保存的是一些类文件的命名空间名称(该名称长度大小)
prefixDirsPsr4 属性:保存的是上面命名空间下的一些src文件所在路径
prefixesPsr0 属性:保存的是命名空间和该命名空间下的一些文件src路径
classMap 属性:保存的是类的映射(比如说一些控制器的映射路径等)
启动框架服务
-
$app = require_once __DIR__.'/../bootstrap/app.php'
引入框架文件
- 这里主要注入Application应用类并创建服务器容器,绑定一些服务在容器中
<?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应用实例(参看下面代码,参看构造器创建应用初始化)
$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.
|
*/
# 向容器中注入 Http 请求
$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Http\Kernel::class
);
# 向容器中注入控制台请求(用于 php artisan list 命令使用)
$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;
- Application.php 文件构造器级相关方法
/**
* Create a new Illuminate application instance.
*
* @param string|null $basePath
* @return void
*/
public function __construct($basePath = null)
{
if ($basePath) {
# 绑定一些文件路径到服务器容器(参看源码)
$this->setBasePath($basePath);
}
# 给容器Container注入Application实例对象并返回(Container是一个静态类)
# 绑定app、Container::class到容器为Application实例对象(app()辅助函数可从容器中解析服务)
$this->registerBaseBindings();
# 启动一些基本服务(绑定一些实例在服务器容器中)
# 注册事件队列服务 events 绑定队列在容器
# 注册日志服务 log 绑定日志到容器
# 注册一系列路由服务 绑定路由或重定向或响应或请求到容器中
$this->registerBaseServiceProviders();
# 应用中注入核心类别名(如app、session等别名指向类文件或接口文件|此处并未注册实例对象app('config')这样还是不能从容器中被解析)
$this->registerCoreContainerAliases();
# ~ 这里框架应用实例创建完毕
}
/**
* Resolve the given type from the container.
*
* (Overriding Container::make)
*
* @param string $abstract
* @return mixed
*/
public function make($abstract)
{
# 获取别名
$abstract = $this->getAlias($abstract);
# 是否延迟加载(参看服务提供者延迟加载文档)
if (isset($this->deferredServices[$abstract])) {
# 服务容器注入被延迟加载,在调用服务时执行当前服务提供者的register()方法(先)和boot()方法(后)
$this->loadDeferredProvider($abstract);
}
# 调用父类make()方法 从容器中解析
return parent::make($abstract);
}
/**
* Resolve the given type from the container.
*
* @param string $abstract
* @return mixed
*/
public function make($abstract)
{
return $this->resolve($abstract);
}
/**
* Resolve the given type from the container.
*
* @param string $abstract
* @param array $parameters
* @return mixed
*/
protected function resolve($abstract, $parameters = [])
{
$abstract = $this->getAlias($abstract);
$needsContextualBuild = ! empty($parameters) || ! is_null(
$this->getContextualConcrete($abstract)
);
// If an instance of the type is currently being managed as a singleton we'll
// just return an existing instance instead of instantiating new instances
// so the developer can keep using the same objects instance every time.
if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {
return $this->instances[$abstract];
}
$this->with[] = $parameters;
$concrete = $this->getConcrete($abstract);
// We're ready to instantiate an instance of the concrete type registered for
// the binding. This will instantiate the types, as well as resolve any of
// its "nested" dependencies recursively until all have gotten resolved.
if ($this->isBuildable($concrete, $abstract)) {
# 解析对象 - 使用反射相关知识
$object = $this->build($concrete);
} else {
$object = $this->make($concrete);
}
// If we defined any extenders for this type, we'll need to spin through them
// and apply them to the object being built. This allows for the extension
// of services, such as changing configuration or decorating the object.
foreach ($this->getExtenders($abstract) as $extender) {
$object = $extender($object, $this);
}
// If the requested type is registered as a singleton we'll want to cache off
// the instances in "memory" so we can return it later without creating an
// entirely new instance of an object on each subsequent request for it.
if ($this->isShared($abstract) && ! $needsContextualBuild) {
$this->instances[$abstract] = $object;
}
$this->fireResolvingCallbacks($abstract, $object);
// Before returning, we will also set the resolved flag to "true" and pop off
// the parameter overrides for this build. After those two things are done
// we will be ready to return back the fully constructed class instance.
$this->resolved[$abstract] = true;
array_pop($this->with);
return $object;
}
网友评论