8.4 현대화 도구은(는) 무엇을 하나요?
언제 사용하나요
이 스킬은 레거시 PHP 프로젝트(보통 PHP 5.x용으로 작성된 커스텀 CMS)가 다음과 같은 경우에 유용합니다:
- 전체 재작성 없이 PHP 8.3 / 8.4에서 실행되어야 할 때, 및/또는
- Docker 없이 공유 호스팅(cPanel/Plesk)으로 FTP를 통해 배포되어야 할 때
일반적인 증상: mysql_*, ereg/eregi, <? short 태그, PHP4 스타일 생성자,
bareword 배열 키($row[Id]), $$var['key'], sizeof(null), MyISAM 덤프,
TemplatePower 템플릿, config/defines*.php에 평문 자격 증명.
이 스킬이 제공하는 것
| 자산 | 목적 |
|---|---|
scripts/compat.php | Shim: mysql_*→mysqli, ereg*/split→preg, userErrorHandler |
scripts/fix_barewords.php | Tokenizer 기반 bareword 배열 키 인용 처리 |
scripts/fix_variable_variables.php | PHP 8 $$var['key'] 균일 변수 구문 호환성 문제 수정 |
scripts/check_signatures.php | 정적 LSP 메서드 시그니처 검사기 |
scripts/lint-all.sh | php -l 스윕 |
scripts/smoke-test.sh | URL 목록 HTTP 스모크 테스트 |
templates/defines.php | .env 로더 + DB 상수 (Docker 유무와 관계없이 작동) |
templates/env.example | .env 템플릿 (DB_* + FTP_*) |
templates/htaccess | 최신 Apache/PHP-FPM .htaccess |
templates/user.ini | 공유 호스팅용 PHP-FPM 오버라이드 |
templates/timthumb.php | 안전한 GD 썸네일 생성기 (취약한 TimThumb 대체) |
deploy/deploy.sh | FTP 또는 rsync 배포; 개발 파일 제외; 원격 .env 작성 |
황금 규칙
- 안전 우선: 건드리기 전에
git init+ 베이스라인 커밋. DB를 백업하세요. - 리팩터 전에 차단 해제: shim으로 전체 코드베이스를 즉시 실행 가능하게 만듭니다.
- 중앙 집중식 DB 레이어:
dbClass를 먼저 교체/제한하고; shim은 rawmysql_*호출을 처리합니다. - 보안은 조기에: 사이트가 렌더링되는 즉시 위험한 도구와 TimThumb을 제거하세요.
- 지속적으로 검증: 모든 배치 후
php -l을 실행하고, 모든 URL을 스모크 테스트하세요.
절차
0. 베이스라인
git init -q && git add -A && git commit -qm "baseline: legacy PHP"
find . -name '*.php' -not -path './node_modules/*' | wc -l
scripts/smoke-test.sh를 위해 실제 공개 URL 목록(DB/사이트맵에서)을 저장하세요.
1. 호환성 shim 설치
scripts/compat.php를includes/compat.php등으로 복사하세요.- 부트스트랩의 가장 위쪽에서 레거시 코드보다 먼저 로드하세요:
include_once(__DIR__.'/../includes/compat.php'); - 이 shim은
mysql_*,ereg/eregi/ereg_replace/eregi_replace/split,mysqli_report(MYSQLI_REPORT_OFF)(SQL 오류는 예외 대신false반환), 그리고userErrorHandler()(PHP 5의 오래된 E_NOTICE "undefined index/variable"를 억제)를 제공합니다. - 핸들러를 한 번 등록하세요:
if (function_exists('userErrorHandler')) set_error_handler('userErrorHandler');
2. 기계적 수정 (스크립트)
php scripts/fix_barewords.php # 드라이 런
php scripts/fix_barewords.php --apply
php scripts/fix_variable_variables.php # 드라이 런
php scripts/fix_variable_variables.php --apply
scripts/lint-all.sh
그런 다음 린트가 여전히 보고하는 문제를 수정하세요:
- Short 태그:
<?→<?php(grep<\?(?!php|=|xml)). - PHP4 생성자:
function ClassName()→function __construct(). - 중괄호 문자열 오프셋:
$s{0}→$s[0]. - 루프/스위치 외부의
break(PHP 8에서 치명적 오류). ${...}내의 가변 변수: bareword 인용 /${$var['k']}사용.
3. 시그니처, 정적 & null 안전
php scripts/check_signatures.php
각 MISMATCH에 대해 자식 메서드에 기본 파라미터를 추가하세요 (예: $tabla = null).
그런 다음 런타임에 나타나는 치명적 오류를 수정하세요:
| 오류 | 수정 |
|---|---|
ArgumentCountError: too few arguments | 후행 파라미터에 기본값 추가 |
정적 메서드에서 $this | self::/static:: 사용 또는 앱 컨텍스트 전달 |
method_exists(null, ...) | is_object($x) && method_exists($x, ...) |
Cannot access offset of type string on string | $x['k'] 전에 is_array($x) 재정렬 |
Undefined constant "X" | bareword 키/상수 인용 |
sizeof/count/array_keys(null) | is_array($x) ? ... : ..., (array)$x |
foreach(null) | foreach ((array)$x as ...) |
Accessing static property X as non static | $this->prop → self::$prop |
4. 실제 DB로 실행 및 반복
설정을 DB에 연결하고 모든 URL을 요청하세요. scripts/smoke-test.sh가 0 실패를 보고하고 로그에 경고가 없을 때까지 테스트당 하나의 치명적 오류를 수정하세요.
5. 보안 (조기에 수행)
- TimThumb을
templates/timthumb.php로 교체하세요. scanner.php,chmod777.php,info.php, 방치된 디버그 스크립트를 삭제하세요..htaccess가.env,.git,config/defines.php, dotfiles를 거부하도록 만드세요.- 커밋된 DB 비밀번호를 교체하고; 비밀을
.env로 옮기세요. - CSRF 토큰, CSP/HSTS, 속도 제한, 준비된 문(Prepared Statements)을 권장합니다.
6. 설정 + 배포
templates/defines.php(.env로더)와templates/env.example를 사용하세요.templates/htaccess와templates/user.ini를 사용하세요.deploy/deploy.sh로 배포하세요.
.env 시스템
config/defines.php는 프로젝트 루트에서 .env를 로드하며, getenv()로 대체하고 최종적으로 안전한 기본값으로 폴백합니다. 이는 동일한 DB_* 키를 사용하여 Docker가 계속 작동하도록 유지하면서, FTP 배포를 단일 파일 편집으로 만듭니다.
.env (커밋 금지):
DB_HOST=localhost
DB_NAME=cpaneluser_termospa
DB_USER=cpaneluser_termospa
DB_PASS=super-secret
DB_SUBDIRECTORIO=
배포 (Docker 없음)
공유 호스팅 (cPanel/Plesk) 체크리스트
- PHP: 8.3 (또는 8.1+) 선택;
mysqli,gd,mbstring,pdo_mysql활성화. - DB: DB + 사용자 생성, 덤프 가져오기. MySQL 8의 경우:
SET SESSION sql_mode='NO_ENGINE_SUBSTITUTION';utf8_spanish_ci→utf8mb3_spanish_ci경고 예상 (또는 utf8mb4 마이그레이션 실행). - 파일:
public_html/에 업로드 (docker/,tools/,router.php,_DOCS/,.git/제외). - 권한: 디렉토리
755, 파일644;recursos/cache/,.cache/,upload/쓰기 가능 (775/777). - 설정: 원격
.env생성 (deploy.sh가 수행) 및DB_*확인. .htaccess에서.env액세스 차단.
deploy.sh
./deploy.sh ftp # lftp 역방향 미러
./deploy.sh ftp --dry-run
./deploy.sh rsync # SSH를 통한 rsync
이 스크립트는 .env (FTP_HOST/USER/PASS/PATH/TLS 또는 SSH_*)를 읽고, 런타임 파일만 스테이징하며, 서버에 FTP 자격 증명이 저장되지 않도록 DB_*만 포함하는 원격 전용 .env를 작성하고, 업로드한 후 권한/DB 단계를 출력합니다.
검증 체크리스트
-
scripts/lint-all.sh→ 모두 깨끗 -
scripts/smoke-test.sh urls.txt→ 0 실패 - 홈 / 제품 / 프로젝트 / 뉴스 / 연락처 페이지 렌더링
-
/sitemap.xml및/rss가 유효한 XML 반환 -
/imagenes/thumbnail/...가 이미지 반환 (GD + 재작성) -
/administracion/login/로드; 로그인 및 콘텐츠 관리자 작동 - 연락처 양식 제출
- 관리자 이미지 업로드가
upload/에 쓰기 - 오류 로그에
PHP Warning/Fatal없음
항상 문제를 일으키는 함정
mysqli_query는 PHP 8.1+에서 기본적으로 예외를 던짐;mysqli_report(MYSQLI_REPORT_OFF)를 호출하여 레거시or die()/if($q=...)가 계속 작동하도록 하세요..htaccess의php_flag/php_value는 PHP-FPM에서 HTTP 500을 유발 —.user.ini를 사용하세요.- PHP 8의 균일 변수 구문은
$$var['key']를 조용히 깨뜨림 (잘못된 변수에 씀) —fix_variable_variables.php를 실행하세요. include()의 상대 경로는 스크립트 디렉토리/CWD를 기준으로 해석됨;__DIR__을 선호하세요.- PHP 8에서 사라짐:
mysql_*,ereg*,split,create_function,each, magic quotes. - OPcache는 오래된 파일을 캐시함: 편집 후 FPM/Apache를 다시 시작하세요.
- UTF-8:
SET NAMES utf8mb4; 새 작업에서는 InnoDB +utf8mb4_unicode_ci를 선호하세요.
유사 프로젝트
이러한 CMS 프로젝트는 동일한 아키텍처를 공유합니다. 부트스트랩 경로와 썸네일 재작성 대상을 조정하여 동일한 절차를 따르세요. scripts/를 대상의 tools/에 복사하고, 프로젝트 루트에서 실행하세요.