最近在使用
Laravel
架構,是以分析一下源碼是如何設計的。
首先我們可以在
Laravel
項目的入口檔案看見這些代碼。
<?php
/**
* Laravel - A PHP Framework For Web Artisans
*
* @package Laravel
* @author Taylor Otwell <[email protected]>
*/
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
支援或許會對你有些許幫助。