로컬 PHP 확장 패키지 개발
1. 확장 패키지 디렉토리 구조 생성
hoo-tool디렉토리를 생성하고 그 안에src디렉토리를 만듭니다.hoo-tool디렉토리에서 다음 명령어를 실행합니다:composer init- 명령 실행 후
composer.json파일의 내용은 다음과 같습니다:{ "name": "hoo/tool", "description": "hoo Tool kit for PHP", "type": "library", "license": "MIT", "autoload": { "psr-4": { "Hoo\\Tool\\": "src/" } }, "authors": [ { "name": "hoo", "email": "hoo@example.com" } ], "minimum-stability": "alpha", "require": {} }
2. composer.json 파일 작성
이 문서에서는 PHP 8.2 버전을 사용하므로 composer.json 파일에 PHP 버전을 명시합니다:
{
"require": {
"php": ">=8.0"
}
}
3. 확장 패키지 PHP 코드 작성
- 응답 관련 도구 클래스 작성 (
Hoo\Tool네임스페이스는src디렉토리에 해당합니다). - 응답 상태 코드 클래스 작성.
- 로깅 유틸리티 클래스 작성.
src 디렉토리에 ResultTool.class 클래스를 생성합니다:
<?php
namespace Hoo\Tool;
use Hoo\Tool\Constants\ErrorCode;
class ResultTool
{
/**
* 성공 응답 생성
* @param array $data 응답 데이터
* @return array 응답 배열
*/
public static function success(array $data = []): array
{
return static::end(ErrorCode::SUCCESS, ErrorCode::getMessage(ErrorCode::SUCCESS), $data);
}
/**
* 오류 응답 생성
* @param string $message 오류 메시지
* @param int $code 오류 코드
* @param array $data 추가 데이터
* @return array 응답 배열
*/
public static function error(string $message = '', int $code = ErrorCode::ERROR, array $data = []): array
{
if (empty($message)) {
return static::end($code, ErrorCode::getMessage($code), $data);
} else {
return static::end($code, $message, $data);
}
}
/**
* 응답 구조 생성
* @param int $code 응답 코드
* @param string $message 응답 메시지
* @param array $data 응답 데이터
* @return array 응답 배열
*/
protected static function end($code, $message, $data): array
{
return [
'code' => $code,
'message' => $message,
'data' => $data,
];
}
}
src 디렉토리에 Constants 디렉토리를 생성하고 그 안에 ErrorCode.class 파일을 생성합니다:
<?php
namespace Hoo\Tool\Constants;
class ErrorCode
{
public const SUCCESS = 200;
public const ERROR = 0;
/**
* 코드에 해당하는 메시지 반환
* @param int $code 오류 코드
* @return string 오류 메시지
*/
public static function getMessage(int $code): string
{
$errors = [
0 => 'Server Error!',
200 => 'success',
// 필요한 만큼 추가
];
return $errors[$code] ?? 'Unknown error';
}
}
src 디렉토리에 LoggerUtil.class 클래스를 생성합니다:
<?php
namespace Hoo\Tool;
class LoggerUtil
{
private string $logFilePath;
private string $logDirectory = './runtime/logs/'; // 로그 파일 디렉토리
private float|int $maxFileSize = 2 * 1024 * 1024; // 파일 크기 제한 (2MB)
private string $datePattern = 'Y-m-d'; // 로그 파일명 날짜 형식
private bool $rollingByType = true; // true: 파일 크기 기준 롤링, false: 날짜 기준 롤링
/**
* 로그 파일 롤링 검사 및 실행
*/
private function checkAndRollFile()
{
$dirPath = dirname($this->logFilePath);
if (!file_exists($dirPath)) {
mkdir($dirPath, 0755, true); // 권한 0755, 재귀적 생성
}
// 날짜 기준 롤링 검사
if (!$this->rollingByType && file_exists($this->logFilePath) && date($this->datePattern) !== date($this->datePattern, filemtime($this->logFilePath))) {
$this->rollByDate();
}
// 파일 크기 기준 롤링 검사
clearstatcache(true, $this->logFilePath);
if ($this->rollingByType && file_exists($this->logFilePath) && filesize($this->logFilePath) >= $this->maxFileSize) {
$this->rollBySize();
}
}
/**
* 날짜 기준으로 로그 파일 롤링
*/
private function rollByDate()
{
$newPath = $this->getNewFilePath(true);
rename($this->logFilePath, $newPath);
}
/**
* 크기 기준으로 로그 파일 롤링
*/
private function rollBySize()
{
$newPath = $this->getNewFilePath(false, true);
rename($this->logFilePath, $newPath);
}
/**
* 새로운 로그 파일 경로 생성
*
* @param bool $byDate 날짜 기준 롤링 여부
* @param bool $forcedBySize 크기 초과로 인한 강제 롤링 여부
* @return string 새로운 로그 파일 경로
*/
private function getNewFilePath($byDate = false, $forcedBySize = false)
{
$baseName = pathinfo($this->logFilePath, PATHINFO_FILENAME);
$extension = pathinfo($this->logFilePath, PATHINFO_EXTENSION);
$dirName = pathinfo($this->logFilePath, PATHINFO_DIRNAME);
$suffix = '';
if ($byDate) {
$suffix = '_' . date($this->datePattern);
} elseif ($forcedBySize) {
$suffix = '_size_' . date('Hi');
}
return "{$dirName}/{$baseName}{$suffix}.{$extension}";
}
/**
* 로그 내용 쓰기
*
* @param string $fileName 로그 파일명
* @param mixed $content 기록할 내용
* @param string $label 로그 레이블
* @return bool 쓰기 성공 여부
*/
public static function write(string $fileName, mixed $content, string $label = ''): bool
{
$instance = new self();
$instance->logFilePath = $instance->logDirectory . date('Ymd') . '/' . $fileName . '.log';
$instance->checkAndRollFile();
$logMessage = "[" . date("Y-m-d H:i:s") . "] " . $label . ' ';
if (is_string($content)) {
$logMessage .= $content . PHP_EOL;
} else {
$logMessage .= PHP_EOL . var_export($content, true) . PHP_EOL;
}
// 로그 파일에 쓰기
$result = file_put_contents($instance->logFilePath, $logMessage, FILE_APPEND);
return $result !== false;
}
}
개발된 패키지 통합
1. composer.json 파일 수정
아직 커밋되지 않은 로컬 패키지를 프로젝트에 추가합니다:
"repositories": [
{
"type": "path",
"url": "패키지의 절대 경로"
}
]
url 경로 예시:
- Windows:
"D:\\docker-code\\code\\hoo-tool" - Linux:
"/code/hoo-tool"
2. 패키지 설치
다음 명령어를 실행하여 패키지를 설치합니다: composer require hoo/tool
3. 패키지 사용 예시
<?php
declare(strict_types=1);
namespace App\Controller;
use Hoo\Tool\LoggerUtil; // 네임스페이스를 올바르게 수정
use Hoo\Tool\ResultTool; // 네임스페이스를 올바르게 수정
// abstract Controller 클래스를 사용한다고 가정
class IndexController extends AbstractController
{
public function index()
{
LoggerUtil::write('test_log', 'Check If The Application Is Under Maintenance', 'Test Log');
// 성공 응답 예시
return ResultTool::success('Successfully retrieved data', [
'method' => 'post',
'message' => "Hello hoo-tool",
]);
// 오류 응답 예시
// return ResultTool::error('Server error', 500, [
// 'method' => 'post',
// 'message' => "Hello hoo-tool",
// ]);
}
}