PHP程序单文件部署

PHPMiniCMS by 达达 at 2013-12-14

昨天给MiniCMS做了一个build.php脚本,用来将MiniCMS目录下的所有文件打包成一个install.php,这样用户只需要上传install.php到网站根目录就可以安装或升级MiniCMS了。

怎么实现的呢?这里跟大家分享一下心得。

在build.php中我做了一个build函数,用于递归遍历目录中的文件和子目录,层层递归遍历,遇到文件就读取内容进行gz压缩后再base64编码成字符串,一方面是缩小生成后的体积,一方面是确保编码出来的内容可以作为install.php中的php字符串。

以下是代码:

function build($dirs) {
    foreach ($dirs as $dir) {
        if (!is_dir($dir)) {
            echo "$dir not exists";
            exit;
        }

        if ($dh = opendir($dir)) {
            $sub_dirs = array();
            while (($item = readdir($dh)) !== false) {
                if ($item[0] == '.' || ($dir == "." && $item == "build.php"))
                    continue;

                $file = $dir."/".$item;

                if (is_dir($file)) {
                    $sub_dirs[] = $file;
                } else {
                    echo "    echo \"解压 $file<br/>\";\n";
                    echo "    install('$file', <<<DATA\n";
                    echo base64_encode(gzcompress(file_get_contents($file)));
                    echo "\nDATA\n);\n";
                }
            }
            closedir($dh);
            build($sub_dirs);
        } else {
            echo "Could not open $dir";
            exit;
        }
    }
}

build函数echo出来的就是要生成到install.php里的php代码。可以看到每个文件编码后作为install.php中install函数的参数,生成到install.php里。

生成出来的内容像这样:

echo "解压 ./index.php<br/>";
install('./index.php', <<<DATA
eJzNVttu2kAQfecrthLS2gJjSNNWLUlRH2gVqapUklZqXWflmA2sCsbx2lES4n/vzPoOhlwa2kgkmJ3bmTmzMz4Y+FO/EfCLSAScLTyXk7EIPGfONcY+Hn0eMqZ3qDl3jXMx4xIf3EXAO2BF+41Gc+4yfyFD5vOA+c6Ek0PS66LgQsKjkJKHWpMdD0ffhyOLfv02HP1gxyejoy+fqK2TAdkkI+8IxQDinGh+wCds7oTuVKO3pxjO1CzHuOkar+zl61hv3tI2gYDwT2lxqetk2SAE0U14yMJrH4FRNAWnhQDzBEFmZvXsfiNu8JnkZD1w6Ewg7qlpt3RT+zXAbA81q2u8hQN92W334nsDAVd1OKJgNubuYsy1EiI9U8SAzIvmRV0zpb2klNnPl1i93pZMxk7IzQT6cj82koe9+K/TQr//My8ncKfikpv3Bpwa0IpP1bogDKQ0ab0diOrypHRzTuzT8MSieJ41fungjrw0zTKg3z8YP7HlW6beekDPY4AarDI6k2FQJqRNum1i9ICXmCggde6EN+ZXO8ldXfVquOzKJpmlQ4rQfBihUJoKkulHZzMhp+lgIgQ+6NAJAuea/ebXjF8J0NbKsNskm19Z9Uh+wsRYTYZCu1+Rp0JlbJWM7EQt14U74eAV8CQPhDMTN1xD8Mqru/BC7gGo1ZTQyKSdktsO7cAh1dWtieEvZ4gQ0Nrv7mupqNzJq9XEufPIYpaw4GTP65pUNKlhv6znLiIPq6S+tbI56KWKgCcxzTwmScDnfBEAfgHn3T6B74MVx+qw1cpZy9nKglhNkVLRXKcrpwmrJDyWxF5pDdS1sGQSujYLtIJbuULf+CtxGacElWoh0+i52U5quo14NZkfzvyueEc468T/W9ph+sGxltKsCmS3Kxdeh9IBkCr1BfSN3NcwX1jtoKjbiM823DPhHm9TctuqN76pCrQmeERHVGf3vdqiOrlLUCy7tCirfQKr8o2eGqwnxeY8mMDbTiFZnSf9cqfgGcltL51ZxGW6uSJPXEQVT3pecsQit5sVueh3NIpaxhu7BIRPsGjRy6MXLRo/5aJVKa0sWouikNoP3rbPYKVCN62/Qr1IX1b1WnzhlM95gi/FhcnUqsID+Em1Bu8bfwCsIHtx
DATA
);

在install.php中,install函数则将参数base64反编码后再进行gz解压,得到最终文件内容,然后写入目标文件。

function install($file, $content) {
  $dir = dirname($file);
  if (is_dir($dir) || mkdir($dir, 0744, true)) {
    file_put_contents($file, gzuncompress(base64_decode($content)));
  } else {
    echo "Could't create directory for $file\n";
    exit;
  }
}

在install.php中实现一个填写配置的表单,表单提交后,就可以开始执行build.php生成出来的这些解压代码了。

很有意思吧 :)