aura / includer
按照顺序从指定的目录中包含多个文件,并将变量提取到有限的包含作用域中。
Requires
- php: >=5.3.0
README
提供从指定目录按顺序包含多个文件的功能,并将变量提取到有限的包含作用域中。
前言
安装
此库需要 PHP 5.3 或更高版本;我们原则上推荐使用最新可用的 PHP 版本。它没有用户空间依赖。
可以通过 Composer 以 aura/includer 的方式安装和自动加载。
或者,下载一个版本 或克隆此存储库,然后要求或包含其 autoload.php 文件。
质量
要在命令行中运行单元测试,请在包根目录中运行 phpunit
。(这需要 PHPUnit 作为 phpunit
可用。)
此库试图遵守 PSR-1、PSR-2 和 PSR-4。如果您注意到遵守疏忽,请通过拉取请求发送补丁。
社区
要提问、提供反馈或与 Aura 社区进行其他沟通,请加入我们的 Google Group、关注 @auraphp on Twitter 或在 Freenode 的 #auraphp 上与我们聊天。
入门
示例场景
假设您有一系列包、模块、插件等。为了执行其设置工作,您的框架或基础需要包含来自这些模块的某些文件,例如配置或路由文件。
在我们的示例中,模块目录结构将如下所示
modules/
foo/
autoload.php
config/
default.php
testing.php
routes.php
bar/
autoload.php
baz/
autoload.php
config/
default.php
一个示例 autoload.php 文件可能如下所示
<?php $loader->addNamespace('Module\Foo', __DIR__); ?>
一个示例配置文件可能如下所示
<?php $config->setValue('db_host', 'localhost'); ?>
一个示例 routes.php 文件可能如下所示
<?php $router->setPath('/blog/read/{id}', function ($id) { // logic for the blog "read" action }); ?>
由于每个文件都使用了共享变量,我们需要它们可用,但同时也希望每个文件都保持与全局作用域的分离。
在包含配置文件时,我们需要 默认 和额外的 "模式",用于覆盖默认值。
如果文件缺失,我们可以跳过它而不会产生不良影响。
完成任务
Includer 使得这种情况以及类似情况相对容易。首先,我们实例化 Includer
<?php use Aura\Includer\Includer; $includer = new Includer; ?>
然后,我们设置需要查看以包含文件的各个目录
<?php $includer->setDirs(array( '/path/to/modules/foo', '/path/to/modules/bar', '/path/to/modules/baz', )); ?>
然后我们设置每个目录中要查找的文件(我们将包括默认配置和覆盖测试配置)
<?php $includer->setFiles(array( 'autoload.php', 'config/default.php', 'config/testing.php', 'routes.php', )); ?>
由于文件需要本地变量,我们首先创建它们,然后将它们提供给包含文件
<?php $loader = new Loader(...); $config = new Config(...); $router = new Router(...); $includer->setVars(array( 'loader' => $loader, 'config' => $config, 'router' => $router, )); ?>
最后,在设置目录、文件和变量后,我们调用 load()
方法
<?php $includer->load(); ?>
这将为每个包含文件创建一个独立的范围,将变量提取到该有限范围中,然后在该有限范围内包含该文件。这意味着除了通过注入的变量外,没有任何包含文件可以影响应用程序的全局状态。
包含顺序
默认情况下,Includer 将按照“目录顺序”包含文件,这由常量 Includer::DIR_ORDER
表示。这意味着 Includer 首先访问第一个目录并尝试加载该目录中标记的所有文件,然后继续到下一个目录。根据上述示例,Includer::DIR_ORDER
的加载顺序如下:
# first dir
modules/foo/autoload.php
modules/foo/config/default.php
modules/foo/config/testing.php
modules/foo/routes.php
# second dir
modules/bar/autoload.php
# third dir
modules/baz/autoload.php
modules/baz/config/default.php
或者,您可以通过指定 load(Includer::FILE_ORDER)
来按“文件顺序”加载文件。这意味着加载器尝试加载每个目录中的第一个文件,然后是第二个文件,依此类推。根据上述示例,Includer::FILE_ORDER
的加载顺序如下:
# first file
modules/foo/autoload.php
modules/bar/autoload.php
modules/baz/autoload.php
# second file
modules/foo/config/default.php
modules/baz/config/default.php
# third file
modules/foo/config/testing.php
# fourth file
modules/foo/routes.php
严格处理
默认情况下,Includer 对它实际包含的路径组合相对严格。它将使用 realpath() 将目录 + 文件路径转换为绝对路径,然后检查该绝对路径是否与 Includer 中指定的目录相同。(这是因为可以使用 ../
和符号链接来指向指定目录之外的文件位置。)不可读的文件或位于指定目录之外的文件将不会被包含。
这种处理方式有时过于严格;例如,如果您使用符号链接,严格的处理可能会排除这些文件。要关闭严格处理,并且只检查文件是否可读,请调用 setStrict(false)
。
<?php // turn off strict processing $includer->setStrict(false); ?>
通配符
在内部,Includer 使用 glob() 来查找文件。这意味着您可以在文件名中使用通配符来包含文件。
<?php // load all '.php' files in each of the directories $includer->addFiles(array( 'config/*.php', 'routes/*.php' ); ?>
缓存文件
如果您有数十个或更多的文件需要包含,那么这么多的文件系统活动可能会导致性能下降。为了减轻这种情况,缓存将要包含的文件可能很有用。
Includer 有一个 read()
方法来获取将要包含的文件的 内容并连接它们,然后为您返回连接后的内容以便您将其缓存在您选择的文件中。然后,您可以将 Includer 指向该缓存文件;如果它存在,Includer 将使用该文件而不是包含不同的目录和文件路径组合。
首先,我们使用 read()
方法获取连接文件的文本。默认情况下,它将按照 Includer::DIR_ORDER
连接文件,但您也可以指定 read(Includer::FILE_ORDER)
如果您愿意的话。
<?php $text = $includer->read(); ?>
read()
方法将获取每个文件的 内容,对其进行修剪,删除任何前导和尾随的 <?php ?>
标签,将 __FILE__
常量替换为其等效的字符串文件名,并将 __DIR__
常量替换为其等效的字符串目录名。(这些替换反映了代码是从原始位置复制到新位置的事实,而常量期望的是原始位置的值。)
现在我们已经有了文件的 内容,我们添加一个开头的 <?php
标签和创建它的时间,然后将其保存为缓存文件
<?php $text = '<?php /** ' . date('Y-m-d H:i:s') . ' */' . PHP_EOL . PHP_EOL . $text; file_put_contents('/path/to/cache_file.php', $text); ?>
最后,我们告诉 Includer 缓存文件的位置。如果它是可读的,Includer 将在 load()
中使用它;否则,它将包含不同的目录和文件组合。
<?php $includer->setCacheFile('/path/to/cache_file.php'); $includer->load(); // uses the cache file if it exists ?>
调试
有时查看 Includer 实际找到的文件可能会有所帮助。使用 getDebug()
方法返回一个包含 Includer 发现的文件信息、顺序和模式的数组。