feat : Decorator Container

This commit is contained in:
2025-09-06 23:08:10 +08:00
parent 5e8cc5c61e
commit cc048c5600
13 changed files with 394 additions and 13 deletions

View File

@@ -20,12 +20,16 @@ class DecoratorController extends AbstractController
* @return array
*/
#[RequestMapping(path: 'basic', methods: 'GET')]
public function basic()
public function basic(): array
{
return (new BasicService)->handle();
}
public function container()
/**
* @return array
*/
#[RequestMapping(path: 'container', methods: 'GET')]
public function container(): array
{
return (new ContainerService)->handle();
}

View File

@@ -0,0 +1,16 @@
<?php
namespace App\Interface\Test\Decorator;
interface LoggerInterface
{
/**
* 定义日志接口
* @param string $msg
* @return void
*/
public function log(string $msg): void;
public function debug(string $msg): void;
public function error(string $msg): void;
public function warning(string $msg): void;
}

View File

@@ -0,0 +1,80 @@
<?php
/**
* This service file is part of item.
*
* @author ctexthuang
* @contact ctexthuang@qq.com
* @web_site https://ctexthuang.com
*/
declare(strict_types=1);
namespace App\Service\Test\Decorator\Container;
use App\Interface\Test\Decorator\LoggerInterface;
use Hyperf\Di\Annotation\Inject;
abstract class AbstractLoggerDecorator implements LoggerInterface
{
/**
* 注入日志接口
* @var LoggerInterface
*/
protected LoggerInterface $logger;
/**
* 注入
* @param LoggerInterface $logger
*/
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
/**
* 抽象复用
* @param string $msg
* @return string
*/
abstract protected function decorateMessage(string $msg): string;
/**
* @param string $msg
* @return void
*/
public function debug(string $msg): void
{
$this->logger->debug($this->decorateMessage($msg));
}
/**
* error 级别日志
* @param string $msg
* @return void
*/
public function error(string $msg): void
{
$this->logger->error($this->decorateMessage($msg));
}
/**
* warning 级别日志
* @param string $msg
* @return void
*/
public function warning(string $msg): void
{
$this->logger->warning($this->decorateMessage($msg));
}
/**
* info 级别日志
* @param string $msg
* @return void
*/
public function log(string $msg): void
{
$this->logger->log($this->decorateMessage($msg));
}
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* This service file is part of item.
*
* @author ctexthuang
* @contact ctexthuang@qq.com
* @web_site https://ctexthuang.com
*/
declare(strict_types=1);
namespace App\Service\Test\Decorator\Container;
use App\Interface\Test\Decorator\LoggerInterface;
use Psr\Log\LoggerInterface as PsrLoggerInterface;
use Hyperf\Logger\LoggerFactory as HyperfLoggerFactory;
class BasicFileLogger implements LoggerInterface
{
/**
* @var PsrLoggerInterface
*/
private PsrLoggerInterface $logger;
/**
* @param HyperfLoggerFactory $loggerFactory
*/
public function __construct(HyperfLoggerFactory $loggerFactory)
{
$this->logger = $loggerFactory->get('app','app');
}
/**
* info 级别日志
* @param string $msg
* @return void
*/
public function log(string $msg): void
{
$this->logger->info($msg);
}
/**
* debug 级别日志
* @param string $msg
* @return void
*/
public function debug(string $msg): void
{
$this->logger->debug($msg);
}
/**
* error 级别日志
* @param string $msg
* @return void
*/
public function error(string $msg): void
{
$this->logger->error($msg);
}
/**
* warning 级别日志
* @param string $msg
* @return void
*/
public function warning(string $msg): void
{
$this->logger->warning($msg);
}
}

View File

@@ -0,0 +1,50 @@
<?php
/**
* This service file is part of item.
*
* @author ctexthuang
* @contact ctexthuang@qq.com
* @web_site https://ctexthuang.com
*/
declare(strict_types=1);
namespace App\Service\Test\Decorator\Container;
use App\Interface\Test\Decorator\LoggerInterface;
class CriticalLoggerDecorator extends AbstractLoggerDecorator
{
/**
* 注入日志接口
* @var LoggerInterface
*/
protected LoggerInterface $logger;
/**
* @param LoggerInterface $logger
*/
public function __construct(LoggerInterface $logger)
{
parent::__construct($logger);
}
/**
* @param string $msg
* @return string
*/
protected function decorateMessage(string $msg): string
{
return $msg; //默认严重级别的不装饰
}
/**
* 重写 只有当 error 级别日志写入才生效
* @param string $msg
* @return void
*/
public function error(string $msg): void
{
$this->logger->error("[CRITICAL] " . $msg);
}
}

View File

@@ -0,0 +1,52 @@
<?php
/**
* This service file is part of item.
*
* @author ctexthuang
* @contact ctexthuang@qq.com
* @web_site https://ctexthuang.com
*/
declare(strict_types=1);
namespace App\Service\Test\Decorator\Container;
use App\Interface\Test\Decorator\LoggerInterface;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Contract\RequestInterface;
class IpLoggerDecorator extends AbstractLoggerDecorator
{
/**
* 注入请求接口
* @var RequestInterface
*/
protected RequestInterface $request;
/**
* 注入日志接口
* @var LoggerInterface
*/
protected LoggerInterface $logger;
/**
* @param LoggerInterface $logger
* @param RequestInterface $request
*/
public function __construct(LoggerInterface $logger,RequestInterface $request)
{
parent::__construct($logger);
$this->request = $request;
}
/**
* ip装饰
* @param string $msg
* @return string
*/
protected function decorateMessage(string $msg): string
{
$ip = $this->request->getServerParams()['remote_addr'] ?? 'unknown';
return "[IP: {$ip}] " . $msg;
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* This service file is part of item.
*
* @author ctexthuang
* @contact ctexthuang@qq.com
* @web_site https://ctexthuang.com
*/
declare(strict_types=1);
namespace App\Service\Test\Decorator\Container;
use App\Interface\Test\Decorator\LoggerInterface;
class TimestampLoggerDecorator extends AbstractLoggerDecorator
{
/**
* 注入日志接口
* @var LoggerInterface
*/
protected LoggerInterface $logger;
/**
* 这里不能注解注入 会导致重复
* @param LoggerInterface $logger
*/
public function __construct(LoggerInterface $logger)
{
parent::__construct($logger);
}
/**
* 复用日期
* @param string $msg
* @return string
*/
protected function decorateMessage(string $msg): string
{
return '[' . date('Y-m-d H:i:s') . '] ' . $msg;
}
}

View File

@@ -11,12 +11,41 @@ declare(strict_types=1);
namespace App\Service\Test\Decorator;
use App\Interface\Test\Decorator\LoggerInterface;
use App\Service\Test\TestBaseService;
use Hyperf\Di\Annotation\Inject;
class ContainerService extends TestBaseService
{
public function handle()
/**
* 注解注入日志接口
* @var LoggerInterface $logger
*/
#[Inject]
protected LoggerInterface $logger;
/**
* @return array
*/
public function handle(): array
{
return $this->return->success();
$this->logger->log('装饰器 [info] 级别日志');
$this->logger->warning('装饰器 [warning] 级别日志');
$this->logger->debug('!!装饰器 [debug] 级别日志');
$this->logger->error('!!!装饰器 [error] 级别日志');
return $this->return->success('完成逻辑');
}
/**
* 封装Log vs 装饰器
*
* ---------- 封装Log -----------
* 封装Log因为无需额外调用栈无装饰器的额外内存占用
*
* ---------- 装饰器 -----------
* 灵活扩展(比如增加一个 traceId 新增装饰器就好) 可以扩展功能 比如时间戳 比如客户端IP 最重要的错误日志告警-写入后调用报警API-比如企业微信机器人等等
*
* 优化方案 : 装饰器+异步写入终极方案todo 研究方向
*/
}

View File

@@ -13,24 +13,24 @@
"license": "Apache-2.0",
"require": {
"php": ">=8.1",
"hyperf/amqp": "~3.1.0",
"hyperf/async-queue": "~3.1.0",
"hyperf/cache": "~3.1.0",
"hyperf/command": "~3.1.0",
"hyperf/config": "~3.1.0",
"hyperf/constants": "~3.1.0",
"hyperf/database": "~3.1.0",
"hyperf/db-connection": "~3.1.0",
"hyperf/elasticsearch": "~3.1.0",
"hyperf/engine": "^2.10",
"hyperf/framework": "~3.1.0",
"hyperf/guzzle": "~3.1.0",
"hyperf/http-server": "~3.1.0",
"hyperf/logger": "~3.1.0",
"hyperf/logger": "^3.1",
"hyperf/memory": "~3.1.0",
"hyperf/process": "~3.1.0",
"hyperf/database": "~3.1.0",
"hyperf/redis": "~3.1.0",
"hyperf/constants": "~3.1.0",
"hyperf/async-queue": "~3.1.0",
"hyperf/amqp": "~3.1.0",
"hyperf/model-cache": "~3.1.0",
"hyperf/elasticsearch": "~3.1.0",
"hyperf/process": "~3.1.0",
"hyperf/redis": "~3.1.0",
"hyperf/tracer": "~3.1.0"
},
"require-dev": {

2
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "88f2a4d4a4e81dc7d415bcdf39930654",
"content-hash": "4ac3b7f3d4fc837bc272d5727a863971",
"packages": [
{
"name": "carbonphp/carbon-doctrine-types",

View File

@@ -11,10 +11,23 @@ declare(strict_types=1);
*/
use App\Interface\Test\Adapter\CacheInterface;
use App\Interface\Test\Decorator\LoggerInterface;
use App\Service\Test\Adapter\Cache\FileCacheAdapter;
use App\Service\Test\Adapter\Cache\RedisCacheService;
use App\Service\Test\Decorator\Container\BasicFileLogger;
use App\Service\Test\Decorator\Container\CriticalLoggerDecorator;
use App\Service\Test\Decorator\Container\IpLoggerDecorator;
use App\Service\Test\Decorator\Container\TimestampLoggerDecorator;
use Hyperf\Logger\LoggerFactory;
use function Hyperf\Support\make;
return [
CacheInterface::class => RedisCacheService::class,
// CacheInterface::class => FileCacheAdapter::class,
LoggerInterface::class => function () {
$logger = make(BasicFileLogger::class);
$logger = make(TimestampLoggerDecorator::class, ['logger' => $logger]);
$logger = make(IpLoggerDecorator::class, ['logger' => $logger]);
return make(CriticalLoggerDecorator::class, ['logger' => $logger]);
},
];

View File

@@ -27,4 +27,22 @@ return [
],
],
],
'app' => [
'handler' => [
'class' => Monolog\Handler\RotatingFileHandler::class,
'constructor' => [
'filename' => BASE_PATH . '/runtime/logs/app/hyperf.log',
'level' => Monolog\Logger::DEBUG,
],
],
'formatter' => [
'class' => Monolog\Formatter\LineFormatter::class,
'constructor' => [
'format' => null,
'dateFormat' => null,
'allowInlineLineBreaks' => true,
'ignoreEmptyContextAndExtra' => true,
],
],
],
];

View File

@@ -16,3 +16,8 @@ Content-Type: application/x-www-form-urlencoded
### Decorator basic test
GET {{host}}/decorator/test/basic
Content-Type: application/x-www-form-urlencoded
### Decorator container test
GET {{host}}/decorator/test/container
Content-Type: application/x-www-form-urlencoded