PHP 버전 업그레이드 시 deprecated 함수로 인한 경고나 오류를 해결하는 방법을 알아보겠습니다. 안전하고 효율적인 대체 방법들을 제시합니다.
문제: PHP 7.0에서 완전히 제거된 mysql_* 함수들
해결책: PDO 또는 MySQLi로 마이그레이션
// 기존 mysql_* 함수 (제거됨)
// $conn = mysql_connect($host, $user, $pass);
// $result = mysql_query("SELECT * FROM users");
// PDO로 대체
class DatabaseHelper {
private $pdo;
public function __construct($host, $dbname, $user, $pass) {
try {
$this->pdo = new PDO(
"mysql:host=$host;dbname=$dbname;charset=utf8mb4",
$user, $pass,
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
} catch (PDOException $e) {
throw new Exception("DB 연결 실패: " . $e->getMessage());
}
}
public function query($sql, $params = []) {
$stmt = $this->pdo->prepare($sql);
$stmt->execute($params);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
public function insert($table, $data) {
$columns = implode(',', array_keys($data));
$placeholders = ':' . implode(', :', array_keys($data));
$sql = "INSERT INTO $table ($columns) VALUES ($placeholders)";
$stmt = $this->pdo->prepare($sql);
return $stmt->execute($data);
}
}
문제: PHP 7.2에서 deprecated, PHP 8.0에서 제거
해결책: foreach 또는 array 함수로 대체
// 기존 each() 사용 (deprecated)
// while (list($key, $value) = each($array)) {
// echo "$key => $value\n";
// }
// foreach로 대체 (권장)
function processArrayModern($array) {
foreach ($array as $key => $value) {
echo "$key => $value\n";
}
}
// each() 동작을 완전히 재현해야 하는 경우
class ArrayIteratorHelper {
public static function each(&$array) {
$key = key($array);
if ($key === null) {
return false;
}
$value = current($array);
next($array);
return [
0 => $key,
1 => $value,
'key' => $key,
'value' => $value
];
}
// 더 현대적인 방법
public static function processWithGenerator($array) {
foreach ($array as $key => $value) {
yield ['key' => $key, 'value' => $value];
}
}
}
// 사용 예시
$data = ['a' => 1, 'b' => 2, 'c' => 3];
// 기존 방식 대체
foreach (ArrayIteratorHelper::processWithGenerator($data) as $item) {
echo "{$item['key']} => {$item['value']}\n";
}
문제: PHP 7.2에서 deprecated, PHP 8.0에서 제거
해결책: 익명 함수(클로저) 사용
// 기존 create_function() 사용 (deprecated)
// $func = create_function('$a,$b', 'return $a + $b;');
// 익명 함수로 대체
$func = function($a, $b) {
return $a + $b;
};
// 동적 함수 생성이 필요한 경우
class FunctionFactory {
public static function createMathFunction($operation) {
switch ($operation) {
case 'add':
return function($a, $b) { return $a + $b; };
case 'multiply':
return function($a, $b) { return $a * $b; };
case 'power':
return function($a, $b) { return pow($a, $b); };
default:
throw new InvalidArgumentException("Unknown operation: $operation");
}
}
// 문자열 기반 함수 생성 (주의해서 사용)
public static function createFromString($params, $body) {
// 보안상 위험하므로 가능한 피하고, 필요시 검증 추가
$code = "return function($params) { $body };";
return eval($code);
}
}
// 사용 예시
$addFunc = FunctionFactory::createMathFunction('add');
echo $addFunc(5, 3); // 8
문제: PHP 7.0에서 제거된 POSIX 정규표현식 함수들
해결책: PCRE 함수로 마이그레이션
// 기존 ereg_* 함수들 (제거됨)
// ereg(), eregi(), ereg_replace(), eregi_replace()
class RegexHelper {
// ereg() 대체
public static function match($pattern, $string, &$matches = null) {
// POSIX를 PCRE 패턴으로 변환
$pcrePattern = '/' . $pattern . '/';
return preg_match($pcrePattern, $string, $matches);
}
// eregi() 대체 (대소문자 무시)
public static function matchIgnoreCase($pattern, $string, &$matches = null) {
$pcrePattern = '/' . $pattern . '/i';
return preg_match($pcrePattern, $string, $matches);
}
// ereg_replace() 대체
public static function replace($pattern, $replacement, $string) {
$pcrePattern = '/' . $pattern . '/';
return preg_replace($pcrePattern, $replacement, $string);
}
// 일반적인 패턴 변환 도우미
public static function convertPosixToPcre($posixPattern) {
// 기본적인 POSIX -> PCRE 변환
$conversions = [
'\<' => '\b', // 단어 경계
'\>' => '\b',
'[:alnum:]' => 'a-zA-Z0-9',
'[:alpha:]' => 'a-zA-Z',
'[:digit:]' => '0-9'
];
$pcrePattern = $posixPattern;
foreach ($conversions as $posix => $pcre) {
$pcrePattern = str_replace($posix, $pcre, $pcrePattern);
}
return '/' . $pcrePattern . '/';
}
}
// 사용 예시
$text = "Hello World 123";
if (RegexHelper::matchIgnoreCase('[a-z]+', $text, $matches)) {
echo "매치됨: " . $matches[0];
}
문제: 코드베이스 전체의 deprecated 함수 사용 현황 파악
해결책: 자동 감지 및 대체 도구 구현
class DeprecatedFunctionHandler {
private static $deprecatedFunctions = [
'mysql_connect' => 'PDO 또는 MySQLi 사용',
'mysql_query' => 'PDO prepare/execute 사용',
'each' => 'foreach 사용',
'create_function' => '익명 함수 사용',
'ereg' => 'preg_match 사용',
'eregi' => 'preg_match with /i flag 사용',
'split' => 'explode 또는 preg_split 사용'
];
public static function checkCode($code) {
$issues = [];
foreach (self::$deprecatedFunctions as $func => $suggestion) {
if (preg_match('/\b' . preg_quote($func) . '\s*\(/', $code)) {
$issues[] = [
'function' => $func,
'suggestion' => $suggestion,
'line' => self::findLineNumber($code, $func)
];
}
}
return $issues;
}
private static function findLineNumber($code, $function) {
$lines = explode("\n", $code);
foreach ($lines as $lineNum => $line) {
if (strpos($line, $function) !== false) {
return $lineNum + 1;
}
}
return null;
}
// 자동 대체 (간단한 경우만)
public static function autoReplace($code) {
$replacements = [
'/\beach\s*\(\s*\$([^)]+)\s*\)/' => 'foreach ($\1 as $key => $value)',
'/mysql_real_escape_string\s*\(\s*([^)]+)\s*\)/' => 'addslashes(\1)', // 임시 대체
];
foreach ($replacements as $pattern => $replacement) {
$code = preg_replace($pattern, $replacement, $code);
}
return $code;
}
// 파일 스캔
public static function scanFile($filepath) {
if (!file_exists($filepath)) {
throw new Exception("파일을 찾을 수 없습니다: $filepath");
}
$code = file_get_contents($filepath);
$issues = self::checkCode($code);
return [
'file' => $filepath,
'issues' => $issues,
'count' => count($issues)
];
}
}
// 사용 예시
$result = DeprecatedFunctionHandler::scanFile('legacy_code.php');
foreach ($result['issues'] as $issue) {
echo "라인 {$issue['line']}: {$issue['function']} - {$issue['suggestion']}\n";
}