이전 버전과 호환되지 않는 변경 사항

Changes to error and exception handling

많은 치명적이고 복구 가능한 치명적인 오류가 PHP 7에서 예외로 변환되었습니다. 이러한 오류 예외는 자체적으로 Throwable 인터페이스(모든 예외가 상속하는 새 기본 인터페이스)를 구현하는 Error 클래스에서 상속됩니다.

즉, 예외가 대신 throw될 수 있기 때문에 사용자 지정 오류 처리기가 더 이상 트리거되지 않을 수 있습니다(캐치되지 않은 Error 예외에 대해 새로운 치명적인 오류가 발생함).

PHP 7에서 오류가 작동하는 방식에 대한 자세한 설명은 PHP 7 오류 페이지에서 찾을 수 있습니다. 이 마이그레이션 가이드는 이전 버전과의 호환성에 영향을 미치는 변경 사항을 열거할 뿐입니다.

set_exception_handler() is no longer guaranteed to receive Exception objects

Exception의 유형 선언을 사용하여 set_exception_handler()로 등록된 예외 처리기를 구현하는 코드는 Error 개체가 throw될 때 치명적인 오류를 발생시킵니다.

핸들러가 PHP 5와 7 모두에서 작동해야 하는 경우 핸들러에서 유형 선언을 제거해야 합니다. 반면 PHP 7에서만 작동하도록 마이그레이션되는 코드는 예외 유형 선언을 대신 Throwable로 대체할 수 있습니다.

                  
<?php
// PHP 5 era code that will break.
function handler(Exception $e) { ... }
set_exception_handler('handler');

// PHP 5 and 7 compatible.
function handler($e) { ... }

// PHP 7 only.
function handler(Throwable $e) { ... }
?>
                  
                

Internal constructors always throw exceptions on failure

이전에는 생성자가 실패하면 일부 내부 클래스가 null 또는 사용할 수 없는 개체를 반환했습니다. 이제 모든 내부 클래스는 이 경우 사용자 클래스가 이미 했던 것과 같은 방식으로 예외를 발생시킵니다.

Parse errors throw ParseError

파서 오류는 이제 ParseError 개체를 발생시킵니다. eval()에 대한 오류 처리에는 이제 이 오류를 처리할 수 있는 catch 블록이 포함되어야 합니다.

E_STRICT notices severity changes

모든 E_STRICT 알림은 다른 수준으로 재분류되었습니다. E_STRICT 상수는 유지되므로 error_reporting(E_ALL|E_STRICT)과 같은 호출은 오류를 일으키지 않습니다.

E_STRICT notices severity changes

Situation New level/behaviour
Indexing by a resource E_NOTICE
Abstract static methods Notice removed, triggers no error
"Redefining" a constructor Notice removed, triggers no error
Signature mismatch during inheritance E_WARNING
Same (compatible) property in two used traits Notice removed, triggers no error
Accessing static property non-statically E_NOTICE
Only variables should be assigned by reference E_NOTICE
Only variables should be passed by reference E_NOTICE
Calling non-static methods statically E_DEPRECATED

Changes to variable handling

PHP 7은 이제 소스 파일을 구문 분석할 때 추상 구문 트리를 사용합니다. 이는 이전 버전의 PHP에서 사용된 파서의 제한으로 인해 이전에 불가능했던 언어에 대한 많은 개선을 허용했지만 일관성을 위해 몇 가지 특별한 경우를 제거하여 이전 버전과의 호환성이 중단되었습니다. 이러한 경우는 이 섹션에서 자세히 설명합니다.

Changes to the handling of indirect variables, properties, and methods

변수, 속성 및 메서드에 대한 간접 액세스는 이제 이전의 특수한 경우와 달리 왼쪽에서 오른쪽 순서로 엄격하게 평가됩니다. 아래 표는 평가 순서가 어떻게 변경되었는지 보여줍니다.

Old and new evaluation of indirect expressions

Expression PHP 5 interpretation PHP 7 interpretation
$$foo['bar']['baz'] ${$foo['bar']['baz']} ($$foo)['bar']['baz']
$foo->$bar['baz'] $foo->{$bar['baz']} ($foo->$bar)['baz']
$foo->$bar['baz']() $foo->{$bar['baz']}() ($foo->$bar)['baz']()
Foo::$bar['baz']() Foo::{$bar['baz']}() (Foo::$bar)['baz']()

이전 오른쪽에서 왼쪽 평가 순서를 사용한 코드는 중괄호와 함께 해당 평가 순서를 명시적으로 사용하도록 다시 작성해야 합니다(위의 중간 열 참조). 이렇게 하면 코드가 PHP 7.x와 앞으로 호환되고 PHP 5.x와 역호환이 됩니다.

이는 global 키워드에도 영향을 줍니다. 필요한 경우 중괄호 구문을 사용하여 이전 동작을 에뮬레이트할 수 있습니다.

                  
<?php
function f() {
    // Valid in PHP 5 only.
    global $$foo->bar;

    // Valid in PHP 5 and 7.
    global ${$foo->bar};
}
?>
                  
                

Changes to list() handling

list() no longer assigns variables in reverse order

list()는 이제 역순이 아니라 정의된 순서대로 변수에 값을 할당합니다. 일반적으로 이는 아래와 같이 list()가 array [] 연산자와 함께 사용되는 경우에만 영향을 미칩니다.

                  
<?php
list($a[], $a[], $a[]) = [1, 2, 3];
var_dump($a);
?>
                  
                

PHP 5에서 위 예제의 출력:

array(3) {
  [0]=>
  int(3)
  [1]=>
  int(2)
  [2]=>
  int(1)
}
                

PHP 7에서 위 예제의 출력:

array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
}
                

일반적으로 list() 할당이 발생하는 순서에 의존하지 않는 것이 좋습니다. 이는 나중에 다시 변경될 수 있는 구현 세부 사항이기 때문입니다.

Empty list() assignments have been removed

list() 구문은 더 이상 비워둘 수 없습니다. 다음은 더 이상 허용되지 않습니다.

                  
<?php
list() = $a;
list(,,) = $a;
list($x, list(), $y) = $a;
?>
                  
                

list()는 문자열의 압축을 풀 수 없습니다

list()는 더 이상 문자열 변수의 압축을 풀 수 없습니다. 대신 str_split()을 사용해야 합니다.

Array ordering when elements are automatically created during by reference assignments has changed

참조 할당에서 해당 요소를 참조하여 자동으로 생성된 경우 배열의 요소 순서가 변경되었습니다. 예를 들어:

                  
<?php
$array = [];
$array["a"] =& $array["b"];
$array["b"] = 1;
var_dump($array);
?>
                  
                

PHP 5에서 위 예제의 출력:

array(2) {
  ["b"]=>
  &int(1)
  ["a"]=>
  &int(1)
}
                

PHP 7에서 위 예제의 출력:

array(2) {
  ["a"]=>
  &int(1)
  ["b"]=>
  &int(1)
}
                

Parentheses around function arguments no longer affect behaviour

PHP 5에서 함수 인수 주위에 중복 괄호를 사용하면 함수 인수가 참조로 전달될 때 엄격한 표준 경고를 완화할 수 있습니다. 경고는 이제 항상 발행됩니다.

                  
<?php
function getArray() {
    return [1, 2, 3];
}

function squareArray(array &$a) {
    foreach ($a as &$v) {
        $v **= 2;
    }
}

// Generates a warning in PHP 7.
squareArray((getArray()));
?>
                  
                

위의 예는 다음을 출력합니다.

Notice: Only variables should be passed by reference in /tmp/test.php on line 13
                

Changes to foreach

주로 내부 배열 포인터 처리 및 반복되는 배열 수정과 관련된 foreach 제어 구조의 동작이 약간 변경되었습니다.

                  
<?php
$array = [0, 1, 2];
foreach ($array as &$val) {
    var_dump(current($array));
}
?>
                  
                

PHP 5에서 위 예제의 출력:

int(1)
int(2)
bool(false)
                

PHP 7에서 위 예제의 출력:

int(0)
int(0)
int(0)
                

foreach by-value operates on a copy of the array

기본 값 기준 모드에서 사용할 때 foreach는 이제 배열 자체가 아니라 반복되는 배열의 복사본에서 작동합니다. 이는 반복 중에 수행된 배열 변경 사항이 반복되는 값에 영향을 미치지 않음을 의미합니다.

foreach by-reference has improved iteration behaviour

참조로 반복할 때 foreach는 이제 반복 중에 이루어진 배열의 변경 사항을 더 잘 추적합니다. 예를 들어, 반복하는 동안 배열에 추가하면 이제 추가된 값도 반복됩니다.

                  
<?php
$array = [0];
foreach ($array as &$val) {
    var_dump($val);
    $array[1] = 1;
}
?>
                  
                

PHP 5에서 위 예제의 출력:

int(0)
                

PHP 7에서 위 예제의 출력:

int(0)
int(1)
                

Iteration of non-Traversable objects

Traversable이 아닌 객체에 대한 반복은 이제 참조에 의한 배열에 대한 반복과 동일한 동작을 갖습니다. 그 결과 객체에 속성을 추가하거나 객체에서 제거할 때도 적용되는 반복 중에 배열을 수정할 때 향상된 동작이 발생합니다.


Changes to int handling

Invalid octal literals

이전에는 유효하지 않은 숫자가 포함된 8진수 리터럴이 자동으로 잘렸습니다(0128은 012로 간주됨). 이제 잘못된 8진수 리터럴로 인해 구문 분석 오류가 발생합니다.

Negative bitshifts

음수에 의한 비트 시프트는 이제 ArithmeticError를 발생시킵니다:

                  
<?php
var_dump(1 >> -1);
?>
                  
                

PHP 5에서 위 예제의 출력:

int(0)
                

PHP 7에서 위 예제의 출력:

Fatal error: Uncaught ArithmeticError: Bit shift by negative number in /tmp/test.php:2
Stack trace:
#0 {main}
  thrown in /tmp/test.php on line 2
                

Out of range bitshifts

int의 비트 너비를 초과하는 비트 시프트(어느 방향이든)는 항상 0이 됩니다. 이전에는 이러한 시프트의 동작이 아키텍처에 따라 다릅니다.

Changes to Division By Zero

이전에는 나누기(/) 또는 모듈러스(%) 연산자의 제수로 0을 사용하면 E_WARNING이 발생하고 false가 반환되었습니다. 이제 나누기 연산자는 IEEE 754에 지정된 대로 부동 소수점을 +INF, -INF 또는 NAN으로 반환합니다. 모듈러스 연산자 E_WARNING이 제거되었으며 DivisionByZeroError 예외가 발생합니다.

                  
<?php
var_dump(3/0);
var_dump(0/0);
var_dump(0%0);
?>
                  
                

PHP 5에서 위 예제의 출력:

Warning: Division by zero in %s on line %d
bool(false)

Warning: Division by zero in %s on line %d
bool(false)

Warning: Division by zero in %s on line %d
bool(false)
                

PHP 7에서 위 예제의 출력:

Warning: Division by zero in %s on line %d
float(INF)

Warning: Division by zero in %s on line %d
float(NAN)

PHP Fatal error:  Uncaught DivisionByZeroError: Modulo by zero in %s line %d
                

Changes to string handling

Hexadecimal strings are no longer considered numeric

16진수를 포함하는 문자열은 더 이상 숫자로 간주되지 않습니다. 예를 들어:

                  
<pre>
                  <code class="language-php">
&#x3C;?php phpinfo(); ?&#x3E;
                  </code>
                </pre>
                  
                

PHP 5에서 위 예제의 출력:

bool(true)
bool(true)
int(15)
string(2) "oo"
                

PHP 7에서 위 예제의 출력:

bool(false)
bool(false)
int(0)

Notice: A non well formed numeric value encountered in /tmp/test.php on line 5
string(3) "foo"
                

filter_var()는 문자열에 16진수가 포함되어 있는지 확인하고 해당 유형의 문자열을 int로 변환하는 데 사용할 수 있습니다.

                  
<?php
$str = "0xffff";
$int = filter_var($str, FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX);
if (false === $int) {
    throw new Exception("Invalid integer!");
}
var_dump($int); // int(65535)
?>
                  
                

\u{ may cause errors

새로운 유니코드 코드포인트 이스케이프 구문의 추가로 인해 리터럴 \u{ 뒤에 잘못된 시퀀스가 ​​포함된 문자열은 치명적인 오류를 일으킬 것입니다. 이를 방지하려면 선행 백슬래시를 이스케이프해야 합니다.


Removed functions

call_user_method() and call_user_method_array()

이 함수는 call_user_func()call_user_func_array()를 위해 PHP 4.1.0에서 더 이상 사용되지 않습니다. 변수 함수 및/또는 ... 연산자 사용을 고려할 수도 있습니다.

All ereg* functions

모든 ereg 기능이 제거되었습니다. PCRE는 권장되는 대안입니다.

mcrypt aliases

더 이상 사용되지 않는 mcrypt_generic_end() 함수는 mcrypt_generic_deinit()를 위해 제거되었습니다.

또한 적절한 MCRYPT_MODE_* 상수와 함께 mcrypt_decrypt()를 사용하기 위해 더 이상 사용되지 않는 mcrypt_ecb(), mcrypt_cbc(), mcrypt_cfb() 및 mcrypt_ofb() 함수가 제거되었습니다.

All ext/mysql functions

모든 ext/mysql 함수는 제거되었습니다. 다른 MySQL API 선택에 대한 자세한 내용은 MySQL API 선택을 참조하십시오.

All ext/mssql functions

모든 ext/mssql 함수가 제거되었습니다.

intl aliases

더 이상 사용되지 않는 datefmt_set_timezone_id() 및 IntlDateFormatter::setTimeZoneID() 별칭이 각각 datefmt_set_timezone()IntlDateFormatter::setTimeZone()을 위해 제거되었습니다.

set_magic_quotes_runtime()

set_magic_quotes_runtime()은 별칭 magic_quotes_runtime()과 함께 제거되었습니다. PHP 5.3.0에서 더 이상 사용되지 않으며 PHP 5.4.0에서 마법 따옴표가 제거되면서 사실상 작동하지 않게 되었습니다.

set_socket_blocking()

사용되지 않는 set_socket_blocking() 별칭이 stream_set_blocking()을 위해 제거되었습니다.

dl() in PHP-FPM

dl()은 더 이상 PHP-FPM에서 사용할 수 없습니다. CLI에서 계속 작동하며 SAPI를 포함합니다.

GD Type1 functions

PostScript Type1 글꼴에 대한 지원이 GD 확장에서 제거되어 다음 기능이 제거되었습니다.

  • imagepsbbox()
  • imagepsencodefont()
  • imagepsextendfont()
  • imagepsfreefont()
  • imagepsloadfont()
  • imagepsslantfont()
  • imagepstext()

대신 TrueType 글꼴 및 관련 기능을 사용하는 것이 좋습니다.


Removed INI directives

Removed features

다음 INI 지시문은 관련 기능도 제거되었으므로 제거되었습니다.

  • always_populate_raw_post_data
  • asp_tags

xsl.security_prefs

xsl.security_prefs 지시문이 제거되었습니다. 대신 XsltProcessor::setSecurityPrefs() 메서드를 호출하여 프로세서별로 보안 기본 설정을 제어해야 합니다.


Other backward incompatible changes

New objects cannot be assigned by reference

new statement는 더 이상 참조로 변수에 할당할 수 없습니다.

                  
<?php
class C {}
$c =& new C;
?>
                  
                

PHP 5에서 위 예제의 출력:

Deprecated: Assigning the return value of new by reference is deprecated in /tmp/test.php on line 3
                

PHP 7에서 위 예제의 출력:

Parse error: syntax error, unexpected 'new' (T_NEW) in /tmp/test.php on line 3
                

Invalid class, interface and trait names

다음 이름은 클래스, 인터페이스 또는 특성의 이름을 지정하는 데 사용할 수 없습니다.

  • bool
  • int
  • float
  • string
  • null
  • true
  • false

또한 다음과 같은 이름을 사용해서는 안 됩니다. PHP 7.0에서는 오류가 발생하지 않지만 향후 사용을 위해 예약되어 있으며 더 이상 사용되지 않는 것으로 간주해야 합니다.

  • resource
  • object
  • mixed
  • numeric

ASP and script PHP tags removed

ASP 및 스크립트 태그를 사용하여 PHP 코드를 구분하는 지원이 제거되었습니다. 영향을 받는 태그는 다음과 같습니다.

Removed ASP and script tags

Opening tag Closing tag
<% %>
<%= %>
<script language="php"> </script>

Calls from incompatible context removed

이전에 PHP 5.6에서 더 이상 사용되지 않는 컨텍스트가 있는 비정적 메서드에 대한 정적 호출은 이제 호출된 메서드에 정의되지 않은 $this 변수와 사용 중단 경고가 발생하게 됩니다.

                  
<?php
class A {
    public function test() { var_dump($this); }
}

// Note: Does NOT extend A
class B {
    public function callNonStaticMethodOfA() { A::test(); }
}

(new B)->callNonStaticMethodOfA();
?>
                  
                

PHP 5.6에서 위 예제의 출력:

Deprecated: Non-static method A::test() should not be called statically, assuming $this from incompatible context in /tmp/test.php on line 8
object(B)#1 (0) {
}
                

PHP 7에서 위 예제의 출력:

Deprecated: Non-static method A::test() should not be called statically in /tmp/test.php on line 8

Notice: Undefined variable: this in /tmp/test.php on line 3
NULL
                

yield is now a right associative operator

yield 구문은 더 이상 괄호를 필요로 하지 않으며 print와 => 사이의 우선 순위를 갖는 오른쪽 연관 연산자로 변경되었습니다. 이로 인해 동작이 변경될 수 있습니다.

                  
<?php
echo yield -1;
// Was previously interpreted as
echo (yield) - 1;
// And is now interpreted as
echo yield (-1);

yield $foo or die;
// Was previously interpreted as
yield ($foo or die);
// And is now interpreted as
(yield $foo) or die;
?>
                  
                

괄호를 사용하여 이러한 경우를 명확하게 할 수 있습니다.

Functions cannot have multiple parameters with the same name

더 이상 같은 이름으로 두 개 이상의 함수 매개변수를 정의할 수 없습니다. 예를 들어 다음 함수는 E_COMPILE_ERROR를 트리거합니다.

                  
<?php
function foo($a, $b, $unused, $unused) {
    //
}
?>
                  
                

Functions inspecting arguments report the current parameter value

func_get_arg(), func_get_args(), debug_backtrace() 및 예외 역추적은 더 이상 매개변수에 전달된 원래 값을 보고하지 않지만 대신 현재 값(수정되었을 수 있음)을 제공합니다.

                  
<?php
function foo($x) {
    $x++;
    var_dump(func_get_arg(0));
}
foo(1);?>
                  
                

PHP 5에서 위 예제의 출력:

1
                

PHP 7에서 위 예제의 출력:

2
                

Switch statements cannot have multiple default blocks

switch 문에서 두 개 이상의 기본 블록을 더 이상 정의할 수 없습니다. 예를 들어 다음 switch 문은 E_COMPILE_ERROR를 트리거합니다.

                  
<?php
switch (1) {
    default:
    break;
    default:
    break;
}
?>
                  
                

$HTTP_RAW_POST_DATA removed

$HTTP_RAW_POST_DATA는 더 이상 사용할 수 없습니다. 대신 php://input 스트림을 사용해야 합니다.

# comments in INI files removed

INI 파일에서 주석 접두사에 대한 지원이 제거되었습니다. ; (세미콜론)을 대신 사용해야 합니다. 이 변경 사항은 php.ini와 parse_ini_file()parse_ini_string()이 처리하는 파일에 적용됩니다.

JSON extension replaced with JSOND

JSON 확장이 JSOND로 대체되어 세 가지 사소한 BC 중단이 발생했습니다. 첫째, 숫자는 소수점으로 끝나지 않아야 합니다(즉, 34.는 34.0 또는 34로 변경되어야 함). 둘째, 과학적 표기법을 사용할 때 e 지수는 소수점 바로 뒤에 오면 안 됩니다(즉, 3.e3을 3.0e3 또는 3e3으로 변경해야 함). 마지막으로 빈 문자열은 더 이상 유효한 JSON으로 간주되지 않습니다.

Internal function failure on overflow

이전에는 float가 정수로 표현하기에 너무 큰 경우 내부 함수가 float-to-integer 강제 변환에서 생성된 숫자를 자동으로 자릅니다. 이제 E_WARNING이 발생하고 null이 반환됩니다.

Fixes to custom session handler return values

false 또는 -1을 반환하는 사용자 정의 세션 핸들러에 의해 구현된 모든 술어 함수는 치명적인 오류가 됩니다. 부울, -1 또는 0 이외의 이러한 함수의 값이 반환되면 실패하고 E_WARNING이 발생합니다.

Sort order of equal elements

내부 정렬 알고리즘이 개선되어 이전과 동일한 것으로 비교되는 요소의 정렬 순서가 다를 수 있습니다.

메모: 동일한 것으로 비교되는 요소의 순서에 의존하지 마십시오. 언제든지 바뀔 수 있습니다.

Misplaced break and switch statements

루프 또는 스위치 제어 구조 외부의 break 및 continue 문은 이제 이전과 같이 런타임 대신 컴파일 시간에 감지되고 E_COMPILE_ERROR를 트리거합니다.

Mhash is not an extension anymore

Mhash 확장은 Hash 확장에 완전히 통합되었습니다. 따라서 extension_loaded()를 사용하여 더 이상 Mhash 지원을 감지할 수 없습니다. 대신 function_exists()를 사용하십시오. 또한, Mhash는 더 이상 get_loaded_extensions() 및 관련 기능에 의해 보고되지 않습니다.

declare(ticks)

declare(ticks) 지시문은 더 이상 다른 컴파일 단위로 누출되지 않습니다.