0

0

PSR-4 实例

php中文网

php中文网

发布时间:2016-08-08 09:28:43

|

1128人浏览过

|

来源于php中文网

原创

以下是一个实现PSR-4规范的例子:

Closure Example

<?php/**
 * 一个具体项目实现的例子.
 * 使用SPL注册了autoload函数之后,以下代码将触发autoload函数从
 * /path/to/project/src/Baz/Qux.php 文件加载
 * FooBarBazQux 类
 *      new FooBarBazQux;
 *      
 * @param string $class The fully-qualified class name.
 * @return void
 */
spl_autoload_register(function($class) {// 项目约定的命名空间前缀$prefix = 'Foo\Bar\';

    // 命名空间前缀的基础目录$base_dir = __DIR__ . '/src/';

    // 这个类是否使用了命名空间前缀?$len = strlen($prefix);
    if (strncmp($prefix, $class, $len) !== 0) {
        // 没有,尝试下个已注册的 autoloaderreturn;
    }

    // 获取相对类名(截取命名空间前缀后剩下的部分)$relative_class = substr($class, $len);

    // 用base目录替换命名空间前缀;// 用目录分隔符替换命名空间分隔符;// 坠上 .php$file = $base_dir . str_replace('\', '/', $relative_class) . '.php';

    // 如果文件存在,加载文件。if (file_exists($file)) {
        require$file;
    }
});

Class Example

以下是一个处理多命名空间的类的例子。

多功能的日期时间选择器实例
多功能的日期时间选择器实例

日期时间选取,日历表格,日期选择器,日期选择

下载
<?phpnamespaceExample;

/**
 * 这个例子是一个针对 一个命名空间前缀对应多个base谬的通用实现。
 * 
 * foo-bar 类的包分别在以下路径下...
 * 
 *     /path/to/packages/foo-bar/
 *         src/
 *             Baz.php             # FooBarBaz
 *             Qux/
 *                 Quux.php        # FooBarQuxQuux
 *         tests/
 *             BazTest.php         # FooBarBazTest
 *             Qux/
 *                 QuuxTest.php    # FooBarQuxQuuxTest
 * 
 * ... 以下代码将类文件的路径添加到 FooBar命名空间前缀下。
 * 
 *      <?php
 *      // 初始化 loader
 *      $loader = new ExamplePsr4AutoloaderClass;
 *      
 *      // 注册 autoloader
 *      $loader->register();
 *      
 *      // 为命名空间前缀注册base目录。
 *      $loader->addNamespace('FooBar', '/path/to/packages/foo-bar/src');
 *      $loader->addNamespace('FooBar', '/path/to/packages/foo-bar/tests');
 * 
 * 下面的代码将触发 autoloader 尝试从
 * /path/to/packages/foo-bar/src/Qux/Quux.php 加载
 * FooBarQuxQuux 类:
 * 
 *      <?php
 *      new FooBarQuxQuux;
 * 
 * 以下代码触发autoloader尝试从
 *  /path/to/packages/foo-bar/tests/Qux/QuuxTest.php
 * 加载FooBarQuxQuuxTest类 :
 * 
 *      <?php
 *      new FooBarQuxQuuxTest;
 */classPsr4AutoloaderClass
{/**
     * An associative array where the key is a namespace prefix and the value
     * is an array of base directories for classes in that namespace.
     *
     * @var array
     */protected$prefixes = array();

    /**
     * Register loader with SPL autoloader stack.
     * 
     * @return void
     */publicfunctionregister()
    {
        spl_autoload_register(array($this, 'loadClass'));
    }

    /**
     * Adds a base directory for a namespace prefix.
     *
     * @param string $prefix The namespace prefix.
     * @param string $base_dir A base directory for class files in the
     * namespace.
     * @param bool $prepend If true, prepend the base directory to the stack
     * instead of appending it; this causes it to be searched first rather
     * than last.
     * @return void
     */publicfunctionaddNamespace($prefix, $base_dir, $prepend = false)
    {// normalize namespace prefix$prefix = trim($prefix, '\') . '\';

        // normalize the base directory with a trailing separator$base_dir = rtrim($base_dir, DIRECTORY_SEPARATOR) . '/';

        // initialize the namespace prefix arrayif (isset($this->prefixes[$prefix]) === false) {
            $this->prefixes[$prefix] = array();
        }

        // retain the base directory for the namespace prefixif ($prepend) {
            array_unshift($this->prefixes[$prefix], $base_dir);
        } else {
            array_push($this->prefixes[$prefix], $base_dir);
        }
    }

    /**
     * Loads the class file for a given class name.
     *
     * @param string $class The fully-qualified class name.
     * @return mixed The mapped file name on success, or boolean false on
     * failure.
     */publicfunctionloadClass($class)
    {// the current namespace prefix$prefix = $class;

        // work backwards through the namespace names of the fully-qualified// class name to find a mapped file namewhile (false !== $pos = strrpos($prefix, '\')) {

            // retain the trailing namespace separator in the prefix$prefix = substr($class, 0, $pos + 1);

            // the rest is the relative class name$relative_class = substr($class, $pos + 1);

            // try to load a mapped file for the prefix and relative class$mapped_file = $this->loadMappedFile($prefix, $relative_class);
            if ($mapped_file) {
                return$mapped_file;
            }

            // remove the trailing namespace separator for the next iteration// of strrpos()$prefix = rtrim($prefix, '\');   
        }

        // never found a mapped filereturnfalse;
    }

    /**
     * Load the mapped file for a namespace prefix and relative class.
     * 
     * @param string $prefix The namespace prefix.
     * @param string $relative_class The relative class name.
     * @return mixed Boolean false if no mapped file can be loaded, or the
     * name of the mapped file that was loaded.
     */protectedfunctionloadMappedFile($prefix, $relative_class)
    {// are there any base directories for this namespace prefix?if (isset($this->prefixes[$prefix]) === false) {
            returnfalse;
        }

        // look through base directories for this namespace prefixforeach ($this->prefixes[$prefix] as$base_dir) {

            // replace the namespace prefix with the base directory,// replace namespace separators with directory separators// in the relative class name, append with .php$file = $base_dir
                  . str_replace('\', '/', $relative_class)
                  . '.php';

            // if the mapped file exists, require itif ($this->requireFile($file)) {
                // yes, we're donereturn$file;
            }
        }

        // never found itreturnfalse;
    }

    /**
     * If a file exists, require it from the file system.
     * 
     * @param string $file The file to require.
     * @return bool True if the file exists, false if not.
     */protectedfunctionrequireFile($file)
    {if (file_exists($file)) {
            require$file;
            returntrue;
        }
        returnfalse;
    }
}

Unit Tests

The following example is one way of unit testing the above class loader:

<?phpnamespaceExampleTests;

classMockPsr4AutoloaderClassextendsPsr4AutoloaderClass
{protected$files = array();

    publicfunctionsetFiles(array $files)
    {$this->files = $files;
    }

    protectedfunctionrequireFile($file)
    {return in_array($file, $this->files);
    }
}

classPsr4AutoloaderClassTestextends PHPUnit_Framework_TestCase
{protected$loader;

    protectedfunctionsetUp()
    {$this->loader = new MockPsr4AutoloaderClass;

        $this->loader->setFiles(array(
            '/vendor/foo.bar/src/ClassName.php',
            '/vendor/foo.bar/src/DoomClassName.php',
            '/vendor/foo.bar/tests/ClassNameTest.php',
            '/vendor/foo.bardoom/src/ClassName.php',
            '/vendor/foo.bar.baz.dib/src/ClassName.php',
            '/vendor/foo.bar.baz.dib.zim.gir/src/ClassName.php',
        ));

        $this->loader->addNamespace(
            'FooBar',
            '/vendor/foo.bar/src'
        );

        $this->loader->addNamespace(
            'FooBar',
            '/vendor/foo.bar/tests'
        );

        $this->loader->addNamespace(
            'FooBarDoom',
            '/vendor/foo.bardoom/src'
        );

        $this->loader->addNamespace(
            'FooBarBazDib',
            '/vendor/foo.bar.baz.dib/src'
        );

        $this->loader->addNamespace(
            'FooBarBazDibZimGir',
            '/vendor/foo.bar.baz.dib.zim.gir/src'
        );
    }

    publicfunctiontestExistingFile()
    {$actual = $this->loader->loadClass('FooBarClassName');
        $expect = '/vendor/foo.bar/src/ClassName.php';
        $this->assertSame($expect, $actual);

        $actual = $this->loader->loadClass('FooBarClassNameTest');
        $expect = '/vendor/foo.bar/tests/ClassNameTest.php';
        $this->assertSame($expect, $actual);
    }

    publicfunctiontestMissingFile()
    {$actual = $this->loader->loadClass('No_VendorNo_PackageNoClass');
        $this->assertFalse($actual);
    }

    publicfunctiontestDeepFile()
    {$actual = $this->loader->loadClass('FooBarBazDibZimGirClassName');
        $expect = '/vendor/foo.bar.baz.dib.zim.gir/src/ClassName.php';
        $this->assertSame($expect, $actual);
    }

    publicfunctiontestConfusion()
    {$actual = $this->loader->loadClass('FooBarDoomClassName');
        $expect = '/vendor/foo.bar/src/DoomClassName.php';
        $this->assertSame($expect, $actual);

        $actual = $this->loader->loadClass('FooBarDoomClassName');
        $expect = '/vendor/foo.bardoom/src/ClassName.php';
        $this->assertSame($expect, $actual);
    }
}
<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split(' ').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li/>').text(i)); }; $numbering.fadeIn(1700); }); }); </script>

以上就介绍了PSR-4 实例,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

616

2026.02.13

微博网页版主页入口与登录指南_官方网页端快速访问方法
微博网页版主页入口与登录指南_官方网页端快速访问方法

本专题系统整理微博网页版官方入口及网页端登录方式,涵盖首页直达地址、账号登录流程与常见访问问题说明,帮助用户快速找到微博官网主页,实现便捷、安全的网页端登录与内容浏览体验。

194

2026.02.13

Flutter跨平台开发与状态管理实战
Flutter跨平台开发与状态管理实战

本专题围绕Flutter框架展开,系统讲解跨平台UI构建原理与状态管理方案。内容涵盖Widget生命周期、路由管理、Provider与Bloc状态管理模式、网络请求封装及性能优化技巧。通过实战项目演示,帮助开发者构建流畅、可维护的跨平台移动应用。

91

2026.02.13

TypeScript工程化开发与Vite构建优化实践
TypeScript工程化开发与Vite构建优化实践

本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

20

2026.02.13

Redis高可用架构与分布式缓存实战
Redis高可用架构与分布式缓存实战

本专题围绕 Redis 在高并发系统中的应用展开,系统讲解主从复制、哨兵机制、Cluster 集群模式及数据分片原理。内容涵盖缓存穿透与雪崩解决方案、分布式锁实现、热点数据优化及持久化策略。通过真实业务场景演示,帮助开发者构建高可用、可扩展的分布式缓存系统。

54

2026.02.13

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

29

2026.02.12

雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法
雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法

本专题系统整理雨课堂网页版官方入口及在线登录方式,涵盖账号登录流程、官方直连入口及平台访问方法说明,帮助师生用户快速进入雨课堂在线教学平台,实现便捷、高效的课程学习与教学管理体验。

15

2026.02.12

豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法
豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法

本专题汇总豆包AI官方网页版入口及在线使用方式,涵盖智能写作工具、图片生成体验入口和官网登录方法,帮助用户快速直达豆包AI平台,高效完成文本创作与AI生图任务,实现便捷智能创作体验。

598

2026.02.12

PostgreSQL性能优化与索引调优实战
PostgreSQL性能优化与索引调优实战

本专题面向后端开发与数据库工程师,深入讲解 PostgreSQL 查询优化原理与索引机制。内容包括执行计划分析、常见索引类型对比、慢查询优化策略、事务隔离级别以及高并发场景下的性能调优技巧。通过实战案例解析,帮助开发者提升数据库响应速度与系统稳定性。

56

2026.02.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
JavaScript高级框架设计视频教程
JavaScript高级框架设计视频教程

共22课时 | 3.6万人学习

前端系列快速入门课程
前端系列快速入门课程

共4课时 | 0.4万人学习

react hooks实战移动端企业级项目
react hooks实战移动端企业级项目

共59课时 | 6.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号