PHP头条
热点:

手撸php框架3.1--构建BaseTank类,3.1--basetank


BaseTank类作为我们框架的核心类,会提供组织框架的一系列功能。
其中包括:

1.提供文件路径定义别名的功能
2.提供类自动加载的功能
3.提供创建框架基础对象的功能(使用DI容器提供的功能)

基于以上设想我们设计了BaseTank类的结构:
静态属性:

1. $app:      持有application对象,是一个单例   
2. $classMap: 注册了类的索引,数组键是类名,数组值是对应的类文件路径   
3. $aliasMap: 别名索引,所有注册的别名,在这里体现
4. $container:DI容器,在创建对象时会使用它提供的依赖注入机制

静态方法:

1.提供注册别名的方法:     registerAlias
2.提供解析别名的方法:     parseAlias
3.提供类的自动加载机制:   autoload
4.提供创建对象的方法,基于DI:        generateObject
5.提供给对象属性批量赋值的方法:      batchSetProperty

1.别名的数据结构

['@@root'] => [
    '@@root/aa' => 'p3/p4/p5',
    '@@root' => 'p1/p2',
]

别名以@@作为前缀,@@+开头部分即根部分相同的作为一组,组内按键值倒序排列。
倒序排列会造成在设置别名时,要时刻注意排序。在解析别名时,要遵循最长匹配原则。
起初想使用类似于DFA算法实现关键词过滤类似的方式,但没有做深入探讨,所以使用这种简单的方式来实现。
registerAlias方法:

public static function registerAlias($alias, $filePath = '')
    {
        if (!empty($filePath)) {
            $dirSeparator = static::getDirSeparator();

            if (strncmp($alias, '@@', 2) !== 0) {
                $alias = '@@'.$alias;
            }

            $firstSeparatorPos = strpos($alias, $dirSeparator);

            $isMultipleLayers = $firstSeparatorPos !== false ? true : false;

            $filePathHasAlias = strncmp($filePath, '@@', 2) !== 0 ? false : true;

            $filePath = $filePathHasAlias ? static::parseAlias($filePath) : rtrim($filePath, static::CLASS_SEPARATOR.$dirSeparator);


            if ($isMultipleLayers) {
                $rootNode = substr($alias, 0, $firstSeparatorPos);
            } else {
                $rootNode = $alias;
            }

            if (!isset(static::$aliasMap[$rootNode]) || empty(static::$aliasMap[$rootNode])) {
                static::$aliasMap[$rootNode] = [
                    $alias => $filePath,
                ];
            } else if (is_array(static::$aliasMap[$rootNode])){
                static::$aliasMap[$rootNode][$alias] = $filePath;
                krsort(static::$aliasMap[$rootNode]);
            }
        }
    }

parseAlias方法:

public static function parseAlias($alias)
    {
        if (strncmp($alias, '@@', 2)) {
            return $alias;
        }

        $dirSeparator = static::getDirSeparator();

        $firstSeparatorPos = strpos($alias, $dirSeparator);

        $isMultipleLayers = $firstSeparatorPos !== false ? true : false;

        if ($isMultipleLayers) {
            $rootNode = substr($alias, 0, $firstSeparatorPos);
        } else {
            $rootNode = $alias;
        }

        if (isset(static::$aliasMap[$rootNode]) && !empty(static::$aliasMap[$rootNode])) {
            foreach (static::$aliasMap[$rootNode] as $eachAlias => $eachFilePath) {
                if (strpos($alias . $dirSeparator, $eachAlias . $dirSeparator) === 0) {
                    return $eachFilePath . substr($alias, strlen($eachAlias));
                }
            }
        }
    }

2.类的自动加载
构造autoload方法,该方法现使用classMap匹配路径,然后使用别名解析路径,只有这两种方式才能寻找到某个类所在的文件路径并require到脚本中。
到时把该autoload方法通过spl_autoload_register方法注册到php类自动加载的调用堆栈中即可。
类自动加载方法:

public static function autoload($className)
    {
        $dirSeparator = static::getDirSeparator();
        //备注:框架类的自动加载,交由composer处理.如果不想使用composer处理,必须使用别名机制.
        if (isset(static::$classMap[$className])) {
            $classFilePath = static::$classMap[$className];
            if (strpos($classFilePath, '@@') !== false) {
                $classFilePath = static::parseAlias($classFilePath);
            }
        } else if(strpos($className, static::CLASS_SEPARATOR) !== false) {
            $classFilePath = static::parseAlias('@@' . str_replace(static::CLASS_SEPARATOR, $dirSeparator, $className) . '.php');
            if ($classFilePath === false || !is_file($classFilePath)) {
                return;
            }
        } else {
            return;
        }

        if (isset($classFilePath) && file_exists($classFilePath)) {
            include_once($classFilePath);
        }
    }

3.创建框架基础对象
该功能通过调用container的方法,委托给container完成,到实现container的地方我们再来详解。
创建对象方法:

public static function generateObject()
 {
//此方法实现和container的实现有关,所以到实现container的地方我们再回头实现它
 }

好,欲知下事如何,且听下回分解……
github源码:https://github.com/2lovecode/tank

www.phpzy.comtrue/php/3199.htmlTechArticle手撸php框架3.1--构建BaseTank类,3.1--basetank BaseTank类作为我们框架的核心类,会提供组织框架的一系列功能。 其中包括: 1.提供文件路径定义别名的功能2.提供类自动加载的功能3.提供创建...

相关文章

相关频道:

PHP之友评论

今天推荐