最近嘗試webman
的二進(jìn)制打包,確實(shí)很方便,但是也出現(xiàn)了一些問題。
比如:使用phinx
數(shù)據(jù)庫遷移,多語言,上傳文件至public目錄等,目前我遇到的都是資源讀取問題。
這些問題解決非常簡單,常常只需要將配置項(xiàng)的base_path()
變成base_path(false)
然后將目錄拷貝至webman.bin
同目錄就能解決,其他錯誤情況也類似,不過對部署上線就非常麻煩了。
通過編寫一個(gè)自定義命令行可以輕松解決這個(gè)問題。
composer require webman/console ^1.2.24
php webman make:command custom:build:bin
目前只簡單實(shí)現(xiàn)目錄copy,將打包結(jié)果壓縮成zip,方便分發(fā)和部署,其他需求可自行修改擴(kuò)展。
<?php
namespace app\command;
use RecursiveIteratorIterator;
use RecursiveDirectoryIterator;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Command\Command;
use Webman\Console\Commands\BuildBinCommand;
use ZipArchive;
class CustomBuildBinCommand extends Command
{
protected static $defaultName = 'custom:build:bin';
protected static $defaultDescription = 'Custom build bin';
/**
* @return void
*/
protected function configure(): void
{
$this->addArgument('version', InputArgument::OPTIONAL, '打包的PHP版本', '8.1');
$this->addArgument('zip', InputArgument::OPTIONAL, '是否將打包輸出目錄壓縮', 0);
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
// 是否將打包輸出目錄壓縮
$zip = $input->getArgument('zip');
// 打包輸出目錄
$buildDir = config('plugin.webman.console.app.build_dir', base_path() . '/build');
$output->writeln('<comment>正在打包...</comment>');
// 調(diào)用打包bin命令
$command = new BuildBinCommand();
$command->execute($input, $output);
$output->writeln('<comment>復(fù)制目錄...</comment>');
// 復(fù)制db目錄 phinx數(shù)據(jù)庫遷移
$this->copyDirectory(base_path() . '/db', $buildDir . '/db');
// 復(fù)制public目錄(如果需要讀取里面的資源)
$this->copyDirectory(base_path() . '/public', $buildDir . '/public');
// 復(fù)制resource目錄(使用多語言)
$this->copyDirectory(base_path() . '/resource', $buildDir . '/resource');
$output->writeln('<info>復(fù)制完畢</info>');
if ($zip) {
$output->writeln('<comment>壓縮中...</comment>');
$zipFilename = $buildDir . '/build.zip';
// 刪除之前的壓縮包
if (file_exists($zipFilename)) {
unlink($zipFilename);
}
// 壓縮目錄并跳過非必要的文件
$this->zipDirectory($buildDir, $zipFilename, [
'*.zip',
'*.sfx',
'*.phar',
'.env'
]);
$output->writeln('<info>壓縮完成! ' . $zipFilename . '</info>');
}
$output->writeln('<info>打包完成!</info>');
return self::SUCCESS;
}
/**
* 拷貝目錄 包含子目錄及文件
* @param $src
* @param $dst
* @return false|void
*/
protected function copyDirectory($src, $dst)
{
$dir = opendir($src);
if (!$dir) {
return false;
}
if (!is_dir($dst)) {
mkdir($dst, 0755, true);
}
while (false !== ($file = readdir($dir))) {
if (($file != '.') && ($file != '..')) {
$srcFile = $src . '/' . $file;
$dstFile = $dst . '/' . $file;
if (is_dir($srcFile)) {
// 遞歸調(diào)用自身,拷貝子目錄
$this->copyDirectory($srcFile, $dstFile);
} else {
// 拷貝文件
copy($srcFile, $dstFile);
}
}
}
closedir($dir);
}
/**
* zip壓縮目錄
* @param $source
* @param $destination
* @param array $exclude
* @return bool
*/
protected function zipDirectory($source, $destination, array $exclude = []): bool
{
$zip = new ZipArchive();
if (!$zip->open($destination, ZipArchive::CREATE)) {
return false;
}
$source = str_replace('\\', '/', realpath($source));
if (is_dir($source) === true) {
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
foreach ($files as $file) {
$file = str_replace('\\', '/', $file);
$fileName = basename($file);
if ($fileName == '.' || $fileName == '..') {
continue;
}
echo "Source: $source, File: $file\n";
// Skip excluded files and dirs
$skip = false;
foreach ($exclude as $pattern) {
if (fnmatch($pattern, $file)) {
$skip = true;
break;
}
}
if ($skip) {
echo "Skipping: $file\n";
continue;
}
$file = realpath($file);
if (is_dir($file) === true) {
$zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
} else if (is_file($file) === true) {
$zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
}
}
} else if (is_file($source) === true) {
$zip->addFromString(basename($source), file_get_contents($source));
}
return $zip->close();
}
}
打包php8.1版本,并將打包結(jié)果壓縮zip:
php -d phar.readonly=0 webman custom:build:bin 8.1 true
打包完成后在輸出目錄會看到一個(gè)build.zip
壓縮包。