이 글은 주로 php7.0의 새로운 기능을 자세히 분석하는 것입니다.
1. 성능 및 기본 레이어
PHP7은 PHP5.6보다 2배 빠릅니다.
php7의 가장 중요한 변화는 Facebook에서 개발한 PHP 실행 엔진 HHVM에 가까운 성능 향상입니다. . 워드프레스 벤치마크 성능 테스트에서는 버전 5.6보다 속도가 2~3배 빨라 메모리 사용량이 크게 줄어든 것으로 나타났다. PHP7에는 반환 유형 선언 추가, 새로운 예약 키워드 추가 등 언어에 대한 일부 변경 사항도 있습니다. 보안 측면에서는 PHP 안전 모드 제거, 매직 따옴표 추가 등이 있습니다. 뿐만 아니라 새 버전은 64비트도 지원하며 최신 버전의 Zend 엔진을 포함하고 있습니다.
테스트해 보세요
매우 간단한 예입니다. 600,000개 요소의 배열을 생성하고 키를 검색하여 키가 존재하는지 확인합니다.
<?php $a = []; for($i=0;$i<600000;$i++){ $a[$i] = $i; } foreach($a as $item) { array_key_exists($item, $a); }
저희는 php5.6.11과 php7.0.4에서 각각 성능을 테스트했습니다.
php5.6.11
➜ time php 1.php 0.67s user 0.06s system 67% cpu 1.078 total ➜ time php 1.php 0.68s user 0.06s system 98% cpu 0.748 total ➜ time php 1.php 0.65s user 0.06s system 67% cpu 1.052 total
3번 평균하면 대략 사용자의 경우 0.65초, 시스템의 경우 0.06초, CPU 속도는 67%입니다. 총 1초 정도.
php7의 상황을 보세요
➜ time /usr/local/opt/php70/bin/php 1.php 0.52s user 0.02s system 98% cpu 0.544 total ➜ time /usr/local/opt/php70/bin/php 1.php 0.49s user 0.02s system 99% cpu 0.513 total ➜ time /usr/local/opt/php70/bin/php 1.php 0.51s user 0.02s system 98% cpu 0.534 total
비해 사용자 사용 시간은 약 20% 감소했고, 시스템 사용 시간은 70% 감소했으며, CPU 사용률은 98%까지 높았습니다. 전체 시간은 다음과 같이 단축됩니다. 0.5초.
이 예시를 보면 효율성이 2배가 됩니다. 실제로 나쁘지 않습니다.
또 다른 예를 살펴보세요. 또한 값이 존재하는지 확인하기 위해 600,000개 요소의 배열을 생성합니다.
<?php $a = []; for($i=0;$i<600000;$i++){ $a[$i] = $i; } foreach($a as $i) { array_search($i, $a); } ?>
먼저 php5.6.11을 보세요
➜ testPHP time php 2.php 0.68s user 0.03s system 66% cpu 1.077 total ➜ testPHP time php 2.php 0.68s user 0.02s system 98% cpu 0.710 total ➜ testPHP time php 2.php 0.68s user 0.02s system 98% cpu 0.713 total ➜ testPHP time php 2.php 0.69s user 0.02s system 98% cpu 0.721 total
그 다음 php7.0.4
➜ testPHP time /usr/local/opt/php70/bin/php 2.php 0.12s user 0.02s system 69% cpu 0.201 total ➜ testPHP time /usr/local/opt/php70/bin/php 2.php 0.11s user 0.01s system 97% cpu 0.131 total ➜ testPHP time /usr/local/opt/php70/bin/php 2.php 0.11s user 0.01s system 96% cpu 0.130 total
를 보면 확실히 6배 이상 빠르네요. 날카로운.
2. 새로운 기능
1. 추가 스칼라 유형 선언
이제 PHP에는 필수(기본) 모드와 엄격 모드의 두 가지 모드가 있습니다. 이제 string, int, float 및 bool 유형 매개변수를 사용할 수 있습니다(강제 모드 또는 엄격 모드). 이는 PHP5에 도입된 다른 유형(클래스 이름, 인터페이스, 배열 및 콜백 유형)을 확장합니다. 이전 버전에서는 (Array $arr), (CLassName $obj) 등의 함수 매개변수 선언만 가능했고, Int, String 등과 같은 기본 유형은 선언할 수 없었습니다.
이해하는 방법은 무엇입니까? php7 이전 버전에서는 함수의 매개변수 유형을 제한하려는 경우 배열 또는 클래스라는 두 가지 유형만 있었습니다.
php7 이전:
class MyInfo { public $a = 123; public function getInfo(array $a, $b) { var_dump($a, $b); } } function getClass(MyInfo $a) { var_dump($a->a); }
getInfo의 첫 번째 매개변수를 배열로 제한하고 싶기 때문에 $a 매개변수 앞에 배열을 추가할 수 있습니다. 선언하다.
마찬가지로 getClass의 매개변수가 클래스가 되기를 원하므로 이 클래스의 className을 사용하여 필수 사용으로 선언합니다.
php7 이전에는 이 두 스칼라만 사용할 수 있었습니다.
사용해 봅시다:
$info = new MyInfo(); $info->getInfo([1,2,3,4], 4);
규정을 따르고 배열을 첫 번째 매개변수로 전달하면 물론 결과는 정상적으로 인쇄됩니다.
➜ testPHP php 3.php array(3) { [0] => int(1) [1] => int(2) [2] => int(3) } int(4)
규정을 설치하지 않으면 잘 알려진 오류는 다음과 같습니다. 보고됨:
$info = new MyInfo(); $info->getInfo(122, 0);
오류:
PHP Catchable fatal error: Argument 1 passed to MyInfo::getInfo() must be of the type array, integer given, called in /Users/yangyi/www/testPHP/3.php on line 25 and defined in /Users/yangyi/www/testPHP/3.php on line 8 PHP Stack trace: PHP 1. {main}() /Users/yangyi/www/testPHP/3.php:0 PHP 2. MyInfo->getInfo() /Users/yangyi/www/testPHP/3.php:25
클래스 사용에도 동일하게 적용됩니다.
$info = new MyInfo(); getClass($info);
출력 결과:
➜ testPHP php 3.php int(123)
마찬가지로 다른 매개변수를 전달하면 오류가 보고됩니다.
getClass(123); ➜ testPHP php 3.php PHP Catchable fatal error: Argument 1 passed to getClass() must be an instance of MyInfo, integer given, called in /Users/yangyi/www/testPHP/3.php on line 27 and defined in /Users/yangyi/www/testPHP/3.php on line 17 PHP Stack trace: PHP 1. {main}() /Users/yangyi/www/testPHP/3.php:0 PHP 2. getClass() /Users/yangyi/www/testPHP/3.php:27
이 php7로 돌아가겠습니다. 스칼라 유형을 확장한 업그레이드에는 bool, int, string, float가 추가되었습니다.
php7에는 필수(기본) 모드와 엄격 모드의 두 가지 모드가 있습니다.
Forced 모드
Forced 모드는 기본 모드입니다. 강제 모드에서는 숫자 유형을 문자열 유형, int 정수, bool 및 강제 유형으로 변환하는 데 도움이 됩니다. 다른 유형은 변환할 수 없으며 오류가 보고됩니다.
이전과 여전히 같은 예입니다.
class MyInfo { public $a = 123; public function get1(bool $b) { var_dump($b); } public function get2(int $b) { var_dump($b); } public function get3(string $b) { var_dump($b); } public function get4(float $b) { var_dump($b); } public function get5(array $b) { var_dump($b); } }
먼저 모든 정수 1
$info = new MyInfo(); $info->get1(1); $info->get2(1); $info->get3(1); $info->get4(1);
을 전달하고 인쇄된 결과를 살펴보겠습니다. 이미 강제로 변환되었습니다.
➜ testPHP /usr/local/opt/php70/bin/php 3.php /Users/yangyi/www/testPHP/3.php:11: bool(true) /Users/yangyi/www/testPHP/3.php:19: int(1) /Users/yangyi/www/testPHP/3.php:26: string(1) "1" /Users/yangyi/www/testPHP/3.php:33: double(1)
계속해서 문자열 1.23을 전달해 보겠습니다.
$info = new MyInfo(); $info->get1('1.23'); $info->get2('1.23'); $info->get3('1.23'); $info->get4('1.23');
결과를 보고 인쇄하세요. 또한 우리를 위해 강제로 변환되었습니다.
➜ testPHP /usr/local/opt/php70/bin/php 3.php /Users/yangyi/www/testPHP/3.php:11: bool(true) /Users/yangyi/www/testPHP/3.php:19: int(1) /Users/yangyi/www/testPHP/3.php:26: string(4) "1.23" /Users/yangyi/www/testPHP/3.php:33: double(1.23)
하지만 매개변수를 배열로 강제할 수 없으면 오류가 발생합니다.
$info->get5('1.23'); testPHP /usr/local/opt/php70/bin/php 3.php PHP Fatal error: Uncaught TypeError: Argument 1 passed to MyInfo::get5() must be of the type array, string given, called in /Users/yangyi/www/testPHP/3.php on line 54 and defined in /Users/yangyi/www/testPHP/3.php:37
PHP5.6.11에서 이 코드를 실행할 때 오류가 발생합니까? 한번 시도해 보세요:
$info = new MyInfo(); $info->get1('1.23'); $info->get2('1.23'); $info->get3('1.23'); $info->get4('1.23'); ➜ testPHP php 3.php PHP Catchable fatal error: Argument 1 passed to MyInfo::get1() must be an instance of bool, string given, called in /Users/yangyi/www/testPHP/3.php on line 48 and defined in /Users/yangyi/www/testPHP/3.php on line 8
알겠습니다. 오류가 직접 보고되었지만 오류 메시지에는 유형이 잘못되었다고 나와 있지만 이러한 유형의 다른 선언은 지원되지 않습니다.
Strict Mode
앞서 언급했듯이 강제 모드에서는 강제 변환에 도움이 되지만 엄격 모드는 어떻습니까?
우선, 엄격 모드를 켜는 방법은 무엇인가요?
<?php declare(strict_types=1);
만 추가하면 됩니다. 이렇게 하면 매개변수가 규정을 준수해야 합니다. 그렇지 않으면 오류가 보고됩니다.
다음 문장을 추가하고 다시 실행해 보겠습니다.
<?php declare(strict_types=1); ... ... $info = new MyInfo(); $info->get1('1.23'); $info->get2('1.23'); $info->get3('1.23'); $info->get4('1.23');
실행하고 살펴보세요. 물론 오류가 직접 보고됩니다.
PHP Fatal error: Uncaught TypeError: Argument 1 passed to MyInfo::get1() must be of the type boolean, string given, called in /Users/yangyi/www/testPHP/3.php on line 49 and defined in /Users/yangyi/www/testPHP/3.php:9
2. 반환 값 유형 선언
우리는 PHP 함수에 반환 값 유형이 없다는 것을 알고 있습니다. php7에는 반환값 유형이 추가되었으며, 함수의 반환값 유형을 정의할 수 있습니다.
php7 업그레이드의 스칼라 유형 선언과 동일하게 반환 유형은 bool, int, string, float, array, class가 될 수 있습니다.
예를 들어 함수의 반환 값을 배열로 지정하려면 다음과 같이 작성할 수 있습니다.
:array {} // 콜론 + 반환 유형
function returnInfo ($a) : array { return $a; } var_dump(returnInfo([1,2,3]));
이상하고 믿을 수 없다고 생각하지 마세요. ? ! !
인쇄 결과 보기:
➜ testPHP /usr/local/opt/php70/bin/php 3.php /Users/yangyi/www/testPHP/3.php:64: array(3) { [0] => int(1) [1] => int(2) [2] => int(3) }
마찬가지로 정수 유형을 반환하려고 합니다:
function returnInfo ($a) : int { return $a; } var_dump(returnInfo('1.233'));
查看结果,他已经帮我们强制转换成整型了。
➜ testPHP /usr/local/opt/php70/bin/php 3.php /Users/yangyi/www/testPHP/3.php:64: int(1)
同样,我们可以返回一个class类型的:
public function getLogger(): Logger { return $this->logger; }
默认,也是强制模式,会帮我们转换,如果,我们想使用严格模式,同样是一样的,在文件头部加上:
<?php declare(strict_types=1);
就可以了,这样,我们规定返回值是什么类型,就必须得是这样,不然就报致命报错。
3. null合并运算符 (??)
由于日常使用中存在大量同时使用三元表达式和 isset()的情况, php7增加了一个新的语法糖 : null合并运算符 (??)
如果变量存在且值不为NULL, 它就会返回自身的值,否则返回它的第二个操作数。
//php version = 7 $username = $user ?? 'nobody'; //php version < 7 得这样使用: $username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
确实方便了很多。
我记得php5.3的更新中,加入了 三元运算符简写形式:
$a ?: $b
千万别和??搞混淆了!!!
$a ?: $b的意思是 $a为true时,直接返回$a, 否则返回$b
$a ?? $b的意思是 $a isset($a)为true, 且不为NULL, 就返回$a, 否则返回$b。
看例子:
$user = 0; $username = $user ?? 'nobody'; echo $username; //输出 0,因为 0 存在 且 不为NULL。 $username = $user ?: 'nobody'; echo $username; //输出 'nobody',因为 0 为 false
4. 太空船操作符(组合比较符)
php7 中,新加入了一个比较符号:96b4fef55684b9312718d5de63fb7121 ,因为长相像太空船,所以,也叫太空船操作符。
它有啥用呢?
96b4fef55684b9312718d5de63fb7121用于比较两个表达式。当$a小于、等于或大于$b时它分别返回-1、0或1。
看例子:
<?php // Integers echo 1 <=> 1; // 0 echo 1 <=> 2; // -1 echo 2 <=> 1; // 1 // Floats echo 1.5 <=> 1.5; // 0 echo 1.5 <=> 2.5; // -1 echo 2.5 <=> 1.5; // 1 // Strings echo "a" <=> "a"; // 0 echo "a" <=> "b"; // -1 echo "b" <=> "a"; // 1 ?>
其实,蛮多地方可以派上用场的。
5. 通过define()定义常量数组
Array类型的常量现在可以通过 define()来定义。在 PHP5.6 中仅能通过const定义。
在php5.3中,增加了可以使用const来申明常量,替代define()函数,但是只能申明一些简单的变量。
//旧式风格: define("XOOO", "Value"); //新式风格: const XXOO = "Value"; //const 形式仅适用于常量,不适用于运行时才能求值的表达式: // 正确 const XXOO = 1234; // 错误 const XXOO = 2 * 617;
在php5.6中,又对const进行来升级,可以支持上面的运算了。
const A = 2; const B = A + 1;
但是,一只都是在优化const,可是确把define()给搞忘记了,php 5.6申明一个数组常量,只能用const。所以,在 php7 中把 define()申明一个数组也给加上去了。
//php 7 define ('AWS' , [12,33,44,55]); // php < 7 const QWE = [12,33,44,55]; echo AWS[1]; //12 echo QWE[2]; //33
至此,到php7版本,define()的功能和const就一摸一样了,所以,你随便用哪一个都可以,但是因为在class类中,什么常量是const。所以,我们就统一用const申明常量好了。
6. 匿名类
现在已经支持通过new class 来实例化一个匿名类,这可以用来替代一些用后即焚的完整类定义。
看下这个官方文档上的一个栗子:
<?php 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()); ?>
我们先输出的打印的结果,显示为匿名类:
class class@anonymous#2 (0) { }
我们来分解下,还原被偷懒的少写的代码:
class logClass implements Logger { public function log(string $msg) { echo $msg; } } $app = new Application; $log2 = new logClass; $app->setLogger($log2);
输出结果为:
class logClass#2 (0) { }
虽然代码简洁了很多,但是还是有点不适应,多用用就好了。
还记得php中的匿名函数嘛?在php5.3中新增的匿名函数,结合新的,顺便复习下:
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 )
7. Unicode codepoint 转译语法
ps : 由于用的少,我就直接抄官网的说明了。
这接受一个以16进制形式的 Unicode codepoint,并打印出一个双引号或heredoc包围的 UTF-8 编码格式的字符串。 可以接受任何有效的 codepoint,并且开头的 0 是可以省略的。
echo "\u{0000aa}"; echo "\u{aa}"; //省略了开头的0 echo "\u{9999}";
看下输出:
ª ª 香
我们在php5.6环境下执行下呢?会怎样:
\u{aa} \u{0000aa} \u{9999}
好吧,直接原样输出了。
8. Closure::call() 闭包
ps : 由于用的少,我就直接抄官网的说明了。
Closure::call() 现在有着更好的性能,简短干练的暂时绑定一个方法到对象上闭包并调用它。
<?php class A {private $x = 1;} // php 7之前: $getXCB = function() {return $this->x;}; $getX = $getXCB->bindTo(new A, 'A'); // intermediate closure echo $getX(); // PHP 7: $getX = function() {return $this->x;}; echo $getX->call(new A);
会输出:
1 1
9. 为unserialize()提供过滤
unserialize 这个函数应该不陌生,它是php中用解开用serialize序列化的变量。
看个栗子:
<?php $a = [1,2,3,4,5,6]; $b = serialize($a); $c = unserialize($b); var_dump($a, $b, $c);
打印结果为:
array(6) { [0] => int(1) [1] => int(2) [2] => int(3) [3] => int(4) [4] => int(5) [5] => int(6) } string(54) "a:6:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;i:4;i:5;i:5;i:6;}" array(6) { [0] => int(1) [1] => int(2) [2] => int(3) [3] => int(4) [4] => int(5) [5] => int(6) }
现在php7中unserialize会变得更佳好用,它多了一个参数,用来反序列化包涵class的过滤不需要的类,变的更加安全。
unserialize($one, ["allowed_classes" => true]); unserialize($one, ["allowed_classes" => false]); unserialize($one, ["allowed_classes" => [class1,class2,class3]]);
举个例子,先序列化一个类。
class MyInfo { public function getMyName() { return 'phper'; } } $phper = new MyInfo(); $one = serialize($phper); //参数allowed_classes 设置为 true,表示允许解析class $two = unserialize($one, ["allowed_classes" => true]); //参数allowed_classes 设置为 false,表示不允许解析class $three = unserialize($one, ["allowed_classes" => false]); //不加参数。正常解析。 $four = unserialize($one); //只允许解析 类 MyInfo1。 $five = unserialize($one, ["allowed_classes" => ["MyInfo1"]]); //分别输出下 getMyName方法; var_dump($one); var_dump($two->getMyName()); var_dump($three->getMyName()); var_dump($four->getMyName()); var_dump($five->getMyName());
发现3和5直接报致命错误了:
PHP Fatal error: main(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "MyInfo" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition in /Users/yangyi/www/php7/5.php on line 22
大致意思就是,没权限解析。
所以,我们改一下:
$three = unserialize($one, ["allowed_classes" => true]); $five = unserialize($one, ["allowed_classes" => ["MyInfo"]]);
再输出,就正常了。
/Users/yangyi/www/php7/5.php:22: string(17) "O:6:"MyInfo":0:{}" /Users/yangyi/www/php7/5.php:23: string(5) "phper" /Users/yangyi/www/php7/5.php:24: string(5) "phper" /Users/yangyi/www/php7/5.php:25: string(5) "phper" /Users/yangyi/www/php7/5.php:26: string(5) "phper"
发现我目前为止并没用到,并没有什么乱用,好吧,继续下一个。
10. IntlChar
ps : 由于用的少,我就直接抄官网的说明了。
新增加的 IntlChar(http://php.net/manual/zh/class.intlchar.php) 类旨在暴露出更多的 ICU 功能。这个类自身定义了许多静态方法用于操作多字符集的 unicode 字符。
<?php printf('%x', IntlChar::CODEPOINT_MAX); echo IntlChar::charName('@'); var_dump(IntlChar::ispunct('!'));
以上例程会输出:
10ffff COMMERCIAL AT bool(true)
若要使用此类,请先安装Intl扩展
相关推荐:《PHP7新特性手册》
위 내용은 PHP7.0의 새로운 기능에 대한 자세한 설명(예)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!