PHP 5부터 7까지의 주요 변화와 새로운 기능

PHP 5부터 7까지의 주요 변화와 새로운 기능:

1.성능 향상 - PHPNG 코드가 PHP 7에 통합되어 PHP 5보다 두 배 빠름 - 상세 설명 필요 2.메모리 사용량 감소 - 최적화된 PHP 7은 더 적은 자원을 사용함 - 상세 설명 필요

//PHP7은 새로운 Zend Engine 3.0을 사용하여 애플리케이션 성능을 두 배로 향상시키고, PHP5.6보다 50% 적은 메모리를 소모합니다.
//추가 하드웨어 없이 더 많은 동시 사용자를 서비스할 수 있습니다.
/**
Magento 트랜잭션 실행 시 PHP7은 PHP5.6보다 두 배 빠릅니다.
Drupal 트랜잭션 실행 시 PHP7은 PHP5.6보다 두 배 빠릅니다.
WordPress 트랜잭션 실행 시 PHP7이 PHP5.6보다 두 배 빠름을 입증했습니다.
*/

3.스칼라 타입 선언 - 이제 매개변수와 반환값 타입을 강제할 수 있습니다(강한 타입 언어)

/**
(string, int, float, bool, interfaces, array, callable, 클래스명) 지원
- 7.1에서 Nullable, void, iterable 추가 (callable과 유사, Traversable 인터페이스 구현 객체)
- 7.2에서 object 추가 (逆变(contravariant) 매개변수 입력과 모든 객체 타입의协变(covariant) 반환에 사용)
- 7.4에서 클래스 속성에 타입 지정 지원
ps:
별칭은 지원되지 않습니다. 예: boolean, integer.
callable은 호출 가능한 함수로 이해할 수 있습니다. (is_callable()로 확인 가능, callback 개념과 관련)
*/
// 강제 모드 (기본값) 
function sumOfInts(int ...$ints) // 스칼라 타입 선언 int형
{
    return array_sum($ints);
}

var_dump(sumOfInts(2, '3', 4.1)); //int(9)
function arraysSum(array ...$arrays): array // 반환값 타입 선언 배열형
{
    return array_map(function(array $array): int {
        return array_sum($array);
    }, $arrays);
}

print_r(arraysSum([1,2,3], [4,5,6], [7,8,9])); 
//Array([0]=>6[1]=>15[2]=>24)
declare (strict_types = 1); // 엄격 모드 활성화, 매개변수 타입 검사, 불일치 시 오류 발생
// 널 가능(Nullable) 타입 (PHP7.1)
// 매개변수 및 반환값 타입은 이제 타입 앞에 물음표를 추가하여 null을 허용할 수 있습니다.
function testReturn(): ?string {}
// Void 함수 (PHP7.1)
// 새로운 반환값 타입 void가 도입되었습니다. 반환값이 void로 선언된 메서드는 return 문을 생략하거나 빈 return 문을 사용해야 합니다. void 함수의 경우 null은 유효한 반환값이 아닙니다.
function swap(&$left, &$right) : void {}
// 7.4 제한된 반환 타입의协变과 매개변수 타입의逆变 (상속 관계)
class A {}
class B extends A {}

class Producer {
    public function method(): A {}
}
class ChildProducer extends Producer {
    public function method(): B {}
}

4.일관된 64비트 지원 - 64비트 아키텍처 머신에서의 지원 지속

phpinfo(); // 아키텍처
// 32비트 PHP는 4바이트, 64비트 PHP는 8바이트
if (PHP_INT_SIZE == 4) {
    $bit = 32;
} else {
    $bit = 64;
}

5.1.개선된 예외 계층 구조 - 예외 계층 구조가 개선되었습니다.

PHP 7은 대부분의 오류 보고 방식을 변경했습니다. 기존(PHP 5)의 오류 보장 메커니즘과 달리, 이제 대부분의 오류가 Error 예외로 발생합니다.

이러한 Error 예외는 일반적으로 Exception 예외와 마찬가지로 첫 번째 일치하는 try/catch 블록에 의해 포착될 수 있습니다. 일치하는 catch 블록이 없으면, 예외 처리기(사전에 set_exception_handler()로 등록된)가 호출됩니다. 아직 예외 처리기가 등록되지 않았다면, 기존 방식으로 처리됩니다: 치명적인 오류(Fatal Error)로 보고됩니다.

Error 클래스는 Exception 클래스에서 상속되지 않으므로 catch (Exception e)...로 Error를 포착할 수 없습니다. catch(Error e) { ... }를 사용하거나 예외 처리기(set_exception_handler())를 등록하여 Error를 포착할 수 있습니다.

/**
예외 계층 구조
Throwable
 Error
  ArithmeticError
   DivisionByZeroError
  AssertionError
  ParseError
  TypeError
 Exception
 */

5.2.많은 치명적 오류가 예외로 변환됨 - 예외의 범위가 확대되어 많은 치명적 오류가 예외로 변환됩니다

(5,6)php5.6.x에서 PHP7.0.x로의 비호환성 변경

<?php
// set_exception_handler()가 더 이상 Exception 객체를 받는다고 보장하지 않음
// PHP 5 시대의 코드가 문제를 일으킬 것입니다
function handler(Exception $e) { ... }
set_exception_handler('handler');

// PHP 5 및 7 호환
function handler($e) { ... }

// PHP 7만 지원
function handler(Throwable $e) { ... }
?>
// E_STRICT 경고 수준 변경

| 시나리오 | 새로운 수준/동작 |
|---|---|
| 추상 정적 메서드 | 더 이상 경고하지 않으며 오류 발생 |
| 중복된 생성자 함수 정의 | 더 이상 경고하지 않으며 오류 발생 |
| 상속 시 메서드 시그니처 불일치 | E_WARNING |
| 두 trait에 동일한(호환되는) 속성 포함 | 더 이상 경고하지 않으며 오류 발생 |
| 비정적 방식으로 정적 속성에 접근 | E_NOTICE |
| 변수가 참조로 할당되어야 함 | E_NOTICE |
| 변수가 참조로 전달되어야 함 | E_NOTICE |
| 정적 방식으로 인스턴스 메서드 호출 | E_DEPRECATED |

6.사용되지 않는 API 및 확장 삭제 - 다양한 오래되고 지원되지 않는 애플리케이션 및 확장이 최신 버전에서 삭제됨

함수
/**
call_user_method(), call_user_method_array()
모든 ereg* 함수
mcrypt 별칭
모든 ext/mysql 함수
intl 별칭
......
*/
INI
/**
always_populate_raw_post_data
asp_tags
*/

7.배열, 반복문 등 처리 변경

/**
list() 역순 할당 수정 (배열에만 영향)
배열 생성 순서 수정
함수 매개변수 근처의 괄호가 더 이상 동작에 영향을 미치지 않음 (일부 허용되지 않는 함수 중첩 동작, 5에서는 ()로 처리 가능했으나 7에서 수정됨)
foreach 내부 포인터 변경 문제 수정
foreach로 값 순회 시 배열의 복사본을 작업 (없음, &$arr 수정은 $v 사용 시 트리거되지 않음, 예: unset($arr[0]) 후 $arr[0]가 나타내는 $v는 여전히 정상적으로 사용 가능? 5도 그런지 테스트 필요)
foreach로 참조 순회 시 더 나은 반복 특성 (반복 중 변경을 더 잘 추적)
*/
// list() 역순 할당 수정 (배열에만 영향)
list($a[], $a[], $a[]) = [1, 2, 3];

var_dump($a);
// 5 => 3,2,1
// 7 => 1,2,3
// 배열 생성 순서 수정
$array = [];
$array["a"] =& $array["b"];
$array["b"] = 1;

var_dump($array);
// 5 => ["b"=>&int(1),"a"=>&int(1)]
// 7 => ["a"=>&int(1),"b"=>&int(1)]
// 함수 매개변수 근처의 괄호가 더 이상 동작에 영향을 미치지 않음 (일부 허용되지 않는 함수 중첩 동작, 5에서는 ()로 처리 가능했으나 7에서 수정됨)
function getArray() {
    return [1, 2, 3];
}

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

// PHP 7에서 경고 생성
squareArray((getArray()));
// foreach 내부 포인터 변경 문제 수정
$array = [0, 1, 2];
foreach ($array as &$val) {
    var_dump(current($array));
}
// 5 => 1,2,false
// 7 => 0,0,0
// foreach로 참조 순회 시 더 나은 반복 특성 (반복 중 변경을 더 잘 추적)
$array = [0];
foreach ($array as &$val) {
    var_dump($val);
    $array[1] = 1;
}
// 5 => 0
// 7 => 0,1

8.정수, 문자열 처리 변경

INT
/**
유효하지 않은 8진수 문자, 이제 오류 발생 (8진수 문자의 유효하지 않은 숫자, 이전에는 자동으로 잘림)
음의 시프트 연산, 이제 오류 발생
범위를 초과한 시프트. 이전에는 오버플로우(원문: 이 작업은 구조에 의존), 이제 항상 0을 반환.
0으로 나누기 변경
*/
// 0으로 나누기 변경
// 나눗셈 연산자 (/)는 이제 IEEE 754에서 지정하는 부동소수점 수를 반환: +INF, -INF 또는 NAN. 나머지 연산자 (%)는 DivisionByZeroError 예외를 발생시키며 더 이상 E_WARNING 오류를 생성하지 않음
var_dump(3/0);
var_dump(0/0);
var_dump(0%0);
// 5 => false,false,false(세 개의 warning)
// 7 => float(INF),float(NAN),치명적 오류(앞 두 개는 warning)
String
/**
16진수 문자열이 더 이상 숫자로 간주되지 않음 (filter_var() 함수를 사용하여 문자열이 16진수를 포함하는지 확인하고 정수로 변환할 수 있음. 반환값은 false 또는 int)
유니코드 출력 지원, 이로 인해 해당 문자열을 사용할 때 주의 필요 - '\u{'.
*/
// 유니코드 출력
echo '\u{UNICODE_CODE}'; // 해당 유니코드 문자 출력

9.문법 설탕

// <=> (우주선 연산자|비교 연산자)
$a <=> $b; // <:-1,=:0,>:1
// ?? (널 병합 연산자)
// $_GET['user']의 값을 가져오고 존재하지 않으면 'nobody'를 반환
$username = $_GET['user'] ?? 'nobody';
// 이는 다음과 동일함:
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';

// 병합 연산자는 체이닝 가능: 이는 $_GET['user'], $_POST['user'], 그리고 'nobody' 중 첫 번째 정의된 값을 반환
$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';
// define으로 상수 배열 정의 (PHP5.6에서는 const로만 정의 가능)
define('ANIMALS', [
    'dog',
    'cat',
    'bird'
]);

echo ANIMALS[1]; // "cat" 출력
// use 문
// PHP 7 이전
use com\web3\ClassA;
use com\web3\ClassB;
use com\web3\ClassC as C;

use function com\web3\fn_a;
use function com\web3\fn_b;
use function com\web3\fn_c;

use const com\web3\ConstA;
use const com\web3\ConstB;
use const com\web3\ConstC;

// PHP 7+ 코드
use com\web3\{ClassA, ClassB, ClassC as C};
use function com\web3\{fn_a, fn_b, fn_c};
use const com\web3\{ConstA, ConstB, ConstC};
// 7.1
// 짧은 배열 구문([]) 이제 list() 구문의 대안으로, 배열 값을 변수에 할당하는 데 사용할 수 있음 (foreach 포함).
$data = [
    [1, 'Tom'],
    [2, 'Fred'],
];

// list() 스타일
list($id1, $name1) = $data[0];

// [] 스타일
[$id1, $name1] = $data[0];

// list() 스타일
foreach ($data as list($id, $name)) {
    // 여기서 $id와 $name로 로직 수행
}

// [] 스타일
foreach ($data as [$id, $name]) {
    // 여기서 $id와 $name로 로직 수행
}


// list() 이제 키 이름 지원 === 짧은 배열 구문도 지원
$data = [
    ["id" => 1, "name" => 'Tom'],
    ["id" => 2, "name" => 'Fred'],
];

// list() 스타일
list("id" => $id1, "name" => $name1) = $data[0];

// [] 스타일
["id" => $id1, "name" => $name1] = $data[0];

// list() 스타일
foreach ($data as list("id" => $id, "name" => $name)) {
    // 여기서 $id와 $name로 로직 수행
}

// [] 스타일
foreach ($data as ["id" => $id, "name" => $name]) {
    // 여기서 $id와 $name로 로직 수행
}
// 7.1 다중 예외 포획
try {
    // 일부 코드
} catch (FirstException | SecondException $e) {
    // 첫 번째와 두 번째 예외 처리
}
// 7.1 음의 문자열 오프셋 지원
// 이제 모든 오프셋을 지원하는 문자열 함수는 음수를 오프셋으로 허용합니다. 이에는 [] 또는 {}를 사용하여 문자열 하위 인덱싱하는 경우도 포함됩니다. 이 경우 음수 오프셋은 문자열 끝에서 시작하는 오프셋으로 해석됩니다.
var_dump("abcdef"[-2]); //e
var_dump(strpos("aabbcc", "b", -3)); //3 두 번째 d에서 시작하여 검색
// 7.2 이름으로 확장 로드
// 확장 파일 더 이상 파일 로딩(Unix에서 .so 파일 확장자, Windows에서 .dll 파일 확장자)을 통해 지정할 필요가 없습니다. php.ini 구성 파일에서 활성화하거나 dl() 함수를 사용하여 활성화할 수 있습니다.
// 7.4 널 병합 할당 연산자
$array['key'] ??= computeDefault();
// 다음과 같은 이전 코드와 동일
if (!isset($array['key'])) {
    $array['key'] = computeDefault();
}
// 7.4 배열 전개 연산
$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
// ['banana', 'orange', 'apple', 'pear', 'watermelon'];
// 7.4 숫자 리터럴 구분 기호 
// 숫자 리터럴은 숫자 사이에 밑줄을 포함할 수 있습니다.
6.674_083e-11; // float
299_792_458;   // decimal
0xCAFE_F00D;   // hexadecimal
0b0101_1111;   // binary
// 7.4 화살표 함수
// 더 간결한 함수 정의 방법을 제공합니다.
$factor = 10;
$nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]);
// $nums = array(10, 20, 30, 40);

// 화살표 함수는 익명 함수에 비해 use를 사용할 필요가 없으며, 다른 매개변수를 직접 가져올 수 있습니다. function () use () {}
// 화살표 함수에서 사용되는 모든 매개변수는 복사본이며, 함수 자체에 영향을 주지 않습니다.

10.기타 기능

/**
1.익명 클래스
2.Closure::call()(Closure::call() 메서드는 임시 바인딩(bindTo)된 객체 범위에 추가되어, 간단한 방식으로 닫고 호출합니다. PHP5.6 바인딩에 비해 더 빠릅니다)
3.안전한 unserialize()
4.국제 문자(새로운 IntlChar 클래스는 더 많은 ICU 기능을 노출하기 위해 추가되었습니다. 이 클래스는 유니코드 문자를 조작하는 데 사용할 수 있는 많은 정적 메서드와 상수를 정의합니다. 이 클래스를 사용하기 전에 Intl 확장을 설치해야 합니다)
5.CSPRNG
6.기대(단정)(기대는 assert() 함수의 이전 버전과의 호환성 강화입니다. 기대는 프로덕션 코드에서 비용이 들지 않는 단정을 허용하며, 단정 실패 시 사용자 정의 예외를 발생시킬 수 있습니다. assert()는 더 이상 언어 구조체가 아니며, 첫 번째 매개변수는 테스트를 위한 표현식의 비교 문자열 또는 부울입니다.)
7.정수 나눗셈
8.세션 옵션
9.생성자
10.클래스 상수 가시성(7.1) 이제 클래스 상수의 가시성 설정을 지원합니다(객체 지향 관련)
	- 가시성, 즉 public, private, protected
11.추상 메서드 재정의(7.2) 허용
	- 하나의 추상 클래스가 다른 추상 클래스를 상속할 때, 상속된 추상 클래스는 상속된 추상 클래스의 추상 메서드를 재정의할 수 있습니다
*/
// 익명 클래스(이제 new class를 사용하여 익명 클래스를 인스턴스화할 수 있으며, 이는 일부 "사용 후 폐기" 완전 클래스 정의를 대체하는 데 사용될 수 있습니다.)
interface Logger {
    public function log(string $msg);
}

class Application {
    private $logger;

    public function getLogger(): Logger {
         return $this->logger;
    }

    public function setLogger(Logger $logger) {
         $this->logger = $logger;
    }
}

$app = new Application;
$app->setLogger(new class implements Logger {
    public function log(string $msg) {
        echo $msg;
    }
});

var_dump($app->getLogger());
//Closure::call()
// 7 이전
<?php
class A {
   private $x = 1;
}

// 클로저 정의 PHP 7 이전 코드
$getValue = function() {
   return $this->x;
};

// 클로저 바인딩
$value = $getValue->bindTo(new A, 'A'); 

print($value()); //1
?>
7+
<?php
class A {
   private $x = 1;
}

// PHP 7+ 코드, 정의
$value = function() {
   return $this->x;
};

print($value->call(new A)); //1
?>
//unserialize()에 대한 필터링(이 기능은 안전하지 않은 데이터를 안전하게 언패킹하기 위한 것입니다. 잠재적인 코드 주입을 방지하기 위한 화이트리스트 방식을 사용합니다.)
//설명: unserialize()는 단일 직렬화된 변수를 조작하여 PHP 값으로 변환합니다.

//문서의 예
// 모든 객체를 __PHP_Incomplete_Class 객체로 변환
$data = unserialize($foo, ["allowed_classes" => false]);

// MyClass와 MyClass2를 제외한 모든 객체를 __PHP_Incomplete_Class 객체로 변환
$data = unserialize($foo, ["allowed_classes" => ["MyClass", "MyClass2"]]);

// 기본적으로 모든 클래스가 허용됨, 두 번째 매개변수 생략과 동일
$data = unserialize($foo, ["allowed_classes" => true]);
                           
//다른 곳에서 찾은 예제
class MyClass1 { 
   public $obj1prop;   
}
class MyClass2 {
   public $obj2prop;
}


$obj1 = new MyClass1();
$obj1->obj1prop = 1;
$obj2 = new MyClass2();
$obj2->obj2prop = 2;

$serializedObj1 = serialize($obj1);
$serializedObj2 = serialize($obj2);

// 기본 동작은 모든 클래스 허용
// 두 번째 매개변수는 생략 가능
// allowed_classes가 false로 전달되면, unserialize는 모든 객체를 __PHP_Incomplete_Class 객체로 변환
$data = unserialize($serializedObj1 , ["allowed_classes" => true]);

// MyClass1과 MyClass2를 제외한 모든 객체를 __PHP_Incomplete_Class 객체로 변환
$data2 = unserialize($serializedObj2 , ["allowed_classes" => ["MyClass1", "MyClass2"]]);

print($data->obj1prop);
print("<br/>");
print($data2->obj2prop);
//출력: 1,2
//국제 문자
rintf('%x', IntlChar::CODEPOINT_MAX); //10ffff
print (IntlChar::charName('@')); //COMMERCIAL AT
print(IntlChar::ispunct('!')); //true

php5의 기존 난수는 암호화 안전 의사난수가 아닙니다. PHP의 난수 보안 문제 - 지식

//CSPRNG   PHP7에서, 다음 두 가지 새로운 함수가 도입되어 크로스 플랫폼 방식으로 암호화 안전 정수와 문자열을 생성합니다.
random_bytes(); // 암호화 안전 의사난수 바이트 생성. 암호, 암호학적 난수 임의 길이 문자열 생성에 적합.
random_int(); // 암호화 안전 의사난수 정수 생성. 결과가 매우 중요한 암호화 난수 정수에 적합.

단정, assert, php 테스트 관련. 단정

//정수 나눗셈
$value = intdiv(10,3);
var_dump($value);
print("
");
print($value);
//PHP7+부터 session_start() 함수는 배열 매개변수를 허용하여 php.ini에 설정된 세션 구성 지시문을 재정의합니다. 이러한 옵션은 session.lazy를 지원하며, 기본적으로 PHP 세션 데이터가 변경될 때 세션 데이터 정보를 덮어씁니다.

//다른 옵션은 read_and_close로, 이는 세션 데이터가 읽혀야 하고 세션이 즉시 닫혀야 함을 나타냅니다. 예를 들어, session.cache_limiter를 private로 설정하고 다음 코드 조각을 사용한 후 세션을 즉시 닫도록 플래그를 설정합니다.
session_start([
   'cache_limiter' => 'private',
   'read_and_close' => true,
]);
//생성자
//PHP5.5에서 생성자 개념이 도입되었습니다. 생성자 함수는 yield로 표시된 값을 매번 실행할 때막 얻습니다. PHP7에서 생성자 반복이 완료되면 생성자 함수의 반환값을 얻을 수 있습니다. Generator::getReturn()을 통해
function generator() {
    yield 1;
    yield 2;
    yield 3;
    return "a";
}
 
$generatorClass = ("generator")();
foreach ($generatorClass as $val) {
    echo $val ." ";
 
}
echo $generatorClass->getReturn();
//1 2 3 a

//생성자 안에 하나 또는 여러 생성자를 도입할 수 있으며, yield from functionName1만 작성하면 됩니다
function generator1() {
    yield 1;
    yield 2;
    yield from generator2();
    yield from generator3();
}
 
function generator2() {
    yield 3;
    yield 4;
}
 
function generator3() {
    yield 5;
    yield 6;
}
 
foreach (generator1() as $val) {
    echo $val, " ";
}

기타:

curl, http2, 소켓, ticks, 비동기 등

1.debug_zval_dump() 이제 "long" 대신 "int"를 출력, "double" 대신 "float" 출력 2.dirname() 이제 선택적 두 번째 매개변수 depth 추가, 현재 디렉토리에서 depth 레벨 위 부모 디렉토리 이름 가져오기. 3.getrusage() 이제 Windows 지원. 4.mktime() 및 gmmktime() 함수 더 이상 is_dst 매개변수 허용하지 않음. 5.preg_replace() 함수 더 이상 "\e" (PREG_REPLACE_EVAL) 지원하지 않음. preg_replace_callback()로 대체해야 함. 6.setlocale() 함수 더 이상 category에 문자열 전달 허용하지 않음. LC_* 상수 사용해야 함. 7.exec(), system() 및 passthru() 함수 NULL에 대한 보호 추가. 8.shmop_open() 이제 int 대신 리소스 반환, 이 리소스를 shmop_size(), shmop_write(), shmop_read(), shmop_close() 및 shmop_delete()에 전달할 수 있음. 9.메모리 누수 방지를 위해 xml_set_object() 이제 실행 종료 시 $parse 수동 정리 필요. 10.curl_setopt 설정 옵션 CURLOPT_SAFE_UPLOAD 변경 TRUE는 CURLOPT_POSTFIELDS에서 @ 접두사로 파일 전송을 비활성화함. @를 필드에서 안전하게 사용할 수 있음. CURLFile를 업로드 대체로 사용할 수 있음. PHP 5.5.0에서 추가, 기본값 FALSE. PHP 5.6.0에서 기본값 TRUE로 변경. PHP 7에서 이 옵션 제거, 파일 업로드에는 반드시 CURLFile 인터페이스 사용해야 함.

PHP7 성능을 최대한 활용하는 방법

1.Opcache 활성화

zend_extension=opcache.so opcache.enable=1 opcache.enable_cli=1

2.GCC 4.8 이상으로 컴파일 GCC 4.8 이상에서만 PHP가 Global Register for opline and execute_data 지원 활성화, 이로 인약 약 5% 성능 향상(WordPress QPS 기준)

3.HugePage 활성화 (시스템 메모리에 따라 결정)

4.PGO (Profile Guided Optimization) 첫 번째 컴파일 성공 후, 프로젝트 코드로 PHP 훈련, 일부 프로파일 정보 생성, 마지막으로 이 정보를 사용하여 두 번째 gcc 컴파일로 맞춤형 PHP7 생성

태그: PHP PHP7 프로그래밍 웹 개발 성능 최적화

5월 22일 20:03에 게시됨