1

出于调试目的,在处理具有许多文件/许多include(例如:Wordpress 代码)的 PHP 项目时,我有时会对查看“未包装”代码以及合并/展平(“展平”是 Photoshop 中使用的术语)感兴趣-当您将许多层合并为一层时,就像工具一样)将所有文件合并到一个大的 PHP 文件中。

如何合并多个 PHP 文件?

例子:

$ php index.php --amalgamation

会将这些文件作为输入:

  • 变量.php

    <?php
    $color = 'green';
    $fruit = 'apple';
    ?>
    

    索引.php

    <?php
    include 'vars.php';
    echo "A $color $fruit";
    ?>
    

并产生这个合并的输出:

<?php
$color = 'green';
$fruit = 'apple';
echo "A $color $fruit";
?>

(它也应该适用于许多文件,例如如果index.php包含vars.php本身包含的文件abc.php)。

4

1 回答 1

1

我们可以编写一个合并/捆绑脚本,它获取给定文件的内容并匹配 的任何实例include|require,然后获取任何引用文件的内容,并用实际代码替换 include/require 调用。

以下是一个基本实现(基于对具有嵌套引用的文件进行的非常有限的测试),它适用于包含/需要其他文件的任意数量的文件。

<?php

// Main file that references further files:
$start = 'test/test.php';

function bundle_files(string $filepath)
{
    // Fetch current code
    $code = file_get_contents($filepath);
    
    // Set directory for referred files
    $dirname = pathinfo($filepath, PATHINFO_DIRNAME);
    
    // Match and substitute include/require(_once) with code:
    $rx = '~((include|require)(_once)?)\s+[\'"](?<path>[^\'"]+)[\'"];~';

    $code = preg_replace_callback($rx, function($m) use ($dirname) {
        // Ensure a valid filepath or abort:
        if($path = realpath($dirname . '/' . $m['path'])) {
            return bundle_files($path);         
        } else {
            die("Filepath Read Fail: {$dirname}/{$m['path']}");
        }
    }, $code);
    
    // Remove opening PHP tags, note source filepath
    $code = preg_replace('~^\s*<\?php\s*~i', "\n// ==== Source: {$filepath} ====\n\n", $code);
    
    // Remove closing PHP tags, if any
    $code = preg_replace('~\?>\s*$~', '', $code);   
    
    return $code;
}

$bundle = '<?php ' . "\n" . bundle_files($start);

file_put_contents('bundle.php', $bundle);
echo $bundle;

在这里,我们使用preg_replace_callback()按出现顺序匹配和替换,回调在每个匹配的文件路径上调用捆绑函数,并用实际代码替换 include/require 引用。该函数还包括一个注释行,指示包含文件的来源,如果/当您调试编译的捆绑文件时,它可能会派上用场。

笔记/作业:

  • 您可能需要改进基本目录引用例程。(预计依赖于 PHP include_path 的“不完整”文件路径会出现问题。)
  • 没有控制_once,代码将被重新包含。(通过记录包含的文件路径和跳过重复来轻松补救。)
  • 匹配仅在 上进行"path/file.php",即。单/双引号内的完整字符串。连接的字符串不匹配。
  • 不理解包括变量或常量的路径。必须在没有副作用的情况下评估文件!才能做到这一点。
  • 如果您使用declare(strict_types=1);,请将其放在顶部并消除以下实例。
  • 捆绑文件可能还有其他副作用,此处未提及。
  • 正则表达式不会向后/查看您的 include/require 是否被注释掉!
  • 如果你的代码跳进跳出 PHP 模式并脱口而出 HTML,所有的赌注都没有了
  • 管理包含自动加载的类超出了此代码段。

请报告任何故障和边缘情况。随意开发和(自由)分享。

于 2021-01-14T16:48:47.873 回答