laravel源码学习(1)-从自加载开始

laravel源码学习(1)-从自加载开始 前言 工作一年多,框架用过symfony,thinkphp,laravel.很多时候都只是在用而不了解框架内部的运行,最近在看完《大话设计模式》和《深入php面向对象,模式与实现》之后想将所看到的内容做一个融汇过程.便想到研究框架.laravel框架目前最流行的php框架就是首选.本系列教程主要从框架设计的角度解读laravel.
正文 所有的框架首要要实现的就是自加载,然后用命名空间的方式代替一大堆的require.工作后发现仍有许多php对命名空间,类自加载一窍不通,故而将类自加载作为第一篇
类自加载的实现
在讲原理之前我们先看一下代码
目录

-- test/Test.php -- index.php -- Loader.php

index.php
index();

Loader.php

Test.php

代码解析
上面的代码可以实现最简单的,类自加载.基本原理
  1. 先看index.php spl_autoload_register("Loader::autoload"); 将Loader::autoload注册,作为__autoload的实现.相当于一旦调用类不存在,则会自动调用Loader::autoload函数.
  2. 再看Loader.php 该类下包含autoload函数,这个函数已由1注册,函数仅包含一行代码
require DIR . '/' . str_replace('\\', '/', $class) . '.php';

这段代码将类名,转化为类所在地址,并引入
综合上面两步就可完成类自加载.当然这只是最简单的自加载(仅实现PSR-0部分要求,关于psr感兴趣的同学可以自行搜索).仅能后实现我们自己的代码,对于第三方代码,无法实现.
用laravel的同学一定知道composer,composer当中的类命名空间都是作者提前写好的,我们无需更改引入包的代码,就可以将包内的类直接使用.这里使用的就是PSR-4代码规范.对于规范内容本文不做过多解释.我们开始真正的研究laravel类自加载的代码实现.
  1. 真正的实现,用phpstrom我们可以很多容易的追踪到实现代码是写在autoload_real.php当中
= 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\ComposerStaticInit0fdc2c73177a176dbcd305400c8a4f4e::getInitializer($loader)); } else { // PSR-0标准,设置命名空间对应路径,以便随后自动加载相关类文件 $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { $loader->set($namespace, $path); } // PSR-4标准,设置命名空间对应路径,以便随后自动加载相关类文件 $map = require __DIR__ . '/autoload_psr4.php'; foreach ($map as $namespace => $path) { $loader->setPsr4($namespace, $path); } // 设置类文件路径与类名的对应关系,以便随后自动加载相关类文件(不遵守PSR-0和PSR-4的类) $classMap = require __DIR__ . '/autoload_classmap.php'; if ($classMap) { $loader->addClassMap($classMap); } }// 将loader内的各种类include进来 $loader->register(true); // 加载公有方法如helpers内定义的函数 if ($useStaticLoader) { $includeFiles = Composer\Autoload\ComposerStaticInit0fdc2c73177a176dbcd305400c8a4f4e::$files; } else { $includeFiles = require __DIR__ . '/autoload_files.php'; } foreach ($includeFiles as $fileIdentifier => $file) { composerRequire0fdc2c73177a176dbcd305400c8a4f4e($fileIdentifier, $file); }return $loader; } }function composerRequire0fdc2c73177a176dbcd305400c8a4f4e($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { require $file; $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; } }

简单总结
laravel的类自加载方式分为以下四种:
  1. PRS-0加载-对应的加载文件autoload_namespaces.php
  2. PRS-4加载-对应的加载文件autoload_psr4.php
  3. 不遵守PSR-0与PSR-4类加载-对应的加载文件autoload_classmap.php
  4. 公有方法加载-对应的加载文件autoload_files.php
自定义自动加载方式
自定义加载方式需要在composer.json当中添加
"autoload": { "psr-0" : { "AppPsr0": "apppsr0/" }, "classmap": [ "database/seeds", "database/factories" ], "psr-4": { "App\\": "app/" }, "files" : ["common/util.php"] }

更新完之后需要运行下方命令,命令会更新总结中描述的四个文件
composer dump-autoload

生产环境需要运行下方命令,改命令会将PSR-0和PSR-4加载的文件写入autoload_classmap里,提升加载速度.
composer dump-atoload -o

【laravel源码学习(1)-从自加载开始】具体情况各位可以自行测试一下,而后查看对应文件.接下来笔者也会写一期开发一个composer包的教程,在里面会对这些做一个更加详细的阐述.

    推荐阅读