PHP7 스칼라 유형 선언 RFC의 샘플 코드에 대한 자세한 설명

黄舟
풀어 주다: 2023-03-06 21:26:01
원래의
1253명이 탐색했습니다.


1. 요약

RFC는 int, float, string 및 bool의 4가지 새로운 스칼라 유형 선언을 추가할 것을 권장합니다. 이러한 유형 선언은 PHP의 원래 메커니즘과 일관되게 사용됩니다. RFC는 또한 동일한 PHP 파일의 모든 함수 호출 및 명령문 반환이 "엄격히 제한된" 스칼라 유형을 갖도록 각 PHP 파일에 새로운 선택적 명령(declare(strict_type=1);)을 추가할 것을 권장합니다. 또한 엄격한 유형 제약 조건을 켠 후 매개변수 구문 분석에 실패하면 확장 기능이나 PHP 내장 함수를 호출하면 E_RECOVERABLE_ERROR 수준 오류가 생성됩니다. RFC는 이 두 가지 기능을 통해 PHP 작성이 더욱 정확해지고 문서화되기를 바라고 있습니다.

2. 상세정보

스칼라 유형 선언:

추가되지 않음 예약어입니다. Int, float, string 및 bool은 유형 선언으로 인식되며 클래스/인터페이스/특성 등의 이름으로 사용이 금지됩니다. 내부 Fast Parameter Parsing API를 통해 구현된 새로운 사용자 스칼라 유형 선언입니다.

strict_types/declare() 지시문

기본적으로 모든 PHP 파일은 약한 유형 검사 모드입니다. 새로운 선언 지시문은 strict_types(1 또는 0)의 값을 지정합니다. 1은 함수 호출 및 return 문에 적용되는 엄격한 유형 검사 모드를 나타내고, 0은 약한 유형 검사 모드를 나타냅니다.

declare(strict_types=1)은 파일의 첫 번째 문이어야 합니다. 이 명령문이 파일의 다른 곳에 나타나면 컴파일 오류가 생성되고 블록 모드가 명시적으로 금지됩니다.

은 인코딩 지시문과 유사하지만 진드기 지시문과 달리 strict_types 지시문은 지정된 파일에만 영향을 미치며 여기에 포함된 다른 파일에는 영향을 미치지 않습니다(include 등을 통해). 이 지시문은 런타임에 컴파일되며 수정할 수 없습니다. 작동 방식은 함수 호출과 반환 유형 검사가 유형 제약 조건을 준수하도록 opcode에 플래그를 설정하는 것입니다.


매개변수 유형 선언

이 지시문은 모든 함수 호출에 영향을 미칩니다(예: 엄격한 확인 모드).

<?php 
 declare(strict_types=1);  
foo(); // strictly type-checked functioncall
 
function foobar() {
      foo(); // strictly type-checked function call
}

  class baz {       
  function foobar() {               
  foo(); // strictly type-checked function call     
  }
}
로그인 후 복사

대비(약한 패리티 모드)

<?php

foo(); // weakly type-checked function call


function foobar() {   
foo(); // weakly type-checked function call

}


class baz {
function foobar() {
foo(); // weakly type-checked function call
}

}
?>
로그인 후 복사

반환 유형 선언:

명령은 동일한 파일 아래의 모든 파일에 영향을 미칩니다. 예를 들어(엄격한 유효성 검사 모드):

<?php

declare(strict_types=1);

function foobar(): int {
return 1.0; // strictly type-checked return

}

 

class baz {
function foobar(): int {
return 1.0; // strictly type-checked return
}}

?>
로그인 후 복사

<?php

function foobar(): int {
return 1.0; // weakly type-checked return

}

 

class baz {
function foobar(): int {
return 1.0; // weakly type-checked return
}}

?>
로그인 후 복사


약한 유형 검사 동작:

一个弱类型校验的函数调用,和PHP7之前的PHP版本是一致的(包括拓展和PHP内置函数)。通常,弱类型校验规则对于新的标量类型声明的处理是相同的,但是,唯一的例外是对NULL的处理。为了和我们现有类、调用、数组的类型声明保持一致,NULL不是默认的,除非它作为一个参数并且被显式赋值为NULL。

为了给不熟悉PHP现有的弱标量参数类型规则的读者,提供简短的总结。表格展示不同类型能够接受和转换的标量类型声明,NULL、arrays和resource不能接受标量类型声明,因此不在表格内。

PHP7标量类型声明介绍RFC[翻译] - 徐汉彬Hansion - 技术行者

*只有范围在PHP_INT_MIN和PHP_INT_MAX内的non-NaN float类型可以接受。(PHP7新增,可查看ZPP Failure on Overflow RFC)

?Non-numeric型字符串不被接受,Numeric型字符串跟随字符串的,也可以被接受,但是会产生一个notice。

?仅当它有toString方法时可以。

严格类型校验行为:

严格的类型校验调用拓展或者PHP内置函数,会改变zend_parse_parameters的行为。特别注意,失败的时候,它会产生E_RECOVERABLE_ERROR而不是E_WARNING。它遵循严格类型校验规则,而不是传统的弱类型校验规则。严格类型校验规则是非常直接的:只有当类型和指定类型声明匹配,它才会接受,否则拒绝。

有一个例外的是,宽泛类型转换是允许int变为float的,也就是说参数如果被声明为float类型,但是它仍然可以接受int参数。

<?php

declare(strict_types=1);

function add(float $a, float $b): float {
return $a + $b;}

 

add(1, 2); // float(3)

?>
로그인 후 복사

在这种场景下,我们传递一个int参数给到定义接受float的函数,这个参数将会被转换为float。除此之外的转换,都是不被允许的。

三、例子:

让我们创建一个函数,让2个数相加。

add.php

<?php

function add(int $a, int $b): int {
return $a + $b;}

?>
로그인 후 복사

如果在分开的文件,我们可以调用add函数通过弱类型的方式

<?php

require "add.php";

var_dump(add(1,2)); // int(3)

// floats are truncated by default

var_dump(add(1.5,2.5)); // int(3)


//strings convert if there&#39;s a number part

var_dump(add("1","2")); // int(3)

?>
로그인 후 복사

默认情况下,弱类型声明允许使用转换,传递进去的值会被转换。

<?php

require "add.php";


var_dump(add("1foo", "2")); // int(3)

// Notice: A non well formed numeric value encountered
로그인 후 복사


但是,通过可选择指令declare开启严格类型校验后,在这个场景下,相同的调用将会失败。

<?php

declare(strict_types=1);

require "add.php";
var_dump(add(1,2)); // int(3)
var_dump(add(1.5,2.5)); // int(3)
// Catchable fatal error: Argument 1 passed to add() must be of the type integer, float given
로그인 후 복사

指令影响同一个文件下的所有函数调用,不管这个被调函数是否在这个文件内定义的,都会采用严格类型校验模式。

<?php declare(strict_types=1); $foo = substr(52,1);
// Catchable fatal error: substr() expects parameter 1 to be string, integer given
로그인 후 복사

标量类型声明也可以用于返回值的严格类型校验:

<?php

function foobar(): int {
return 1.0;

}

var_dump(foobar());// int(1)
로그인 후 복사

在弱类型模式下,float被转为integer。

<?php

declare(strict_types=1);

function foobar(): int {
return 1.0;

}

var_dump(foobar());

//Catchable fatal error: Return value of foobar() must be of the type integer,float returned
로그인 후 복사

四、背景和理论基础

历史

PHP从PHP5.0开始已经有对支持class和interface参数类型声明,PHP5.1支持array以及PHP5.4支持callable。这些类型声明让PHP在执行的时候传入正确的参数,让函数签名具有更多的信息。

先前曾经想添加标量类型声明,例如Scalar Type Hints with Casts RFC,因为各种原因失败了:

(1)类型转换和校验机制,对于拓展和PHP内置函数不匹配。

(2)它遵循一个弱类型方法。

(3)它的“严格”弱类型修改尝试,既没有满足严格类型的粉丝期望,也没有满足弱类型的粉丝。

这个RFC尝试解决全部问题。

弱类型和强类型

在现代编程语言的实际应用中,有三种主要的方法去检查参数和返回值的类型:

(1)全严格类型检查(也就是不会有类型转换发生)。例如F#、GO、Haskell、Rust和Facebook的Hack的用法。

(2)广泛原始类型检查(“安全”的类型转换会发生)。例如Java、D和Pascal。他们允许广泛原始类型转换(隐式转换),也就是说,一个8-bit的integer可以根据函数参数需要,被隐形转换为一个16-bit的integer,而且int也可以被转换为float的浮点数。其他类型的隐式转换则不被允许。

(3)弱类型检查(允许所有类型转换,可能会引起警告),它被有限制地使用在C、C#、C++和Visual Basic中。它们尝试尽可能“不失败”,完成一次转换。

PHP在zend_parse_parameters的标量内部处理机制是采用了弱类型模式。PHP的对象处理机制采用了广泛类型检查方式,并不追求精确匹配和转换。

每个方法各有其优缺点。

这个提案中,默认采用弱类型校验机制,同时追加一个开关,允许转换为广泛类型校验机制(也就是严格类型校验机制)。

둘 다 지원하는 이유는 무엇인가요?

지금까지 대부분의 스칼라 유형 선언 지지자들은 엄격한 유형 검사와 약한 유형 검사 모두에 대한 지원을 요구했습니다. 그 중 하나를 지원하십시오. 이 RFC는 약한 유형 검사를 기본 동작으로 만들고 엄격한 유형 검사를 사용하기 위한 선택적 지시문을 추가합니다(동일한 파일에서). 이 선택에는 여러 가지 이유가 있습니다.

PHP 커뮤니티의 많은 부분이 Quan을 좋아하는 것 같습니다 정적 유형. 그러나 스칼라 유형 선언에 엄격한 유형 검사를 추가하면 몇 가지 문제가 발생합니다.

(1) 명백한 불일치 발생: 확장 및 PHP 내장 -in 함수는 스칼라 유형 매개변수에 대해 약한 유형 검사를 사용하지만 사용자의 PHP 함수는 엄격한 유형 검사를 사용합니다.

(2) 상당수의 사람들이 약한 타입 검사를 선호하고 이 제안에 동의하지 않아 구현을 차단할 수도 있습니다. .

(3) 이미 기존 코드는 PHP의 약한 유형을 사용하므로 영향을 받습니다. 매개변수에 스칼라 유형 선언을 추가하는 데 함수가 필요한 경우 특히 라이브러리 파일의 경우 기존 코드 기반의 복잡성이 크게 증가합니다.

여기에는 약한 유형 검사를 좋아하는 사람들이 아직도 꽤 있습니다. 그러나 엄격한 유형 검사 선언을 추가하는 것과 약한 유형 검사 선언을 추가하는 것은 모두 몇 가지 문제를 일으킬 것입니다.

(1) 대부분의 사람들 엄격한 유형 검사를 선호하면 이 제안이 마음에 들지 않아 구현이 차단됩니다.

(2) 정적 분석 기회를 제한합니다. (최적화 기회를 의미할 수도 있음)

(3) 자동 유형 변환 시 일부 데이터 손실 버그를 숨겨줍니다.

약한 유형과 엄격한 유형 선언을 구별하는 구문을 추가하는 세 번째 솔루션이 제안되었습니다. 이는 또한 몇 가지 문제를 가져올 것입니다:

(1) 약한 유형과 엄격한 유형 검사를 좋아하지 않는 사람들은 강제로 라이브러리를 사용하게 됩니다. 엄격한 형식 또는 약한 형식으로 정의된 항목은 별도로 처리됩니다.

(2) 엄격한 선언을 추가하는 것과 마찬가지로 이 역시 원래 약한 유형 구현의 확장 및 PHP 내장과 일치하지 않습니다. 기능에서 .

이 세 가지 솔루션으로 인해 발생하는 문제를 해결하기 위해 이 RFC에서는 네 번째 솔루션을 제안합니다. 각 파일은 엄격하게 정의되거나 약합니다. 유형 검사. 다음과 같은 이점이 있습니다.

(1) 사람들은 자신에게 맞는 유형 검사를 선택할 수 있습니다. strict 유형 검사 캠프와 약한 유형 검사 캠프를 모두 만족시킵니다.

(2) API는 특정 유형 선언 패턴에 강제로 적응하지 않습니다.

(3) 파일은 기본적으로 약한 유형 검사 체계를 사용하므로 코드를 손상시키지 않고 기존 코드 베이스를 수정할 수 있습니다. 구조체의 경우 스칼라 유형 선언을 추가합니다. 코드 기반에서 유형 선언을 점진적으로 추가하거나 특정 모듈에 대해서만 추가하는 것도 가능합니다.

(4) 스칼라 유형 선언을 정의하려면 단일 구문만 필요합니다.

(5) 엄격한 유형 검사를 선호하는 사람들은 일반적으로 이 기능을 사용자 정의 함수뿐만 아니라 다음 함수에서도 사용합니다. 확장 및 PHP 내장 함수. 즉, PHP 사용자는 엄격한 스칼라 선언의 모순 없이 통합된 메커니즘을 얻게 됩니다.

(6) 엄격한 유형 검사 모드에서는 확장 및 PHP 내장 함수에 의해 발생하는 유형 검사 실패의 오류 수준, 이는 사용자 정의 함수(E_RECOVERABLE_ERROR)에 의해 생성된 함수와 일치합니다.

(7) 엄격한 유형의 코드와 약한 유형의 코드를 단일 코드 베이스에 완벽하게 통합할 수 있습니다.

위 내용은 PHP7 스칼라 유형 선언 RFC의 샘플 코드에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿