最近在使用Laravel
框架,所以分析一下源码是如何设计的。
首先我们可以在Laravel
项目的入口文件看见这些代码。
<?php
/**
* Laravel - A PHP Framework For Web Artisans
*
* @package Laravel
* @author Taylor Otwell <taylor@laravel.com>
*/
define('LARAVEL_START', microtime(true));
/*
|--------------------------------------------------------------------------
| 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.
|
*/
require __DIR__.'/../vendor/autoload.php'; // (1)
/*
|--------------------------------------------------------------------------
| 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.
|
*/
$app = require_once __DIR__.'/../bootstrap/app.php'; // (2)
/*
|--------------------------------------------------------------------------
| 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); // (3)
$response = $kernel->handle( // (4)
$request = Illuminate\Http\Request::capture()
);
$response->send(); //(5)
$kernel->terminate($request, $response); // (6)
这里面我划分了6
个点,分别是:
(1)类加载
(2)应用实体类初始化
(3)绑定http
或者console
内核
(4)请求处理
(5)结果返回客户端
(6)结束请求后的处理操作
这次分析的是类加载。
程序第一次请求,我们会进入autoload.php
文件
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit859fdbc36eb6d63b36031b6c1db7e16b::getLoader();
这里面autoload_real.php
是重点,这个类基本上在composer
中起了入口文件的功能。它将所有的功能都汇总在一起。ComposerAutoloaderInit859fdbc36eb6d63b36031b6c1db7e16b::getLoader()
这个就是autooad_real.php
的类,这里为什么会用这么奇怪的名字?因为这是一个全局的类,为了不让其他程序员写出相同的名字,所以添加上一串哈希值。然后我们看看getLoader
到底是在干什么的?
public static function getLoader()
{
//单例,防止多次初始化
if (null !== self::$loader) {
return self::$loader;
}
//注册自动加载函数
spl_autoload_register(array('ComposerAutoloaderInit859fdbc36eb6d63b36031b6c1db7e16b', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
//删除自动加载函数
spl_autoload_unregister(array('ComposerAutoloaderInit859fdbc36eb6d63b36031b6c1db7e16b', 'loadClassLoader'));
//检查PHP版本是否大于等于5.6,是就使用静态方法调用
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
//调用闭包函数,类默认引用传递
call_user_func(\Composer\Autoload\ComposerStaticInit859fdbc36eb6d63b36031b6c1db7e16b::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);
//这也是PHP=5.6就直接调用静态变量
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit859fdbc36eb6d63b36031b6c1db7e16b::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
//file文件加载进来
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire859fdbc36eb6d63b36031b6c1db7e16b($fileIdentifier, $file);
}
return $loader;
}
//加载ClassLoader类
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
上面的composer
加载重点其实在$loader->register(true);
这个语句就是文件根据命名空间找到文件的功能。
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*/
public function register($prepend = false)
{
//注册根据命名空间自动加载类文件函数
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
根据上面的注释,很清晰的知道了composer
究竟在干了什么了。然而你或许会疑问那些文件究竟是怎么来的,这里我可以告诉你是在使用composer install
的时候就已经生成好的了。就这样子Laravel
的文件加载就完成了。
如果你还是不懂,那可能就是PHP
基础问题了。可以看看我的PHP
框架开发教程。只要跟着框架自己写一遍之后,你就会发现,其实这里面没什么难以理解的。最主要的还是如何定义命名空间获取目录中的文件问题。而且我的框架开发中的composer
支持或许会对你有些许帮助。