aura/includer

按照顺序从指定的目录中包含多个文件,并将变量提取到有限的包含作用域中。

2.0.3 2016-10-03 19:57 UTC

This package is auto-updated.

Last update: 2024-09-11 03:55:11 UTC


README

提供从指定目录按顺序包含多个文件的功能,并将变量提取到有限的包含作用域中。

前言

安装

此库需要 PHP 5.3 或更高版本;我们原则上推荐使用最新可用的 PHP 版本。它没有用户空间依赖。

可以通过 Composer 以 aura/includer 的方式安装和自动加载。

或者,下载一个版本 或克隆此存储库,然后要求或包含其 autoload.php 文件。

质量

Scrutinizer Code Quality Code Coverage Build Status

要在命令行中运行单元测试,请在包根目录中运行 phpunit。(这需要 PHPUnit 作为 phpunit 可用。)

此库试图遵守 PSR-1PSR-2PSR-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 发现的文件信息、顺序和模式的数组。