Home  >  Article  >  Backend Development  >  Analysis of automatic loading of flight source code in PHP micro-framework

Analysis of automatic loading of flight source code in PHP micro-framework

不言
不言Original
2018-07-23 10:40:351868browse

这篇文章给大家分享的内容是关于php微框架中flight源码的自动加载的解析,有一定的参考价值,有需要的朋友可以参考一下。

先来看下框架的单入口文件index.php,先引入了Flight.php框架类文件。

<?php
require &#39;flight/Flight.php&#39;;
Flight::route(&#39;/&#39;, function(){
    echo &#39;hello world!&#39;;
});
Flight::start();

Flight.php中定义了Flight类,类里面先定义了3个魔术方法,这三个魔术方法是为了防止当前类被实例化

// Don&#39;t allow object instantiation
private function __construct() {}
private function __destruct() {}
private function __clone() {}

如果试着去new Flight会提示如下错误:

Fatal error: Uncaught Error: Call to private Flight::__construct() from invalid context in /usr/local/var/www/flight135/index.php:3 Stack trace: #0 {main} Next Error: Call to private Flight::__destruct() from context &#39;&#39; in /usr/local/var/www/flight135/index.php:3 Stack trace: #0 {main} thrown in /usr/local/var/www/flight135/index.php on line 3

接着定义了一个重载方法__callStatic(),在index.php中执行Flight::route('/', 'hello')就会调用该__callStatic,其中$name就是'route',$params就是自己写的hello函数。在__callStatic()中调用了当前类的app()静态方法,这里为什么不使用self::app()来调用呢?

/**
 * Handles calls to static methods.
 *
 * @param string $name Method name
 * @param array $params Method parameters
 * @return mixed Callback results
 * @throws \Exception
 */
public static function __callStatic($name, $params) {
    $app = Flight::app();
    return \flight\core\Dispatcher::invokeMethod(array($app, $name), $params);
}

接着就是在static app()中开始处理自动加载了

/**
 * @return \flight\Engine Application instance
 */
public static function app() {
    static $initialized = false;
    if (!$initialized) {
        require_once __DIR__.&#39;/autoload.php&#39;;
        self::$engine = new \flight\Engine();
        $initialized = true;
    }
    return self::$engine;
}

进入到autoload.php来看,引入了core目录下的Loader.php类文件,Loader就是加载器。

autoload.php
require_once __DIR__.&#39;/core/Loader.php&#39;;
\flight\core\Loader::autoload(true, dirname(__DIR__));

Loader中定义了加载存放哪些类型:$classes(类路径数组),$instances(对象数组),$dirs(框架目录路径数组)

/**
 * Registered classes.
 *
 * @var array
 */
protected $classes = array();
/**
 * Class instances.
 *
 * @var array
 */
protected $instances = array();
/**
 * Autoload directories.
 *
 * @var array
 */
protected static $dirs = array();

autoload()中使用spl_autoload_register将当前类(__CLASS__)中的loadClass方法注册为加载的执行方法。

/**
 * Starts/stops autoloader.
 *
 * @param bool $enabled Enable/disable autoloading
 * @param array $dirs Autoload directories
 */
public static function autoload($enabled = true, $dirs = array()) {
    if ($enabled) {
        spl_autoload_register(array(__CLASS__, &#39;loadClass&#39;));
    }
    else {
        spl_autoload_unregister(array(__CLASS__, &#39;loadClass&#39;));
    }
    if (!empty($dirs)) {
        self::addDirectory($dirs);
    }
}

/**
 * Autoloads classes.
 *
 * @param string $class Class name
 */
public static function loadClass($class) {
    $class_file = str_replace(array(&#39;\\&#39;, &#39;_&#39;), &#39;/&#39;, $class).&#39;.php&#39;;
    foreach (self::$dirs as $dir) {
        $file = $dir.&#39;/&#39;.$class_file;
        if (file_exists($file)) {
            require $file;
            return;
        }
    }
}

接下来我们试着按照flight自动加载的方式,写个简单的自动加载进行测试:

/autoload/index.php
<?php

class MyClass{
    public static function __callStatic($name, $params){
        self::app();
    }

    public static function app(){
        require_once __DIR__.&#39;/Loader.php&#39;;
        Loader::autoload(true, dirname(__DIR__));

        new \autoload\Test();
    }
}

MyClass::test();
new \autoload\Test2();
var_dump(Loader::getClasses());//array(2) { [0]=> string(36) "/usr/local/var/www/autoload/Test.php" [1]=> string(37) "/usr/local/var/www/autoload/Test2.php" } 

/autoload/Loader.php
<?php
class Loader {
    public static $dirs = [];
    public static $classes = [];

    public static function autoload($enabled=true, $dirs=[]) {
        if ($enabled) {
            spl_autoload_register([__CLASS__, 'loadClass']);
        } else {
            spl_autoload_unregister([__CLASS__, 'loadClass']);
        }
        
        if (!empty($dirs)) {
            self::addDirectory($dirs);
        }
    }

    public static function loadClass($class) {
        $class_file = str_replace(['\\', '_'], '/', $class).'.php';
        
        foreach (self::$dirs as $dir) {
            $file = $dir.'/'.$class_file;
            
            if (file_exists($file)) {
                require $file;
                self::$classes[] = $file;
                
                return;
            }
        }
    }

    public static function addDirectory($dir) {
        if (is_array($dir) || is_object($dir)) {
            foreach ($dir as $value) {
                self::addDirectory($value);
            }
        }
        else if (is_string($dir)) {
            if (!in_array($dir, self::$dirs)) self::$dirs[] = $dir;
        }
    }

    public static function getClasses(){
        return self::$classes;
    }
}

/autoload/Test.php
<?php
namespace autoload;
class Test {}

/autoload/Test2.php
<?php
namespace autoload;
class Test2 {}

x相关推荐:

GoFrame框架的gtime模块和自定义时间格式化语法的分析

Swoft源码之Swoole和Swoft的分析

The above is the detailed content of Analysis of automatic loading of flight source code in PHP micro-framework. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn