tp框架中的根命名空间

根命名空间是一个关键的概念,例如 \think\cache\driver\File 类为例, think就是一个根命名空间,其对应的初始命名空间目录就是系统的类库目录( thinkphp/library/think),我们可以简单的理解一个根命名空间对应了一个类库包

分析:

  • /thinkphp/base.php
// 载入Loader类
require __DIR__ . '/library/think/Loader.php';
// 注册自动加载
Loader::register();
  • /thinkphp/library/think/loader.php
 // 注册自动加载机制
    public static function register($autoload = '')
    {
        // 注册命名空间定义
        /*
            获取关联数组:$prefixDirPrs4 = array(
                'think\'=>array('/thinkphp/library/think'),
                'traits\'=>array("/thinkphp/library/traits")
            );

        */
        self::addNamespace([
            'think'  => __DIR__ . '/',
            'traits' => __DIR__ . '/../traits/',
        ]);
    ...


// 注册命名空间
    public static function addNamespace($namespace, $path = '')
    {
        if (is_array($namespace)) {
            foreach ($namespace as $prefix => $paths) {
                //$prefix等于'think\' 和  'traits\'
                //$path 等于'/thinkphp/library/think' 和 "/thinkphp/library/traits"
                self::addPsr4($prefix . '\\', rtrim($paths, DIRECTORY_SEPARATOR), true);
            }
        } else {
            self::addPsr4($namespace . '\\', rtrim($path, DIRECTORY_SEPARATOR), true);
        }
    }
// 添加Psr4空间
    private static function addPsr4($prefix, $paths, $prepend = false)
    {
        if (!$prefix) {
            // Register directories for the root namespace.
            if ($prepend) {
                self::$fallbackDirsPsr4 = array_merge(
                    (array) $paths,
                    self::$fallbackDirsPsr4
                );
            } else {
                self::$fallbackDirsPsr4 = array_merge(
                    self::$fallbackDirsPsr4,
                    (array) $paths
                );
            }
        } elseif (!isset(self::$prefixDirsPsr4[$prefix])) {
            // Register directories for a new namespace.
            //$prefix等于'think\' 和  'traits\'
            //$path 等于'/thinkphp/think' 和 "/thinkphp/traits"
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }

            self::$prefixLengthsPsr4[$prefix[0]][$prefix] = $length;

            self::$prefixDirsPsr4[$prefix]                = (array) $paths;
        } elseif ($prepend) {
            // Prepend directories for an already registered namespace.
            self::$prefixDirsPsr4[$prefix] = array_merge(
                (array) $paths,
                self::$prefixDirsPsr4[$prefix]
            );
        } else {
            // Append directories for an already registered namespace.
            self::$prefixDirsPsr4[$prefix] = array_merge(
                self::$prefixDirsPsr4[$prefix],
                (array) $paths
            );
            /*
                获取关联数组:$prefixDirPrs4 = array(
                    'think\'=>array('/thinkphp/library/think'),
                    'traits\'=>array("/thinkphp/library/traits")
                );
                此时,类库目录和根命名空间绑定
             */
        }
    }

自动加载

分析:

  • /thinkphp/library/think/base.php
 // 注册自动加载机制
    public static function register($autoload = '')
    {
        // 注册系统自动加载
        // spl_autoload_register — 注册给定的函数作为 __autoload 的实现
        spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);
  • 通过命名空间引入类
use think\cache\driver\File;
  • /thinkphp/library/think/load.php
    // 自动加载
    //这时传入$class = 'think\cache\driver\File'
    public static function autoload($class)
    {
        if (isset(self::$classAlias[$class])) {
            return class_alias(self::$classAlias[$class], $class);
        }
        // $file = '/thinkphp/library/think/cache/driver/File.php'
        if ($file = self::findFile($class)) {

            // Win环境严格区分大小写
            // pathinfo() 返回一个关联数组包含有 path 的信息。返回关联数组还是字符串取决于 options。
            if (strpos(PHP_OS, 'WIN') !== false && pathinfo($file, PATHINFO_FILENAME) != pathinfo(realpath($file), PATHINFO_FILENAME)) {
                return false;
            }
            //将绝对路径为"/thinkphp/library/think/cache/driver/File.php"的文件加载进来
            __include_file($file);
            return true;
        }
    }
    ......

    /**
     * 查找文件
     * @access private
     * @param  string $class
     * @return string|false
     */
    //这时传入$class = 'think\cache\driver\File'
    private static function findFile($class)
    {
        // 查找 PSR-4
        // string strtr ( string $str , string $from , string $to ):转换指定字符 
        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . '.php';

        $first = $class[0];
        if (isset(self::$prefixLengthsPsr4[$first])) {
            foreach (self::$prefixLengthsPsr4[$first] as $prefix => $length) {

                if (0 === strpos($class, $prefix)) {
                    foreach (self::$prefixDirsPsr4[$prefix] as $dir) {
                        if (is_file($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
                        //返回$file = "/thinkphp/library/think/cache/driver/File.php"
                            return $file;
                        }
                    }
                }
            }
        }

        // 查找 PSR-4 fallback dirs
        foreach (self::$fallbackDirsPsr4 as $dir) {
            if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
                return $file;
            }
        }
    }
    ...

    /**
     * 作用范围隔离
     *
     * @param $file
     * @return mixed
     */
    function __include_file($file)
    {
        return include $file;
    }

你可能感兴趣的:(tp框架)