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

具体情况各位可以自行测试一下,而后查看对应文件.接下来笔者也会写一期开发一个composer包的教程,在里面会对这些做一个更加详细的阐述.

你可能感兴趣的:(laravel源码学习(1)-从自加载开始)