유틸리티 라이브러리
모두 정적 메서드이며 외부 의존성이 없습니다. 네임스페이스는 _Flexagon\Libs입니다.
| 클래스 | 주요 기능 |
|---|---|
StringUtil |
케이스 변환, UTF-8 정제, hex 인코딩, 랜덤 문자열 생성 |
ArrayUtil |
키 camelCase 변환, 배열 diff, 중첩 배열 키 탐색 |
ValidUtil |
이메일·정수·실수·영숫자·아이디 형식 검증 |
CryptoUtil |
AES-256-CBC 암복호화 (문자열 / 배열, IV 랜덤화 지원) |
FileUtil |
디렉터리 순회, 재귀 생성, 확장자 판별 |
HttpUtil |
URL 파싱, 쿼리스트링 분리, 요청 경로 해석 |
NetUtil |
GET/POST HTTP 클라이언트, JSON 응답 파싱, 파일 업로드 |
HtmlUtil |
리다이렉트, HTML 태그·속성 제거, 이미지 URL 추출 |
TimeDateUtil |
타임스탬프 변환, 타임존 오프셋, 상대 시간 표기 |
SqlUtil |
파라미터 정규화·확장, SQL 이스케이프, SELECT → COUNT 변환 |
ClassUtil |
클래스명·경로·프로퍼티·호출자 조회 |
PhpDocUtil |
PHPDoc 태그 파싱 (어노테이션 기능의 기반) |
AssetLoader |
CSS/JS 관리 |
TemplateLoader |
템플릿 로딩 |
DataSourceManager |
커넥션 풀링 및 전역 트랜잭션 |
Env |
환경변수와 .env.php에서 설정·비밀 값 읽기 |
전역 헬퍼 함수
Libs/_Util.php가 정의하는 세 함수는 네임스페이스 없이 어디서나 쓸 수 있습니다.
_echo('안녕하세요, {name}님', ['name' => $user->getName()]); // 치환 후 출력
$msg = _t('{count}건 검색됨', ['count' => 42]); // 치환 후 반환
___()는 _t()의 별칭입니다. 치환은 한 번만 하므로, 값 안에 {name}이 들어 있어도 다시 치환되지 않습니다.
번역 (I18n)
헬퍼는 치환하기 전에 _Flexagon\I18n\Translator에 등록된 번역기로 문자열을 먼저 번역합니다. 번역기를 등록하지 않으면 원문을 그대로 씁니다.
번역기는 메서드 하나만 구현하면 됩니다.
namespace _Flexagon\I18n;
interface TranslatorInterface
{
public function translate(string $message): string;
}
요청 초반(public/_entry.php 또는 application/_Config.php)에 한 번 등록합니다.
// public/_entry.php
use _Flexagon\I18n\Translator;
setlocale(LC_MESSAGES, 'ko_KR.UTF-8');
bindtextdomain('messages', LOCALE_ROOT);
textdomain('messages');
Translator::setTranslator(new \I18n\GettextTranslator());
스켈레톤의 application/I18n/에 예제 어댑터 세 개가 들어 있습니다.
| 클래스 | 번역 수단 | 필요한 것 |
|---|---|---|
GettextTranslator |
gettext() |
ext-gettext |
MoTranslator |
__() |
__()를 정의하는 라이브러리 (.mo 리더 등) |
SymfonyTranslator |
trans() |
symfony/translation |
Translator::setTranslator(new \I18n\SymfonyTranslator($symfonyTranslator));
LOCALE_ROOT의 기본값은 PROJECT_ROOT . '/locale'입니다. 바꾸려면 프레임워크가 부팅되기 전에 define()하세요.
주의할 점은 다음과 같습니다.
- 출력은 이스케이프되지 않습니다.
_echo()는 번역·치환 결과를 그대로 출력합니다. 사용자 입력 값은 넘기기 전에htmlspecialchars()로 이스케이프하고, 번역 파일도 HTML 출력원으로 보고 신뢰할 수 있는 것만 쓰세요. - 번역기는 프로세스 단위 static입니다. 요청마다 새로 시작하는 PHP-FPM 모델에 맞춘 설계입니다. 상주형 워커(Swoole·RoadRunner·FrankenPHP worker 모드)에서는 요청마다 번역기를 다시 등록하세요.
setlocale()은 프로세스 전역이라 스레드 간에 안전하지 않습니다. - 비용은 어댑터가 결정합니다. 프레임워크 자체 오버헤드는 호출당 약 0.3µs입니다. gettext는 .mo를 프로세스 단위로 캐시합니다(파일을 바꾸면 PHP-FPM 재시작 필요). .mo 라이브러리 중에는 매 요청 파일을 파싱하는 것도 있고, Symfony Translation은
cache_dir를 설정하지 않으면 매 요청 카탈로그를 다시 읽습니다.
Enum 헬퍼
EnumSupporter 트레이트를 backed enum에 붙이면 편의 메서드가 생깁니다.
use _Flexagon\Supporters\EnumSupporter;
enum UserRole: string {
use EnumSupporter;
case ADMIN = 'ADMIN';
case USER = 'USER';
}
UserRole::keys(); // ['ADMIN', 'USER']
UserRole::values(); // ['ADMIN', 'USER']
UserRole::toArray(); // ['ADMIN' => 'ADMIN', 'USER' => 'USER']
UserRole::toCommaString(); // 'ADMIN,USER'
ENUM 컬럼 DDL을 만든다면 toQuotedCommaString() 을 쓰세요. 각 값을 따옴표로 감싸고, 값 안의 따옴표는 두 번 겹쳐 이스케이프합니다.
UserRole::toQuotedCommaString(); // "'ADMIN','USER'"
UserRole::toQuotedCommaString('"'); // '"ADMIN","USER"'
// 값에 따옴표나 쉼표가 있어도 안전합니다
// case A = "it's"; case B = 'a,b';
// toCommaString() → it's,a,b (DDL 이 깨짐)
// toQuotedCommaString() → 'it''s','a,b'
백킹 값이 없는 순수 enum에서는 keys() 와 toCommaString() 은 케이스 이름을, values() 와 toArray() 는 null 을 돌려줍니다.
enum 타입 프로퍼티는 DAO 매핑에서도 자동으로 처리됩니다. DB의 스칼라 값이 대응하는 케이스로 변환되어 모델에 주입되고, 반대로 저장할 때는 ->value가 바인딩됩니다.