Laravel框架中Autoloader模块的代码分析

2020-08-13 20:51:37
本篇文章给大家分享的内容是关于Laravel框架中Autoloader模块的代码分析,有一定的参考价值,希望可以帮助到有需要的朋友。

首先是中文注释:

<?php namespace Laravel;class Autoloader {/** * 类名到文件名得映射 * * @var array */public static $mappings = array();/**     * PSR-0命名转换目录 * * @var array */public static $directories = array();/** * 命名空间和目录的映射 * * @var array */public static $namespaces = array();/** * 下划线类库和目录映射 * * @var array */public static $underscored = array();/** * 自动加载类的别名 * * @var array */public static $aliases = array();/** * Load the file corresponding to a given class. * * This method is registered in the bootstrap file as an SPL auto-loader. * * @param  string  $class * @return void */public static function load($class){// 尝试类是否有别名if (isset(static::$aliases[$class])){return class_alias(static::$aliases[$class], $class);}// 查找映射elseif (isset(static::$mappings[$class])){require static::$mappings[$class];return;}// 加载这个新的类foreach (static::$namespaces as $namespace => $directory){            # 支持函数 是否命名空间开头 在helpers.php中if (starts_with($class, $namespace)){return static::load_namespaced($class, $namespace, $directory);}}static::load_psr($class);}/** * 从给定的目录加载命名空间 * * @param  string  $class * @param  string  $namespace * @param  string  $directory * @return void */protected static function load_namespaced($class, $namespace, $directory){return static::load_psr(substr($class, strlen($namespace)), $directory);}/** * 使用PSR-0标准来试图解析一个类 * * @param  string  $class * @param  string  $directory * @return void */protected static function load_psr($class, $directory = null){        // 用PSR-0来解析类 使之变成路径字符串$file = str_replace(array('', '_'), '/', $class);$directories = $directory ?: static::$directories; // 获得类路径$lower = strtolower($file); # 默认全部小写// 尝试解析foreach ((array) $directories as $directory){if (file_exists($path = $directory.$lower.EXT)){return require $path;}elseif (file_exists($path = $directory.$file.EXT)){return require $path;}}}/** * 注册一个数组 包含类路径映射 * * @param  array  $mappings * @return void */public static function map($mappings){static::$mappings = array_merge(static::$mappings, $mappings);}/** * 注册类的别名 * * @param  string  $class * @param  string  $alias * @return void */public static function alias($class, $alias){static::$aliases[$alias] = $class;}/** * 注册目录 * * @param  string|array  $directory * @return void */public static function directories($directory){$directories = static::format($directory);static::$directories = array_unique(array_merge(static::$directories, $directories));}/** * 映射命名空间和目录 * * @param  array   $mappings * @param  string  $append * @return void */public static function namespaces($mappings, $append = ''){$mappings = static::format_mappings($mappings, $append);static::$namespaces = array_merge($mappings, static::$namespaces); # 合并之后: (array "命名空间", array "命名空间","路径")}/** * 注册下划线命名空间 * * @param  array  $mappings * @return void */public static function underscored($mappings){static::namespaces($mappings, '_'); # 下划线风格}/** * 格式目录映射 * * @param  array   $mappings * @param  string  $append * @return array */protected static function format_mappings($mappings, $append){foreach ($mappings as $namespace => $directory){# 清理命名空间$namespace = trim($namespace, $append).$append;unset(static::$namespaces[$namespace]); # 去除之前的 如果存在的话$namespaces[$namespace] = head(static::format($directory)); # 一个命名空间只能对应一个目录}return $namespaces;}/** * 格式化一个目录数组 * * @param  array  $directories * @return array */protected static function format($directories){return array_map(function($directory){return rtrim($directory, DS).DS;# 清理目录}, (array) $directories); // 用map遍历目录数组}}

改类被自动装在到spl中:

spl_autoload_register(array('LaravelAutoloader', 'load')); # spl_autoload_register array 命名空间,具体方法

注册好之后,就载入一些预先设置好的配置:

定义系统root

Autoloader::namespaces(array('Laravel' => path('sys'))); # 定义Laravel系统根目录映射

然后是默认使用的ORM框架

# 定义EloquentORM框架Autoloader::map(array('LaravelDatabaseEloquentRelationshipsBelongs_To'                     => path('sys').'database/eloquent/relationships/belongs_to'.EXT,'LaravelDatabaseEloquentRelationshipsHas_Many'                     => path('sys').'database/eloquent/relationships/has_many'.EXT,'LaravelDatabaseEloquentRelationshipsHas_Many_And_Belongs_To'                     => path('sys').'database/eloquent/relationships/has_many_and_belongs_to'.EXT,'LaravelDatabaseEloquentRelationshipsHas_One'                     => path('sys').'database/eloquent/relationships/has_one'.EXT,'LaravelDatabaseEloquentRelationshipsHas_One_Or_Many'                     => path('sys').'database/eloquent/relationships/has_one_or_many'.EXT,));

随后是Symfony的HTTP组件和Console组件

# Symfony组件加载Autoloader::namespaces(array('SymfonyComponentConsole'                     => path('sys').'vendor/Symfony/Component/Console','SymfonyComponentHttpFoundation'                    => path('sys').'vendor/Symfony/Component/HttpFoundation',));

当然,不要忘记了application.php中的配置

'aliases' => array('Auth'       => 'LaravelAuth','Authenticator' => 'LaravelAuthDriversDriver','Asset'      => 'LaravelAsset','Autoloader' => 'LaravelAutoloader','Blade'      => 'LaravelBlade','Bundle'     => 'LaravelBundle','Cache'      => 'LaravelCache','Config'     => 'LaravelConfig','Controller' => 'LaravelRoutingController','Cookie'     => 'LaravelCookie','Crypter'    => 'LaravelCrypter','DB'         => 'LaravelDatabase','Eloquent'   => 'LaravelDatabaseEloquentModel','Event'      => 'LaravelEvent','File'       => 'LaravelFile','Filter'     => 'LaravelRoutingFilter','Form'       => 'LaravelForm','Hash'       => 'LaravelHash','HTML'       => 'LaravelHTML','Input'      => 'LaravelInput','IoC'        => 'LaravelIoC','Lang'       => 'LaravelLang','Log'        => 'LaravelLog','Memcached'  => 'LaravelMemcached','Paginator'  => 'LaravelPaginator','Profiler'  => 'LaravelProfilingProfiler','URL'        => 'LaravelURL','Redirect'   => 'LaravelRedirect','Redis'      => 'LaravelRedis','Request'    => 'LaravelRequest','Response'   => 'LaravelResponse','Route'      => 'LaravelRoutingRoute','Router'     => 'LaravelRoutingRouter','Schema'     => 'LaravelDatabaseSchema','Section'    => 'LaravelSection','Session'    => 'LaravelSession','Str'        => 'LaravelStr','Task'       => 'LaravelCLITasksTask','URI'        => 'LaravelURI','Validator'  => 'LaravelValidator','View'       => 'LaravelView',),

基本上流程就出来了。

牵扯的重要的文件地址:

laravel/core.php
laravel/autoloader.php
application/config/application.php

配合Ioc,够用了。下次分析一下laravel的Ioc,不过个人感觉功能太少。使用仿spring的Ding更好