Files
FendxPHP/bin/console
Lawson 2782d765fb feat(database): 添加用户角色权限系统及相关监控功能
- 创建用户表(users)包含基本信息和认证字段
- 创建角色表(roles)用于权限控制
- 创建权限表(permissions)定义系统权限
- 创建用户角色关联表(user_roles)建立用户与角色关系
- 创建角色权限关联表(role_permissions)建立角色与权限关系
- 创建迁移记录表(migrations)追踪数据库变更
- 添加AdminController提供管理员面板功能
- 实现系统监控、配置管理、缓存清理等功能
- 添加AOP切面编程支持的各种通知类型
- 实现告警管理AlertManager支持多渠道告警
- 添加文档注解接口规范
2026-04-08 17:00:28 +08:00

438 lines
13 KiB
PHP

#!/usr/bin/env php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use Fendx\Cli\Application;
use Fendx\Cli\Command\VersionCommand;
use Fendx\Cli\Command\HelpCommand;
use Fendx\Cli\Command\ServerCommand;
use Fendx\Cli\Command\MigrateCommand;
use Fendx\Cli\Command\GenerateCommand;
/**
* FendxPHP 控制台应用
*/
class ConsoleApplication extends Application
{
protected function getDefaultCommands(): array
{
return [
new VersionCommand(),
new HelpCommand(),
new ServerCommand(),
new MigrateCommand(),
new GenerateCommand(),
new TestCommand(),
new DeployCommand(),
new BenchmarkCommand(),
];
}
}
/**
* 测试命令
*/
class TestCommand extends \Fendx\Cli\Command\Command
{
protected function configure(): void
{
$this->setName('test')
->setDescription('运行测试套件')
->addArgument('type', '测试类型: unit, integration, api, e2e, performance, security')
->addOption('filter', 'f', '过滤测试用例')
->addOption('coverage', 'c', '生成覆盖率报告')
->addOption('parallel', 'p', '并行测试', false, 4);
}
protected function execute(\Fendx\Cli\Input\InputInterface $input, \Fendx\Cli\Output\OutputInterface $output): int
{
$type = $input->getArgument('type') ?? 'all';
$filter = $input->getOption('filter');
$coverage = $input->getOption('coverage');
$parallel = $input->getOption('parallel');
$output->writeln("<info>运行 {$type} 测试...</info>");
return match ($type) {
'unit' => $this->runUnitTests($output, $filter, $coverage),
'integration' => $this->runIntegrationTests($output, $filter),
'api' => $this->runApiTests($output, $filter),
'e2e' => $this->runE2ETests($output, $filter),
'performance' => $this->runPerformanceTests($output),
'security' => $this->runSecurityTests($output),
'all' => $this->runAllTests($output, $filter, $coverage, $parallel),
default => $this->showError($output, "未知的测试类型: {$type}")
};
}
private function runUnitTests($output, $filter, $coverage): int
{
$output->writeln("<info>运行单元测试...</info>");
$command = "vendor/bin/phpunit tests/Unit --colors=always";
if ($filter) {
$command .= " --filter {$filter}";
}
if ($coverage) {
$command .= " --coverage-html reports/coverage --coverage-clover reports/coverage.xml";
}
$this->executeCommand($output, $command);
if ($coverage) {
$output->writeln("<info>覆盖率报告已生成: reports/coverage/index.html</info>");
}
return 0;
}
private function runIntegrationTests($output, $filter): int
{
$output->writeln("<info>运行集成测试...</info>");
// 启动测试环境
$this->executeCommand($output, "docker-compose -f docker-compose.test.yml up -d");
sleep(10); // 等待服务启动
$command = "vendor/bin/phpunit tests/Integration --colors=always";
if ($filter) {
$command .= " --filter {$filter}";
}
$result = $this->executeCommand($output, $command);
// 清理测试环境
$this->executeCommand($output, "docker-compose -f docker-compose.test.yml down");
return $result;
}
private function runApiTests($output, $filter): int
{
$output->writeln("<info>运行 API 测试...</info>");
$command = "vendor/bin/codecept run api --colors";
if ($filter) {
$command .= " -g {$filter}";
}
return $this->executeCommand($output, $command);
}
private function runE2ETests($output, $filter): int
{
$output->writeln("<info>运行端到端测试...</info>");
// 启动完整环境
$this->executeCommand($output, "docker-compose up -d");
$this->executeCommand($output, "kubectl apply -f k8s/");
sleep(30); // 等待所有服务就绪
$command = "vendor/bin/codecept run e2e --colors";
if ($filter) {
$command .= " -g {$filter}";
}
$result = $this->executeCommand($output, $command);
// 清理环境
$this->executeCommand($output, "kubectl delete -f k8s/");
$this->executeCommand($output, "docker-compose down");
return $result;
}
private function runPerformanceTests($output): int
{
$output->writeln("<info>运行性能测试...</info>");
// 并发测试
$this->executeCommand($output, "ab -n 10000 -c 100 http://localhost/api/users");
// 内存测试
$this->executeCommand($output, "php bin/console benchmark:memory");
// 数据库性能测试
$this->executeCommand($output, "php bin/console benchmark:database");
return 0;
}
private function runSecurityTests($output): int
{
$output->writeln("<info>运行安全测试...</info>");
// 依赖漏洞扫描
$this->executeCommand($output, "composer audit");
// 代码安全扫描
$this->executeCommand($output, "vendor/bin/phpstan analyse --level=8");
// API 安全测试
$this->executeCommand($output, "vendor/bin/codecept run security");
return 0;
}
private function runAllTests($output, $filter, $coverage, $parallel): int
{
$output->writeln("<info>运行所有测试...</info>");
$tests = [
'unit' => $this->runUnitTests($output, $filter, $coverage),
'integration' => $this->runIntegrationTests($output, $filter),
'api' => $this->runApiTests($output, $filter),
];
$failed = array_filter($tests, fn($result) => $result !== 0);
if (empty($failed)) {
$output->writeln("<info>所有测试通过! ✅</info>");
return 0;
} else {
$output->writeln("<error>部分测试失败! ❌</error>");
return 1;
}
}
private function executeCommand($output, string $command): int
{
$output->writeln("<comment>执行: {$command}</comment>");
$process = proc_open($command, [
1 => ['pipe', 'w'],
2 => ['pipe', 'w'],
], $pipes);
if (!is_resource($process)) {
return 1;
}
// 读取输出
while (($line = fgets($pipes[1])) !== false) {
$output->write($line);
}
// 读取错误输出
while (($line = fgets($pipes[2])) !== false) {
$output->write("<error>{$line}</error>");
}
return proc_close($process);
}
private function showError($output, string $message): int
{
$output->writeln("<error>{$message}</error>");
return 1;
}
}
/**
* 部署命令
*/
class DeployCommand extends \Fendx\Cli\Command\Command
{
protected function configure(): void
{
$this->setName('deploy')
->setDescription('部署应用到指定环境')
->addArgument('environment', '部署环境: local, docker, k8s')
->addOption('force', 'f', '强制部署', false);
}
protected function execute(\Fendx\Cli\Input\InputInterface $input, \Fendx\Cli\Output\OutputInterface $output): int
{
$environment = $input->getArgument('environment');
$force = $input->getOption('force');
$output->writeln("<info>部署到 {$environment} 环境...</info>");
return match ($environment) {
'local' => $this->deployLocal($output, $force),
'docker' => $this->deployDocker($output, $force),
'k8s' => $this->deployKubernetes($output, $force),
default => $this->showError($output, "未知的环境: {$environment}")
};
}
private function deployLocal($output, $force): int
{
$output->writeln("<info>部署到本地环境...</info>");
// 检查依赖
$this->executeCommand($output, "composer install");
// 运行迁移
$this->executeCommand($output, "php bin/console migrate:run");
// 设置权限
$this->executeCommand($output, "chmod -R 755 storage/ runtime/");
$output->writeln("<info>本地部署完成! 🎉</info>");
return 0;
}
private function deployDocker($output, $force): int
{
$output->writeln("<info>部署到 Docker 环境...</info>");
if ($force) {
$this->executeCommand($output, "docker-compose down --volumes");
}
$this->executeCommand($output, "docker-compose up -d --build");
// 等待服务启动
$output->writeln("<comment>等待服务启动...</comment>");
sleep(30);
// 健康检查
$this->executeCommand($output, "curl -f http://localhost/health");
$output->writeln("<info>Docker 部署完成! 🐳</info>");
return 0;
}
private function deployKubernetes($output, $force): int
{
$output->writeln("<info>部署到 Kubernetes 环境...</info>");
if ($force) {
$this->executeCommand($output, "kubectl delete namespace fendx");
}
$this->executeCommand($output, "kubectl apply -f k8s/");
// 等待部署完成
$this->executeCommand($output, "kubectl rollout status deployment/fendx-php -n fendx");
$output->writeln("<info>Kubernetes 部署完成! ☸️</info>");
return 0;
}
}
/**
* 基准测试命令
*/
class BenchmarkCommand extends \Fendx\Cli\Command\Command
{
protected function configure(): void
{
$this->setName('benchmark')
->setDescription('运行性能基准测试')
->addArgument('type', '测试类型: all, memory, database, cache, api');
}
protected function execute(\Fendx\Cli\Input\InputInterface $input, \Fendx\Cli\Output\OutputInterface $output): int
{
$type = $input->getArgument('type') ?? 'all';
$output->writeln("<info>运行 {$type} 基准测试...</info>");
return match ($type) {
'memory' => $this->benchmarkMemory($output),
'database' => $this->benchmarkDatabase($output),
'cache' => $this->benchmarkCache($output),
'api' => $this->benchmarkApi($output),
'all' => $this->benchmarkAll($output),
default => $this->showError($output, "未知的测试类型: {$type}")
};
}
private function benchmarkMemory($output): int
{
$output->writeln("<info>内存基准测试...</info>");
$start = memory_get_usage();
// 模拟业务逻辑
for ($i = 0; $i < 100000; $i++) {
$data = ['id' => $i, 'name' => "user_{$i}", 'email' => "user{$i}@example.com"];
$json = json_encode($data);
$array = json_decode($json, true);
}
$end = memory_get_usage();
$used = ($end - $start) / 1024 / 1024;
$output->writeln("<info>内存使用: {$used} MB</info>");
return 0;
}
private function benchmarkDatabase($output): int
{
$output->writeln("<info>数据库基准测试...</info>");
$start = microtime(true);
// 模拟数据库查询
for ($i = 0; $i < 1000; $i++) {
// 这里应该执行实际的数据库查询
usleep(100); // 模拟 0.1ms 查询时间
}
$end = microtime(true);
$duration = ($end - $start) * 1000;
$output->writeln("<info>1000 次查询耗时: {$duration} ms</info>");
return 0;
}
private function benchmarkCache($output): int
{
$output->writeln("<info>缓存基准测试...</info>");
$start = microtime(true);
// 模拟缓存操作
for ($i = 0; $i < 10000; $i++) {
// 模拟缓存写入
usleep(10); // 模拟 0.01ms 缓存时间
// 模拟缓存读取
usleep(5); // 模拟 0.005ms 缓存时间
}
$end = microtime(true);
$duration = ($end - $start) * 1000;
$output->writeln("<info>20000 次缓存操作耗时: {$duration} ms</info>");
return 0;
}
private function benchmarkApi($output): int
{
$output->writeln("<info>API 基准测试...</info>");
$this->executeCommand($output, "ab -n 1000 -c 10 http://localhost/api/users");
return 0;
}
private function benchmarkAll($output): int
{
$this->benchmarkMemory($output);
$this->benchmarkDatabase($output);
$this->benchmarkCache($output);
$this->benchmarkApi($output);
return 0;
}
}
// 运行控制台应用
try {
$app = new ConsoleApplication();
$app->run();
} catch (\Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
exit(1);
}