PHP Composer: 로컬에서 개발된 확장 패키지 통합

로컬 PHP 확장 패키지 개발

1. 확장 패키지 디렉토리 구조 생성

  1. hoo-tool 디렉토리를 생성하고 그 안에 src 디렉토리를 만듭니다.
  2. hoo-tool 디렉토리에서 다음 명령어를 실행합니다: composer init
  3. 명령 실행 후 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 코드 작성

  1. 응답 관련 도구 클래스 작성 (Hoo\Tool 네임스페이스는 src 디렉토리에 해당합니다).
  2. 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,
            ];
        }
    }
    
  3. 응답 상태 코드 클래스 작성.
  4. 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';
        }
    }
    
  5. 로깅 유틸리티 클래스 작성.
  6. 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",
        // ]);
    }
}

태그: PHP Composer Package Development Local Packages autoloading

7월 8일 16:41에 게시됨