【待完成】php8的新特性

http://www.itdecent.cn/p/708802f0f239

  • 前言:php經(jīng)歷了php7.1~php7.4,終于2020年11月26日發(fā)布了php8.0.0,截止目前,最新一次的更新發(fā)布是2021年5月6號(hào)

接下來(lái)我們就來(lái)康康php8帶來(lái)了哪些新特性呢?先看一下官方介紹

image.png
  • PHP 8.0 是 PHP 語(yǔ)言的一個(gè)主版本更新。
    它包含了很多新功能與優(yōu)化項(xiàng), 包括命名參數(shù)、聯(lián)合類型、注解、構(gòu)造器屬性提升、match 表達(dá)式、nullsafe 運(yùn)算符、JIT,并改進(jìn)了類型系統(tǒng)、錯(cuò)誤處理、語(yǔ)法一致性。

  • 接下來(lái)我們安裝一下php8,逐個(gè)的了解一下
    下載頁(yè)面 或者直接指向下載命令

zhangguofu@localhost Downloads $ wget https://www.php.net/distributions/php-8.0.6.tar.gztar -zxvf  php-8.0.6.tar.gz

zhangguofu@localhost Downloads $ tar -zxvf  php-8.0.6.tar.gz

zhangguofu@localhost Downloads $ cd php-8.0.6

zhangguofu@localhost php-8.0.6 $ sudo mkdir /usr/local/php8
# 修改權(quán)限
zhangguofu@localhost php-8.0.6 $ sudo chmod 777  /usr/local/php8

  • 我是在mac下安裝的,遇到了一個(gè)報(bào)錯(cuò)
configure: error: Please specify the install prefix of iconv with --with-iconv=<DIR>

解決方法也很簡(jiǎn)單,看報(bào)錯(cuò)信息,讓在configure的時(shí)候 指定iconv的目錄,我看了一下,我的mac里面并沒有安裝,使用下面命令安裝

zhangguofu@localhost php8 $ brew install libiconv                                                                               

 zhangguofu@localhost php-8.0.6 $ ./configure   --prefix=/usr/local/php8/  --enable-debug  --enable-fpm --with-config-file-path=/usr/local/php8/etc/  --with-iconv=/usr/local/opt/libiconv


zhangguofu@localhost php-8.0.6 $ make && make install

  • 安裝成功
zhangguofu@localhost bin $ pwd
/usr/local/php8/bin
zhangguofu@localhost bin $ /usr/local/php8/bin/php -v
PHP 8.0.6 (cli) (built: May 26 2021 14:43:31) ( NTS DEBUG )
Copyright (c) The PHP Group
Zend Engine v4.0.6, Copyright (c) Zend Technologies
zhangguofu@localhost bin $     

#添加配置文件
zhangguofu@localhost php-8.0.6 $ cp php.ini-development  /usr/local/php8/etc/php.ini

開始測(cè)試

  • 至此,php8安裝完成,為了方便演示,我選擇在laravel里面的單元測(cè)試模塊執(zhí)行,當(dāng)然,你直接使用 /path/php /path/demo.php 去執(zhí)行php腳本也可以。如果你想這樣執(zhí)行,那下面配置這一步可以跳過
  • 這里簡(jiǎn)單介紹一下 laravel里面怎么配置測(cè)試環(huán)境,我的一個(gè)文件在項(xiàng)目根目錄/tests/Unit/Php8Test.php下面,方法名稱 必須是test開頭才可以執(zhí)行測(cè)試
<?php

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;

class Php8Test extends TestCase
{
    public function test1()
    {
        phpinfo();
    }

}

通過phpstorm面板設(shè)置


image.png

你可以為每個(gè)test類設(shè)置一個(gè)執(zhí)行環(huán)境,interpreter,就是你的php解釋器的路徑


image.png

環(huán)境配置完畢

回頭看看我們前面說的新特性

  • PHP 8.0 是 PHP 語(yǔ)言的一個(gè)主版本更新。
    它包含了很多新功能與優(yōu)化項(xiàng), 包括命名參數(shù)、聯(lián)合類型、注解、構(gòu)造器屬性提升、match 表達(dá)式、nullsafe 運(yùn)算符、JIT,并改進(jìn)了類型系統(tǒng)、錯(cuò)誤處理、語(yǔ)法一致性。

  • 命名參數(shù),如果一個(gè)函數(shù)里面有m個(gè)參數(shù),但是你只想指定 第m-1 那一個(gè)參數(shù),在php8里面是可以實(shí)現(xiàn)的,但是php7是報(bào)錯(cuò)的
    但是注意兩點(diǎn):

  • 僅僅指定必填參數(shù),跳過可選參數(shù)。

  • 參數(shù)的順序無(wú)關(guān)

<?php
/**
 * Notes:
 * User: zhangguofu
 * Date: 2021/5/26
 * Class Eight_Php
 */

namespace Php8\Eight_Php;
class Eight_Php
{
    public function run()
    {
        $this->person(age:100);
    }

    public function person($name="",$sex="",$age="")
    {
        echo "the name is $name,the sex is $sex,the age is $age".PHP_EOL;
    }

}

$obj =new Eight_Php();
$obj->run();

image.png
  • 構(gòu)造器屬性提升,這樣我們就可以通過構(gòu)造方法聲明我們的成員屬性,而不需要提前聲明,從而減少我們的代碼量
image.png

相關(guān)代碼:

#php8
namespace Php8\Eight_Php;
class Eight_Php
{
    public function __construct(public $name='')
    {

    }
    public function run()
    {
        echo $this->name.PHP_EOL;
    }
}
$obj =new Eight_Php("jimi");
$obj->run();

#php7
namespace Php8\Seven_Php;

class Seven_Php
{
    public $name='';
    public function __construct($name)
    {
        $this->name=$name;

    }
    public function run()
    {
        echo $this->name.PHP_EOL;
    }

}
$obj=new Seven_Php('jimi');
$obj->run();

  • 聯(lián)合類型,你可以在聲明變量的同時(shí)聲明類型,在代碼運(yùn)行時(shí)會(huì)被校驗(yàn),還是以剛才代碼為例,我對(duì)name 聲明int,如果是參數(shù)接收多種類型,比如,float|string 表示接收 字符串和浮點(diǎn)型。感覺有點(diǎn)像強(qiáng)類型了吧,單其實(shí)也不是 float 和int 會(huì)自動(dòng)轉(zhuǎn)化,比如參數(shù)只接受int ,傳值是1.23 類型轉(zhuǎn)換后就是1
    image.png
  • 通過上一個(gè)例子其實(shí)也看出來(lái)了,php8增強(qiáng)了字符串和數(shù)字之間的校驗(yàn)


    image.png
  • 而且這種類型校驗(yàn)的增強(qiáng),還體現(xiàn)在對(duì)內(nèi)部函數(shù)的校驗(yàn),提升了報(bào)錯(cuò)級(jí)別,如果內(nèi)部函數(shù)的類型不對(duì),原來(lái)的是報(bào)warning,現(xiàn)在是fatal


    image.png

重點(diǎn)看一看JIT

PHP 8 的JIT(Just In Time)編譯器將作為擴(kuò)展集成到php 中Opcache 擴(kuò)展 ,PHP 8 引入了兩個(gè)即時(shí)編譯引擎,一個(gè)是tracing jit ,一個(gè)是function jit,用于運(yùn)行時(shí)將某些操作碼直接轉(zhuǎn)換為從cpu 指令。 這意味著使用JIT 后,Zend VM 不需要解釋某些操作碼,并且這些指令將直接作為CPU 級(jí)指令執(zhí)行。


  • 但是再了解jit之前,我們要知道為什么要出現(xiàn)jit,那么我們就要了解php到底是怎么運(yùn)行的。那么我們從兩個(gè)方面去看這個(gè)問題,一種是php-fpm(接收web請(qǐng)求),一種是php的CLI 解釋器(使用php運(yùn)行腳本)

什么是php-fpm

  • 在了解php-fpm之前,請(qǐng)大家先思考一個(gè)問題,一個(gè)用戶發(fā)起了一個(gè)web(niginx服務(wù)器)請(qǐng)求,在php代碼里面,那么我們?cè)趺礃硬趴梢酝ㄟ^ _POST,_GET,$_SERVER獲取一些請(qǐng)求信息呢?我們應(yīng)該參照什么格式去組裝數(shù)據(jù)呢?
    其實(shí)我們知道,每種動(dòng)態(tài)語(yǔ)言,也就是解釋性語(yǔ)言,都需要通過對(duì)應(yīng)的解析器才能被服務(wù)器識(shí)別,但是解釋器和服務(wù)器 必須遵循某種協(xié)議,雙方才能夠正常通信,那么這種協(xié)議就是CGI協(xié)議,但是CGI的機(jī)制是每響應(yīng)一次web請(qǐng)求,都會(huì)創(chuàng)建和初始化一個(gè)新的處理進(jìn)程,請(qǐng)求結(jié)束就kill掉這個(gè)進(jìn)程。那每次請(qǐng)求,都要執(zhí)行這三步 創(chuàng)建->初始化->結(jié)束,那其實(shí)這個(gè)過程不僅浪費(fèi)了資源,而且效率也很低。那怎么辦?FastCGI應(yīng)時(shí)而生,作為CGI的改良版本,F(xiàn)astCGI會(huì)啟動(dòng)一個(gè)常駐服務(wù)進(jìn)程,這個(gè)進(jìn)程不需要管理生命周期,也就避免了進(jìn)程的重復(fù)的創(chuàng)建和結(jié)束,另一方面,不需要再重復(fù)的讀取環(huán)境變量,每當(dāng)有web請(qǐng)求過來(lái),由FastCGI管理器,也就那個(gè)常駐服務(wù)進(jìn)程去啟動(dòng)CGI解釋器進(jìn)程
image.png
  • 好了,既然有了CGI,那么針對(duì)這些解釋性語(yǔ)言,比如php phython,都要根據(jù)自己的語(yǔ)言做一個(gè)適配吧。那么php官方就弄出來(lái)了PHP-CGI,php定制版的CGI。
  • 但是隨著使用,大家發(fā)現(xiàn)了PHP-CGI的問題

1.修改php.ini 后必須重啟PHP-CGI才可以生效,而不能實(shí)現(xiàn)平滑重啟
2.直接干掉PHP-CGI,php就不能運(yùn)行了,這顯然是不能接受的
3.這玩意不會(huì)自己管理進(jìn)程,它只能解析請(qǐng)求,返回結(jié)果

那么FastCGI都已經(jīng)到來(lái)了,php的FastCGI還會(huì)遠(yuǎn)嗎,當(dāng)然不會(huì),到 2004年一個(gè)叫 Andrei Nigmatulin的屌絲發(fā)明了PHP-FPM,PHP-FMP 全名叫做PHP-FASTCGI Process Manager,說白了就是php定制版的FastCGI(這里強(qiáng)調(diào)一下,不管是PHP-CGI 還是 PHP-FPM都是為了實(shí)現(xiàn)CGI協(xié)議,而不是一種新的協(xié)議),其實(shí)有一句話剛才我沒說,網(wǎng)上很多人說PHP-CGI 就是 php管理FAST-CGI的一種程序,那你現(xiàn)在知道了PHP-FMP 全名叫做PHP-FASTCGI Process Manager之后,你可以理直氣壯的跟他們說no,并給他們普及一下這個(gè)知識(shí)點(diǎn)了。

php-fmp的進(jìn)程包括 master(常駐服務(wù)程序)和worker進(jìn)程兩種

master進(jìn)程
  • master負(fù)責(zé)進(jìn)程的調(diào)度(比如worker進(jìn)程不夠的時(shí)候去fork一個(gè)子進(jìn)程)
  • 負(fù)責(zé)監(jiān)聽端口,一般是9000這個(gè)端口,可以在配置文件里面設(shè)置,當(dāng)然,還有另外一種方式,就是通過socket,可以通過netstat -nap | grep master的進(jìn)程號(hào) 查看端口信息(9000端口其實(shí)就是tcp的通信方式,而socket是說的unix socket,從效率上來(lái)說,unix socket顯然是最好的,因?yàn)樗沁M(jìn)程之間的通信,但是unix socket要保證是在一臺(tái)服務(wù)器,如果是不同機(jī)器之間的通信,還是要使用tcp通信)
image.png
image.png
  • 接收來(lái)自服務(wù)器的請(qǐng)求
work進(jìn)度 看名字就知道了,就是真正的打工階級(jí),代碼真正執(zhí)行的地方
image.png
  • 再來(lái)看看php-fmp和nignx是怎么通信的
    以socker通信為栗子,nginx的conf文件里面,可以看到下面這段信息
        location ~ [^/]\.php(/|$)
        {
            try_files $uri =404;
            fastcgi_pass  unix:/tmp/php-cgi.sock;
            fastcgi_index index.php;
            include fastcgi.conf;
        }

相信這段信息大家都可以看明白,/tmp/php-cgi.sock 就是php和nginx聯(lián)系的橋梁,同時(shí)我們也看到了include fastcgi.conf,我們來(lái)看一下

root@6d05153a8988:/usr/local/nginx/conf# cat fastcgi.conf

fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  REQUEST_SCHEME     $scheme;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;
fastcgi_param PHP_ADMIN_VALUE "open_basedir=NULL";

我們看到了一些熟悉的,比如REMOTE_ADDR,REQUEST_URI,現(xiàn)在你應(yīng)該明白了,我們通過$_SERVER獲取到的信息就是這個(gè)配置文件里面指定的

我們?cè)賮?lái)看一下php-fmp的配置文件(請(qǐng)注意看里面的注釋,我不做解釋了)


root@6d05153a8988:/usr/local/php/etc# cat php-fpm.conf
[global]
pid = /usr/local/php/var/run/php-fpm.pid
error_log = /usr/local/php/var/log/php-fpm.log
log_level = notice

[www]
listen = /tmp/php-cgi.sock
listen.backlog = -1
listen.allowed_clients = 127.0.0.1
listen.owner = www
listen.group = www
listen.mode = 0666
user = www
group = www
# 如何控制子進(jìn)程,選項(xiàng)有static和dynamic
#區(qū)別:
#如果dm設(shè)置為 static,那么其實(shí)只有pm.max_children這個(gè)參數(shù)生效。系統(tǒng)會(huì)開#啟設(shè)置數(shù)量的php-fpm進(jìn)程。
#如果dm設(shè)置為 dynamic,那么pm.max_children參數(shù)失效,后面3個(gè)參數(shù)生效。
#系統(tǒng)會(huì)在php-fpm運(yùn)行開始 的時(shí)候啟動(dòng)pm.start_servers個(gè)php-fpm進(jìn)程,
#然后根據(jù)系統(tǒng)的需求動(dòng)態(tài)在pm.min_spare_servers和pm.max_spare_servers之#間調(diào)整php-fpm進(jìn)程數(shù)。
pm = dynamic
# 靜態(tài)方式下開啟的php-fpm進(jìn)程數(shù)量
pm.max_children = 20
# 動(dòng)態(tài)方式下的起始php-fpm進(jìn)程數(shù)量
pm.start_servers = 10
# 動(dòng)態(tài)方式下的最小php-fpm進(jìn)程數(shù)
pm.min_spare_servers = 10
# 動(dòng)態(tài)方式下的最大php-fpm進(jìn)程數(shù)量
pm.max_spare_servers = 20
# php-fpm子進(jìn)程能處理的最大請(qǐng)求數(shù)
pm.max_requests = 1024
pm.process_idle_timeout = 10s
request_terminate_timeout = 100
request_slowlog_timeout = 0
slowlog = var/log/slow.log

  • 關(guān)于php-fpm 的相關(guān)操作

INT, TERM
QUIT 平滑終止
USR1 重新打開日志文件
USR2 平滑重載所有worker進(jìn)程并重新載入配置和二進(jìn)制模塊

啟動(dòng): /usr/local/php/sbin/php-fpm
查看進(jìn)程數(shù): ps aux | grep -c php-fpm
查看mater進(jìn)程號(hào):ps aux|grep 'php-fpm: master'|grep -v grep|awk '{print $2}' 或者cat /usr/local/php/var/run/php-fpm.pid

# 強(qiáng)制關(guān)閉
pkill php-fpm

kill -INT `cat /usr/local/php/var/run/php-fpm.pid` 
kill -INT [pid]

# 平滑重啟 其實(shí)就是通過創(chuàng)建新的進(jìn)程使 php.ini 生效
kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`
kill -USR2 [pid]
小結(jié)

至此,php-fpm 算是說完了,其實(shí)通過上面的解說,大家也會(huì)明白一個(gè)問題,為什么lnmp 承受的并發(fā)比lamp高,php-fpm 是不是其中的一個(gè)原因呢?

php的cli解釋器

運(yùn)行步驟

異同

【外賣連接】

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容