laravel的启动过程,也是laravel的核心,对这个过程有一个了解,有助于得心应手的使用框架,希望能对大家有点帮助。
提示:在此之前,最好看一下官方文档,大概知道laravel,再来看这个笔记,这样效果可能会好一点。
统一入口
laravel框架使用了统一入口,入口文件:/public/index.php
<?php
//自动加载文件设置
require __DIR__.'/../bootstrap/autoload.php';
//初始化服务容器(可以查看一下关于‘服务容器’的相关文档)
$app = require_once __DIR__.'/../bootstrap/app.php';
//通过服务容器生成一个kernel类的实例(Illuminate\Contracts\Http\Kernel实际上只是一个接口,真正生成的实例是App\Http\Kernel类,至于怎么把接口和类关联起来,请查看Contracts相关文档)
$kernel = $app->make('Illuminate\Contracts\Http\Kernel');
//运行Kernel类的handle方法,主要动作是运行middleware和启动URL相关的Contrller
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
//控制器返回结果之后的操作,暂时还没看,以后补上
$response->send();
kernel->terminate(
kernel−>terminate(request, $response);
自动加载文件
laravel的自动加载,其实也就是Composer的自动加载
我的理解是,Composer根据声明的依赖关系,从相关库的源下载代码文件,并根据依赖关系在 Composer 目录下生成供类自动加载的 PHP 脚本,使用的时候,项目开始处引入 “/vendor/autoload.php” 文件,就可以直接实例化这些第三方类库中的类了。
那么,Composer 是如何实现类的自动加载的呢?接下来,我们从 laravel 的入口文件开始顺藤摸瓜往里跟进,来一睹 Composer 自动加载的奥妙。
代码:/bootstrap/autoload.php
<?php
define('LARAVEL_START', microtime(true));
//这就是传说中Composer的自动加载文件
require __DIR__.'/../vendor/autoload.php';
//Composer自动生成的各个核心类的集合,如果你需要修改一些vendor里面的文件来查看一些laravel运行细节,那么就请删除此文件
$compiledPath = __DIR__.'/../vendor/compiled.php';
if (file_exists($compiledPath))
{
require $compiledPath;
}
代码: laravel/vendor/autoload.php
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer' . '/autoload_real.php';
//别被吓到了,他就是autoload_real.php文件的类名而已
return ComposerAutoloaderInit03dc6c3c47809c398817ca33ec5f6a01::getLoader();
代码:laravel/vendor/composer/autoload_real.php
主要是getLoader方法里面,加了注释的几行,这是关键
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit03dc6c3c47809c398817ca33ec5f6a01
{
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;
}
spl_autoload_register(array('ComposerAutoloaderInit03dc6c3c47809c398817ca33ec5f6a01', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit03dc6c3c47809c398817ca33ec5f6a01', 'loadClassLoader'));
$includePaths = require __DIR__ . '/include_paths.php';
array_push($includePaths, get_include_path());
set_include_path(join(PATH_SEPARATOR, $includePaths));
//Psr0标准-设置命名空间对应的路径,以便于随后自动加载相关类文件(看看psr0和psr4的区别)
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
//Psr4标准-设置命名空间对应的路径,以便于随后自动加载相关类文件(看看psr0和psr4的区别)
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
//设置类文件路径与类名的对应关系,以便于随后自动加载相关类文件(可能你有一部分类,由于历史原因,他们的命名空间不遵守PSR0和PSR4,你就可以使用此方法自动加载)
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
//根据上述三种方法注册自动加载文档的方法,可以查看一下PHP的spl_autoload_register和__autoload方法
$loader->register(true);
//加载公用方法,比如app()方法取得一个application实例,就是这里加载的,可以查看一下autoload_files.php文件都加载了什么公用方法,有很多关于 array的操作方法哦
$includeFiles = require __DIR__ . '/autoload_files.php';
foreach ($includeFiles as $file) {
composerRequire03dc6c3c47809c398817ca33ec5f6a01($file);
}
return $loader;
}
}
function composerRequire03dc6c3c47809c398817ca33ec5f6a01($file)
{
require $file;
}
对于laravel自动加载过程的总结
laravel自动加载的过程就是这样实现的,总结为四种加载方式:
PSR0加载方式—对应的文件就是autoload_namespaces.php
PSR4加载方式—对应的文件就是autoload_psr4.php
其他加载类的方式—对应的文件就是autoload_classmap.php
加载公用方法—对应的文件就是autoload_files.php
怎么样自定义自动加载方式
如果某些文件,需要自动自定义加载方式,可以在Composer.json文件中定义
"autoload" : {
//以第一种方式自动加载,表示app目录下的所有类的命名空间都是以Apppsr0开始且遵循psr0规范(注意:您的laravel中没有此项,作为示意例子)
"psr-0" : {
"AppPsr0": "apppsr0/"
},
//以第二种方式自动加载,表示app目录下的所有类的命名空间都是以App开始且遵循psr4规范
"psr-4" : {
"App\\": "app/"
},
//以第三种加载方式自动加载,它会将所有.php和.inc文件中的类提出出来然后以类名作为key,类的路径作为值
"classmap" : ["database"],
//以第四种加载方式自动加载,composer会把这些文件都include进来(注意:您的laravel中没有此项,作为示意例子)
"files" : ["common/util.php"]
}