Quantcast
Browsing Latest Articles All 5 Live
Mark channel Not-Safe-For-Work? (0 votes)
Are you the publisher? or about this channel.
No ratings yet.
Articles:

PPPoE(PPP over Ethernet)とは

PPP(Point to Point Protocol)とは

  • 2点間を接続するプロトコルの一つ
  • データリンク層(第2層)
  • 伝送エラーの検出、アドレス情報の交換、接続相手の確認などの機能を持つ
  • TCP/IP以外の通信プロトコルにも対応(電話回線からインターネットに接続)

Ethernetとは

  • LAN規格(限られた範囲内で、相互にデータ送信可能なネットワーク)
  • バス型と、スター型がある
  • どのコンピューターも通信回線を使用する権利を有する

PPPoEとは

  • PPPの機能をEthernet上で利用可能にするためのプロトコル
  • インターネットの接続に、「認証ID」と「認証パスワード」が必要
  • フレッツ光やフレッツADSLも含む

纪念我的第七个CCNA实验 PPP认证实验操作

PPP简介

PPP

PPP属于数据链路层的协议,它主要干的活是针对点对点的路由器连接的数据链路层进行封装。PPP的下面有两个子协议,一个是NCP协议,另外一个是LCP协议。其中NCP是针对网络层的子协议。而LCP是针对数据链路层的子协议。今天我们的实验是要验证PPP的LCP协议中的pap认证和chap认证。

PAP验证方式

PAP验证的主要过程是,两台路由器相互发送对面的用户数据库里面的账号密码,如果发送的用户名和密码在对面的路由器的用户数据库中存在的话,那么认证成功。类似于我们在web应用最常规的用户名,密码登陆。
PAP验证的过程中,用户名和密码都是以明文的方式进行传送的。另外,PAP的验证过程中所发送的密码不支持MD5加密。这就意味着,发送的用户名和密码信息,只能匹配对面路由的常规用户数据库(username ,password___)

CHAP验证方式

CHAP验证就不是单纯的用户名,密码登陆了。首先点对点的路由器双方设定相同的密码X,并且用户名是对方的hostname。CHAP的认证的过程中不会发送用户名和密码的信息。其过程有点类似于SSH的数据传送方式。先是两个点对点的路由器的某一端生成一段名为challenge的随机数。然后把这个随机数发送给另一段的路由器。另一段的路由器拿到这串随机数后和密码X一起做一次md5加密,加密的HASH结果发送给对面的路由器。对面的路由器这个时候也把自己生成的challenge随机数和自己的密码X一起做一次md5加密,加密的HASH结果和对方传来的HASH结果做比较,如果一致那么证明对方拥有自己生成的challenge随机数和与自己相同的密码。

实验

PAP验证方式的实验

スクリーンショット 2018-03-10 14.42.13.png

RT1的设定

Router(config)#hostname RT1
RT1(config)#username syoui password villa
RT1(config)#int s2/0
RT1(config-if)#ip address 172.16.10.1 255.255.255.0
RT1(config-if)#en
RT1(config-if)#encapsulation ppp
RT1(config-if)#ppp au
RT1(config-if)#ppp authentication pa
RT1(config-if)#ppp authentication pap 
RT1(config-if)#ppp pap
RT1(config-if)#ppp pap se
RT1(config-if)#ppp pap sent-username gemo ?
  password  Set outbound PAP password
RT1(config-if)#ppp pap sent-username gemo p
RT1(config-if)#ppp pap sent-username gemo password ruby
RT1(config-if)#no sh

%LINK-5-CHANGED: Interface Serial2/0, changed state to down

RT1一边设定后的RT1的s2/0的状态,可以看到因为另外一边的ppp封装协议还没有设定好,s2/0的LCP处于 Closed的状态

RT1(config-if)#do show interface s2/0
Serial2/0 is down, line protocol is down (disabled)
  Hardware is HD64570
  Internet address is 172.16.10.1/24
  MTU 1500 bytes, BW 128 Kbit, DLY 20000 usec,
     reliability 255/255, txload 1/255, rxload 1/255
  Encapsulation PPP, loopback not set, keepalive set (10 sec)
  LCP Closed
  Closed: LEXCP, BRIDGECP, IPCP, CCP, CDPCP, LLC2, BACP
  Last input never, output never, output hang never
  Last clearing of "show interface" counters never
  Input queue: 0/75/0 (size/max/drops); Total output drops: 0
  Queueing strategy: weighted fair
  Output queue: 0/1000/64/0 (size/max total/threshold/drops)
     Conversations  0/0/256 (active/max active/max total)
     Reserved Conversations 0/0 (allocated/max allocated)
     Available Bandwidth 96 kilobits/sec
  5 minute input rate 0 bits/sec, 0 packets/sec
  5 minute output rate 0 bits/sec, 0 packets/sec
     0 packets input, 0 bytes, 0 no buffer
     Received 0 broadcasts, 0 runts, 0 giants, 0 throttles
     0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored, 0 abort
     0 packets output, 0 bytes, 0 underruns
     0 output errors, 0 collisions, 1 interface resets
     0 output buffer failures, 0 output buffers swapped out
     0 carrier transitions
     DCD=down  DSR=down  DTR=down  RTS=down  CTS=down

RT2的设定

Router(config)#hostname RT2
RT2(config)#
RT2(config)#username gemo password ruby
RT2(config)#int s2/0
RT2(config-if)#ip address 172.16.10.2 255.255.255.0
RT2(config-if)#no sh

RT2(config-if)#
%LINK-5-CHANGED: Interface Serial2/0, changed state to up

RT2(config-if)#en
RT2(config-if)#encapsulation ppp
RT2(config-if)#ppp au
RT2(config-if)#ppp authentication pa
RT2(config-if)#ppp authentication pap 
RT2(config-if)#ppp se
RT2(config-if)#ppp pap
RT2(config-if)#ppp pap se
RT2(config-if)#ppp pap sent-username syoui p
RT2(config-if)#ppp pap sent-username syoui password villa
RT2(config-if)#
%LINEPROTO-5-UPDOWN: Line protocol on Interface Serial2/0, changed state to up

RT1和RT2边的ppp封装协议设定好以后,RT1的s2/0的状态,可以看到LCP OPEN的状态

RT1(config-if)#do show interface s2/0
Serial2/0 is up, line protocol is up (connected)
  Hardware is HD64570
  Internet address is 172.16.10.1/24
  MTU 1500 bytes, BW 128 Kbit, DLY 20000 usec,
     reliability 255/255, txload 1/255, rxload 1/255
  Encapsulation PPP, loopback not set, keepalive set (10 sec)
  LCP Open
  Open: IPCP, CDPCP
  Last input never, output never, output hang never
  Last clearing of "show interface" counters never
  Input queue: 0/75/0 (size/max/drops); Total output drops: 0
  Queueing strategy: weighted fair
  Output queue: 0/1000/64/0 (size/max total/threshold/drops)
     Conversations  0/0/256 (active/max active/max total)
     Reserved Conversations 0/0 (allocated/max allocated)
     Available Bandwidth 96 kilobits/sec
  5 minute input rate 0 bits/sec, 0 packets/sec
  5 minute output rate 0 bits/sec, 0 packets/sec
     0 packets input, 0 bytes, 0 no buffer
     Received 0 broadcasts, 0 runts, 0 giants, 0 throttles
     0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored, 0 abort
     0 packets output, 0 bytes, 0 underruns
     0 output errors, 0 collisions, 1 interface resets
     0 output buffer failures, 0 output buffers swapped out
     0 carrier transitions
     DCD=up  DSR=up  DTR=up  RTS=up  CTS=up

这个时候我们尝试改掉RT2的用户名和密码,然后在RT2上debug ppp authentication查看pap认证的状态的变化。

RT2(config-if)#no username gemo
RT2(config)#int s2/0
RT2(config-if)#no ppp au
RT2(config-if)#no ppp authentication 
RT2(config-if)#ppp authentication  pap
RT2(config-if)#
%LINEPROTO-5-UPDOWN: Line protocol on Interface Serial2/0, changed state to down

Serial2/0 Using hostname from interface PAP

Serial2/0 Using password from interface PAP

Serial2/0 PAP: O AUTH-REQ id 17 len 15

Serial2/0 PAP: I AUTH-REQ id 17 len 15

Serial2/0 PAP: Authenticating peer

Serial2/0 PAP: Phase is AUTHENTICATING, Unauthenticated User

Serial2/0 PAP: O AUTH-NAK id 17 len 26 msg is "Authentication failed"

Serial2/0 PAP: Phase is FORWARDING, Attempting Forward

我们可以看到在删掉RT2的用户名以后,debug日志中可以看到从RT2传给RT1的认证错误的信息,告诉RT1你传给我的用户名和密码信息是错误的。
接下来我们再把RT2的用户名和密码改为原有的用户名和密码

RT2(config-if)#username gemo password ruby
RT2(config)#
Serial2/0 Using hostname from interface PAP

Serial2/0 Using password from interface PAP

Serial2/0 PAP: O AUTH-REQ id 17 len 15

Serial2/0 PAP: Phase is FORWARDING, Attempting Forward

RT2(config)#
Serial2/0 PAP: I AUTH-REQ id 17 len 15

Serial2/0 PAP: Authenticating peer

Serial2/0 PAP: Phase is FORWARDING, Attempting Forward

%LINEPROTO-5-UPDOWN: Line protocol on Interface Serial2/0, changed state to up

RT2(config)#do ping 172.16.10.1

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 172.16.10.1, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/2/5 ms

RT2(config)#

我们可以看到,s2/0的网口已经正常启用,这是ping对面的IP也能ping通了。在认证不成功的时候,RT2和RT1对相互连接的串口是ping不通的。

%LINEPROTO-5-UPDOWN: Line protocol on Interface Serial2/0, changed state to up
CHAP验证方式的实验

スクリーンショット 2018-03-10 15.35.44.png

RT1的设定

Router(config)#hostname RT1
RT1(config)#username RT2 se
RT1(config)#username RT2 secret 123
RT1(config)#int s2/0
RT1(config-if)#en
RT1(config-if)#encapsulation ppp
RT1(config-if)#ppp au
RT1(config-if)#ppp authentication ch
RT1(config-if)#ppp authentication chap 
RT1(config-if)#no sh

%LINK-5-CHANGED: Interface Serial2/0, changed state to down

RT2的设定

Router(config)#hostname RT2
RT2(config)#username RT1 se
RT2(config)#username RT1 secret 123
RT2(config)#int s2/0
RT2(config-if)#en
RT2(config-if)#encapsulation pp
RT2(config-if)#encapsulation ppp 
RT2(config-if)#ppp au
RT2(config-if)#ppp authentication ch
RT2(config-if)#ppp authentication chap 
RT2(config-if)#no sh

RT2(config-if)#
%LINK-5-CHANGED: Interface Serial2/0, changed state to up
%LINEPROTO-5-UPDOWN: Line protocol on Interface Serial2/0, changed state to up
     0 output buffer failures, 0 output buffers swapped out
     0 carrier transitions
     DCD=up  DSR=up  DTR=up  RTS=up  CTS=up

RT2的s2/0端口状态

RT2(config-if)#do show interface s2/0
Serial2/0 is up, line protocol is up (connected)
  Hardware is HD64570
  MTU 1500 bytes, BW 128 Kbit, DLY 20000 usec,
     reliability 255/255, txload 1/255, rxload 1/255
  Encapsulation PPP, loopback not set, keepalive set (10 sec)
  LCP Open
  Open: CDPCP
  Last input never, output never, output hang never
  Last clearing of "show interface" counters never
  Input queue: 0/75/0 (size/max/drops); Total output drops: 0
  Queueing strategy: weighted fair
  Output queue: 0/1000/64/0 (size/max total/threshold/drops)
     Conversations  0/0/256 (active/max active/max total)
     Reserved Conversations 0/0 (allocated/max allocated)
     Available Bandwidth 96 kilobits/sec
  5 minute input rate 0 bits/sec, 0 packets/sec
  5 minute output rate 0 bits/sec, 0 packets/sec
     0 packets input, 0 bytes, 0 no buffer
     Received 0 broadcasts, 0 runts, 0 giants, 0 throttles
     0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored, 0 abort
     0 packets output, 0 bytes, 0 underruns
     0 output errors, 0 collisions, 1 interface resets
     0 output buffer failures, 0 output buffers swapped out
     0 carrier transitions
     DCD=up  DSR=up  DTR=up  RTS=up  CTS=up

可以看到LCP的状态已经是Open了。

我们尝试改变RT2的hostname,然后重启RT2的ppp authentication,发现ping不通对面的RT1了,我们把RT2的hostname改回来以后,发现立马又可以ping通对面的RT1了。

RT2(config-if)#hostname RRRR
RRRR(config)#do ping 172.16.10.1

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 172.16.10.1, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/2/3 ms

RRRR(config)#int s2/0
RRRR(config-if)#no ppp au
RRRR(config-if)#no ppp authentication ch
RRRR(config-if)#no ppp authentication ch
RRRR(config-if)#ppp au
RRRR(config-if)#ppp authentication ch
RRRR(config-if)#ppp authentication chap 
RRRR(config-if)#
%LINEPROTO-5-UPDOWN: Line protocol on Interface Serial2/0, changed state to down

RRRR(config-if)#do ping 172.16.10.1

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 172.16.10.1, timeout is 2 seconds:
.....
Success rate is 0 percent (0/5)

RRRR(config-if)#hostname RT2
RT2(config)#hostname RT2
%LINEPROTO-5-UPDOWN: Line protocol on Interface Serial2/0, changed 
RT2(config)#do ping 172.16.10.1

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 172.16.10.1, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/2/4 ms

PPPについてのめも

P++: 銀河に平和をもたらすための奇策と決着

PHP 8から、PHPは「PHP」と「P++」という2つの言語を提供するようになる

というキャッチーな紹介をするP++: 静的型付けをめざすPHPという記事がそれなりに話題になり、このニュースは目覚しく革新的な内容で、多くのひとの目を引き付けました。

これは早まった理解であり、ほとんど誤報と言ってもいい内容でした。2019年8月15日には提案者本人も、少くとも「P++」の計画を短期的に実現するととは非現実的であり時期尚早であることを認めています。

この記事では、PHP開発の現状、なぜ野心的なP++計画が提案され、事実上撤回されたかの経緯について紹介します。

[中立性のための表示] この記事の著者@tadsanはPHPの静的解析を強く推進する立場です。

三行で要約

  • PHPはバージョンを経るごとに「歴史的経緯」による負債が削ぎ落されてきた
  • PHPはRFCと呼ばれる提案とPHP開発者たちによる投票を経て意思決定される
  • いわゆる「P++(仮称)」について、2019年8月現在で決まった事実は何もない

本題に入る前に本件に関連する重要人物にも軽く触れておきます。

  • Zeev Suraski
    • 1997年にAndi GutmansとともにPHP 3を開発した
    • 2000年にPHP 4で仮想機械方式のインタプリタZend Engineを導入する
    • Zend Technologiesの社名や製品名に含まれるZendはZeevとAndiの合成語
    • 今回のP++の発案者
  • Nikita Popov
    • PHP 5.5(2012年)以降、PHPに非常に数多くの提案と実装を行ってきた
    • PHP 7.0では構文解析処理を書き直しASTを導入するなどの立役者
    • PHPの処理系を改善すると同時に、多くのレガシーな仕様の廃止を提案してきた

今回の登場人物を含め、現在のPHP開発においては、誰もPHPについての意思決定権を持っていないことに注意してください。

Ruby作者のまつもとゆきひろ氏などは優しい終身の独裁者とも呼ばれ、Ruby開発における意思決定役を担っていますが、PHPの意思決定プロセスは多数決による投票制です。それはPHPの最初の開発者であるRasmus Lerdorfも同様で、PHP開発メンバーの一員として1票の投票権しかありません。

PHP 7から現在までのおさらい

これからの話の前にPHP 5系から現在までのPHPの変遷について復習します。PHP 7.0がリリースされたのは2015年12月であり、今からおよそ3年半前のことです。

はじめにPHP7以降の変更点から、主に文法の改善に着目して抜萃します。

具体的な説明についてはリンクしたPHPマニュアルの記事を参照してください。

これらの項目のうちには、「複数の記法を一種類に統一した」もののほか、「なぜPHP 5ではこんな不可解な仕様があったのか」と首をかしげるものも含まれます。この要因としてはPHP 7.0で構文解析プロセスの改善(パーサの書き直し、抽象構文木の導入)に伴って、PHP 5時代にあった不合理な文法的制約が大きく取り払われたこと、が大きいです。

次に、PHP 7.0以降で追加された言語機能について主に型・クラス関連に絞って抜萃して紹介します。

  • PHP: PHP 7.0 新機能 - Manual
    • declare(strict_types=1)で厳格モードの型宣言
      • ファイル単位での設定
    • スカラー型宣言
      • PHP 5では「型ヒント」あるいは「タイプヒンティング」と呼ばれ、array, callableとクラス名・インターフェイス名など一部キーワードのみ記述可能で、string, int, bool, floatなどのスカラー型は書くことができなかった
      • declare(strict_types=1) に設定していないとき独自のルールでキャスト
    • 戻り値の型宣言
    • 無名クラス new class {...}
  • PHP: PHP 7.1新機能 - Manual
    • nullableな型 ?
    • 戻り値を返さない関数の特殊な型宣言 : void
    • iterable 擬似型
    • 複数の例外クラスの catch
  • PHP: PHP 7.2新機能 - Manual
    • object 型宣言
    • パラメータの型の拡大変換
      • インターフェイスの実装やメソッドのオーバーライド時に引数の型指定を省略可能に
  • PHP: PHP 7.3新機能 - Manual
    • (型に関連する目立った機能追加はなし)

これらの機能の改廃や追加はRequest for Comments(RFC)という提案と、php.internalsメーリングリストによる議論、PHP開発者らによる投票という手続きを経て導入されています。RFCにはそれぞれの提案の背景や経緯、モチベーション、目的、想定される影響などが明記されています。

まだマニュアルに含まれていませんが、PHP 7.4ではさらに数多くの提案が実装されて居り、実装済みのRFCも列挙します。

全体的に見て、PHPは過去の歴史的事情による非合理な仕様が取り除かれ、ほかのプログラミング言語にあるような言語機能が次々と取り入れられつつある過程にあると説明できます。このような機能追加の過程において非常に大きな役割を果たしてきたのがNikitaです。彼は2012年にジェネレータ(コルーチン)の導入をはじめ、現在に至るまでPHPに多くの提案をしてきました。

Nikitaは継続して多くの機能追加を提案してきただけでなく、毎年のバージョンアップの度にレガシーな機能の廃止提案も欠かさず行ってきました。今回の件の発端は現在投票期間中の提案PHP RFC: Deprecate short open tags, againです。

銀河に平和をもたらしたい

2019年8月8日にZeevがBringing Peace to the Galaxyという件名のメールをphp.internalsメーリングリストに投稿しました。

[... and not in the Sith Lord kind of way.]

件名と繋げると、銀河に平和をもたらす。 ……シス卿のような方法ではなく。 から始まる長文のメールです。冒頭部をざっくり訳すと以下のような内容です。

internals@(メーリングリスト)の最近の(それとあまり最近ではない)議論と最近の提案のいくつか、そして言語の方向性についてのいくつかの声明の見てください。明らかに私たちは両極化が高まっています。

Peterが昨日言ったように、一部のひとたちはいくつかのレガシーなものを取り除きたいのです。私が思うに実際にはその範疇を超えてしまっており、internals@の多くは、PHPの各部はひどく修理が必要で(私も一部同意しますが)、ほかの競合する言語にある機能が「彼らの意見では」非常に欠けているとのことです。

両極化した一方の端には、私たちが常に抱いていた、後方互換性についての強い偏見を維持すべきであり、PHPは緊急のオーバーホールを要しているわけではなく、機能に関して「少ないことは豊かなこと(less is more)、私たちはほかの言語から競って機能をコピーすることはせず、むしろPHPをシンプルに保つことを選択する」と考える人々が居ます。

これらの視点はほとんど正反対です。そのため、internals@の議論は片方が勝って相手が負けるゼロサムゲームと化してしまいました。

私は前者よりも後者の陣営での見方がずっと近いと言ってよいでしょう。それと同時に、前者の視点にも優位性があることも理解しています。私の陣営が「勝った」として、どちらかが勝てばどちらかが負ける議論による否定的な雰囲気や、そのほかのグループの(私がとても尊敬している)人々が感じる失望感は間違いなくプロジェクトにとって悪いことなので、私はしばしばピュロスの勝利(犠牲に見合わない勝利)のように感じます。(立場が逆になったときに、同じように感じてくれると願っています)

では、両方の陣営を本当に幸せにする方法があったらどうでしょうか。私はあると思います。

この記事ではこれまで7.0以降のPHPが積極的に後方互換性を切り捨てて新しい機能を取り込んできたことを紹介しました。しかしそれはPHPコミュニティの総意だということはなく、あまり好ましく思わない人々も少なからず居るということです。

話題に挙がったP++は、Zeevがそれを解決すべく提案したアイディアです。ここではC言語とC++、(旧来の)JavaScriptとES6のような関係を引き合いに出し、保守的な言語としてのPHPと、革新的な機能を取り込むため言語(仮称:P++)を分けよう、PHPの悪評を覆すために言語名は分けようというのです。

このメールの結びでは、このアイディアはコーナーケースについてまだ熟慮していない、生のアイディアであることを認めていますが、Zeevは技術的にも実現可能性は高いと見ており、ブレインストーミングを促したいというのがこのメールの趣旨です。

この議論の直接の契機となったのは、PHP RFC: Deprecate short open tags, againについての議論でしょう。この提案は<?php … ?>の代りに単に <? … ?> と書ける機能を廃止しようとする提案です。短いタグ(<? … ?>)はphp.iniで無効化することができるため、すくなくとも現代のPHPのライブラリとして一般公開されるようなコードでは <?php または <?= … ?> の二種類のタグのどちらかだけを使うことが暗黙の了解となっています。

しかしながら議論は上記で引用したメールで要約されたように、[RFC] [VOTE] Deprecate PHP's short open tags, again - Externalsのスレッドでは、いささか痛々しい応酬を呈しています。Zeevは廃止提案に対してCounterargument to Deprecate Short Tags RFC V2として反論をまとめています。要は「壊れてないものを直すな」「あってもなくても誰も困らない仕様を消すために時間を浪費するな(させるな)」という主張です。

つまりP++はどういう状況なの?

P++は現在、元スレッドのBringing Peace to the Galaxy - Externalsと次のスレッドP++: FAQ - Externalsで議論されています。

今回の渦中にある文章PHP: P++ idea: FAQは単なるメーリングリストの議論のための「よくある質問」をまとめたメモ書きをwiki.php.netに置いたに過ぎず、「PHP 8の方針について決定事項の告知」という性格のものではありません。 PHP 8.0で導入される実装済みの機能は https://wiki.php.net/rfc#php_80 を参照してください。

FAQの内容については型付きPHP、P++のFAQを参考にしてください。

さて、Nikitaはこのアイディアについて基本的に反対ですが、実現可能性に関しては、これまで数々の機能をPHPに取り入れてきたNikitaでさえ、次のような見解を示しています。

I think this part is unrealistic from a simple manpower perspective. We have something like ~2 full time developers working on PHP. Even if you can rally some additional interest around this idea, I don't think we have the resources to create a substantially different language in any reasonable amount of time. Doing feature additions and changes to PHP is Hard. Even simple changes require a fair bit of design and engineering effort to integrate with the large complexity of the existing language. This would not change for a hypothetical P++, because we still need to interoperate with PHP.

Even if I agreed with the idea (which I'm pretty skeptical about in this
particular form), I really don't think we have the resources to do
something like this.

https://externals.io/message/106453#106472

要約すると 単純に人材が居ないから無理。フルタイム開発者が興味を持って取り組んだとしても妥当な時間で実質的に新しい言語を完成させるのは無茶。PHPとP++を分けたところで相互運用しなきゃいけないんだし設計めっちゃ大変。私がこのアイディアに賛成したとしてもリソースがないから懐疑的と言ってますね。

現状まだRFCとして提案されておらず、「P++」の仕様はおろか実現可能性も含めて具体的な検討前の段階です。

「本の虫」の記事について

P++: 静的型付けをめざすPHP

PHPで静的型付けをしやすくする機能強化を推進する潮流があるのは事実で、そのような仕様強化はPHPではなくP++に行おうという提案である。ただし提案者のZeevはPHPの意思決定の代表者ではない。

PHP 8から、PHPは「PHP」と「P++」という2つの言語を提供するようになる。

P++はコミュニティの分断と対立を憂慮したZeevが解決のためにしたアイディア(もはや奇策)であり、メーリングリスト上でのブレインストーミングの対象とはなっているが、実装方針・実現可能性・リリース時期について何の意思決定がされたわけでもない。

また、FAQにおいては「PHP 8/9?」程度の言及であり、2020年12月にリリース見込みであるPHP 8.0にP++が導入されることをZeevが主張しているという事実もない。

PHPとP++は同じコードベースであり、ほとんどのコードは共有するので、PHPの開発リソースが2倍必要になることはない。

これは非常に楽観的な見解で、現状P++の仕様、特に型の設計について具体的なものは何も示されていないので、なんとも測りがたい要素です。型についてPHPの標準関数の挙動にまで及ぶ厳密な型システムを導入した場合、PHPとの相互運用のための開発リソースが2倍以上必要になるであろう事態も想像に堅くない。

ありそうな質問

  • Q: なんでこのひと銀河の平和の話をしてるの?
  • A: さあ…

私からは以上です。P++が本当に導入されるかどうかはどうでもいいですが、php.internalsに平和が訪れるといいですね。

追記 (8月15日)

日本時間で8月15日になって、Xdebug開発者でPHP 7.4リリースマネージャでもあるDerick RethansがRFCで「P++の実現可能性についての世論調査」という名目で投票を開始しました。これはPHPの開発方針として具体的な仕様を取り入れること決めるものではなく、それぞれのZeevが提案するP++プロジェクトに投票者(開発者)個人が時間とエネルギーを費す意向があるかということを調査するものです。

こうやって陣営を色分けしようとすることが非難されたような気がしないでもないのですが、議論に時間を使う前にそれぞれの開発者の意向を明確にしたいのは理解できます。

日本時間の4時0分現在では0:22で圧倒的にNoです。これは世論調査なので通常のRFCとはかなり毛色が異なるのですが、普段のRFCで議決権を行使してないメンバーも積極的に「No」をつきつけている状況です。直近の提案だと投票者が多いものでPHP: rfc:typed_properties_v2に70人ほどが票を投じてるのですが、今回の意識調査にはTyped Propertyの議決に参加してないひとが投票しているので、あまり参考にならない感じです。

php.netのVCSのアカウント(=RFCの議決権)を持っているからといってPHPのアクティブな開発者だというわけではないのですが、すくなくとも人数の面では多くの開発関係者が、P++は非現実的なアイディアだと見ている状況です。

追記2 (8月15日)

PHP: rfc: Poll: Feasibility of P++にZeev本人も「No」を投じ、短期的に「P++」計画が推進されることはなくなったようです。

スクリーンショット 2019-08-15 6.51.15.png
(時刻表示はUTC: 日本時間 2019年8月15日5時59分)

雑な訳ですが、Vote: Straw poll for P++ feasibilityでのZeevの投稿を引用します。

ユーモラスなトーンによって、やっとinternals@がまとまったことを嬉しく思います。
私はあなたがたがこのアイディアが好きではなさそうだという感触を得ました。

大事なこととして、私はこの投票の正当性についての意見(投票の過程、権限などなど…)は自分の中にしまっておき、2点だけコメントします:

  • このP++のアイディアは真空では無意味です。このアイデアに関する歓迎は、「1つの幸せな大家族」と「分裂」の間にある決定を暗示しました。現段階ではそれらが選択肢として理解されているので、私も反対票を投じたいです(いま投票しました、もちろん)。でも、それは間違った選択だと思います。
  • 「1つの幸せな大家族」だけが選択肢ではないと明らかになったとき、それを議論するのは確実に意味があることです。家族をソフトに分割する方法を選びましょう: 「細分化 (2n方言)」「多くのエディション (n方言)」または「明確な権限の別の方言 (2方言)」。それは私たちの多く(私も多分に含まれる)にとっては不可解だと感じ、このアイディアは全員が団結して反対する「邪悪な分断者」だと受け止められたのだと思います。おそらく私は違っていて、PHPに導入しようとしている変更や機能はどのような分割も必要としないのでしょう。それが事実なら、本当におそろしいことです。私たちはこの道を進むと、それを見ることになるでしょう。現段階でそのレベルのエネルギーをつぎこむことは明らかに早いです。
  • ですが、私たちが直面しようとしている現実が明らかになったとき、それを探求することには間違いなく意味があります。

このスレッドではこれ以上は返信しません。ただし個人的なメッセージには喜んで応えます。

Zeev本人がこう言ってるので、すくなくともPHP 8.0(2020年12月)に向けたP++が導入されることはないでしょう。コミュニティとしては対立構造が浮き彫りになったことを認めながら、言語分割ではないベターな妥協点を見付けていくことになるでしょう。

型付きPHP、P++のFAQ

以下はP++ idea: FAQの日本語訳です。
オーサーのZeev SuraskiはZendのZeで、ようするにPHPのすごい人です(特権とかは特にない)。

P++ idea: FAQ

これはinternalsで提示したアイデアに関するFAQです。
その後の議論で何度も提起された、多くの問題点に対処するものです。
P++は一時的なコード名であり、変更になる可能性があります。

What is this all about?

これは何?

短くまとめると以下のようなものです。

PHPの世界は、大きくわけてふたつの考え方があります。
まずひとつめは、PHPのアバウトで後方互換性が強力でシンプルさを重視しているところが好きな人々です。
もうひとつは、より高度で複雑な機能を持ち、古い文法は切り捨てる、厳密な言語を好む層です。

ここには「正しい」も「間違い」もありません。
どちらも意義のある考え方であり、どちらにも多くの支持者がいます。
しかし、これら両方の考え方を同時に満足できる言語を作成することは困難です。
これはinternalsで常に論争が発生する原因のひとつです。

この提案は、PHPと共に利用できる新たなPHPの方言を作ろうというものです。
この新たなPHPは、PHPの歴史哲学に縛られることはありません。
この方言は本家よりより厳密であり、後方互換性に縛られることなく、不要な要素はどんどん削除し、より複雑な機能、特に厳密な型付けといった要素を、PHP本家のような複雑さを伴わずに導入することができます。

これはforkではありません。
コードベースは同じであり、コードベースを利用する開発者も同じです。
コードの大部分は同一であり、特定の一部のポイントのみが異なる実装を持つようになります。
これはPHP7で導入されたstrict_typesと同じようなものであり、そしてそれよりは大規模なものです。

Do we really need to do all that just because some folks can't give up on short tags?

一部の人々がshort_open_tagを諦めることができないという理由だけで、こんな実装を行う必要がありますか?

このproposalはshort_open_tagとは無関係であり、そのRFCがこのproposalの動機になったわけではありません。
この提案の目標はもっと野心的で、PHPの明確なビジョンを示すことです。
そしてゆるふわPHPとガチガチPHPの両者を提供することで、最終的にはinternalsの両派閥の緊張を和らげることを願っています。

Why fork PHP?

これはforkではありません。
同じコードベースで管理され、同じバージョン管理され、同じ人々が開発し、同じバイナリで提供されます。
PHPをインストールすると同時にP++がインストールされ、その逆もまた然りです。
ひとつのバイナリでPHP、P++、そしてPHPとP++が混ざったソースを実行することができます。

あるPHPファイルがP++であることをどのように示すかはまだはっきり決まってはいませんが、おそらくファイル最上部に何らかのヘッダを記述することになるでしょう。

<?p++?>
<?php 'Hello, world!'; ?>

さらに、名前空間全体をP++であると一括指定する方法を考えているため、フレームワークなどは個々のファイルそれぞれにP++をマークしていく必要はありません。

This means doubling our dev efforts, while internals@ is already low on contributors. How will we deal with that?

internalsでの開発者が減少しつつある現在、開発工数が2倍になるのだが大丈夫か?

その指摘はまったく当たりません。
コードのほとんどは、PHPモードとP++モードで共用されます。

データ構造、主なサブシステム、エクステンション、Webサーバインターフェイス、OPcache、およびその他ほとんどにおいて、実行中のファイルがPHPであるかP++であるかに関わらず、全く同じコードが実行されます。
追加になる開発オーバーヘッドは、PHPとP++で異なる特定部分だけになります。

P++はPHPに比べるとチェックが増える可能性が高いため、一部のコードには2つのバージョンを維持するため多くのif文の追加が必要となることでしょう。
しかしながら、これは厳密なチェックを導入するためには、どうしても必要となる要素です。
ガチガチコードの最過激派においてさえ、移行段階を経ることなくいきなり厳密コードしか使えなくしようなどとは想定していません。
従って、このアプローチは、他の多くのRFCと同じような段階的取り組みだと言うことができます。

Why not just make a perpetual PHP 7.4 LTS and be done with it, as we move to a stricter PHP 8/9?

PHP7.4をLTSとして長期サポートし、PHP8/9は厳密モードだけにするのはどうでしょう?

このアプローチには多くの問題があります。
アバウトPHPを好む層は、今後の機能追加やパフォーマンス改善が見込めないとしてもPHP7.4に留まり続けます。
このproposalの意図と異なり、これは実質的にforkを意味します。

Will I need to choose between PHP and P++?

PHPとP++どちらかを選ぶ必要がありますか?

イエスでもあるしノーでもある。
前述したように、片方をインストールするともう片方も自動的にインストールされるので、ひとつのサーバで両方の方言を実行可能です。
しかし実際には、strict_types同様に、プロジェクトによってどちらかひとつを選択して使用する可能性が高いでしょう。

Will I be able to mix and match PHP and P++ in the same app?

ひとつのアプリでPHPとP++を混ぜて使用できますか?

はい、コードがPHPであるかP++であるかの判定は、リクエスト単位ではなくファイル単位で行われます。
正確な判定アルゴリズムはこれから検討する必要がありますが。
PHPファイルのコードはPHPセマンティクスで動作し、P++ファイルのコードはP++セマンティクスで動作します。
これはstrict_typesの動作とよく似ています。

これは最初は厄介そうに思えるかも知れませんが、こうすることで実用的な使用例が生まれます。
たとえばP++フレームワーク上でPHPのコードを動かす、あるいはその逆です。
CとC++の関係に、少しばかり似ています。

Does it mean PHP will no longer evolve? Will all new features go into P++?

PHPは進化しなくなりますか?全ての新機能はP++にだけ導入されますか?

いいえ。別々に進化するということを意味します。
厳密型に関する機能はP++だけに適用される可能性が高く、P++ファイルでのみ使用可能です。
互換性は維持されますが、今後決して壊れないという意味ではありません。

JITなどのパフォーマンス向上、エクステンション、非同期といった、厳密性と関係の無い機能はPHPとP++の両方で利用できます。

What are the benefits of this approach?

このアプローチの利点は何?

このアプローチには多くの利点があります。
まずinternalsやその他の場所にいる、両派閥陣営にともに良い解決策を与えます。
PHPの動的な仕組みを好む人はそちらを使い続け、厳密な型指定を好む人はそちらに移行することができます。
次善の策は、ゼロサムです。
すなわち、勝った派閥が全てを手に入れ、もう片方には何も残りません。

技術的に優れた解決策であるうえに、最小限の労力で使用者の全てをサポートすることができます。
また、近年のinternals戦争の主要な原因に終止符を打つことができるかもしれません。

最後に、このドキュメントの読者はほとんどが技術者であると思われますが、クリーンな状態から始まるP++にはポジショニングやブランディングに対する大きなアドバンテージが存在するでしょう。
言語仕様上の理由でPHPを選択対象から外した企業、上司、開発者は、PHP8や9のリリースよりP++のリリースに注目する可能性が高いでしょう。

Aren't we risking fragmenting the userbase?

ユーザのコードベースを分断する危険性はありませんか?

その可能性はあります。
しかし、それはこのアイデアの欠点ではなく、現在既に存在しているものです。

PHPの動的な性質を好む大勢の人がいて、彼らはPHPがどんどん型志向に向かいつつある現状を畏れつつ見守っています。

それと同時に、『このナンセンスな動的性質を排除するのにどうしてこんなに時間がかかるんだ』と考えている大勢の人がいます。

これはどちらが良い悪いということではありません。
この相反する両者とどちらも手を繋ぐための手段は、あまり多くありません。

・動的PHPを保つ:strict主義者には受け入れられません。
・厳格PHPに移行する:動的主義者には受け入れられません。
・forkする:これは純粋な損失です。技術的な利点はなく、それでなくとも開発者の手が足りません。
・両方を満足させる:このproposalがやろうとしていることです。プロジェクト自体は統一したまま、相互運用性を持つふたつの方言を維持します。コードの分散は避けられませんが、できるかぎり最小限に留めます。

How does this differ from Nikita's Editions idea?

NikitaのEditionsアプローチとの違いはなに?

彼の提案とは多くの類似点がありますが、意味的な違いが幾つか存在します。
Editionsアプローチを完全に理解できていないため、以下は不正確である、あるいは誤りがある可能性があることに注意してください。

・このproposalでは、動的型付けのPHPも維持するという明確な目標があります。
すなわち、長期にわたり最新機能を完全サポートしていく、PHPの方言です。
Editionsアプローチは、現在の動作をレガシーと見做します。
すなわち、ある時点で推奨されなくなり、いずれ削除される可能性があります。

・ロールアウト戦略は明確に異なります。
P++の場合、PHPと完全に互換性のない要素(厳密性、型操作ロジック、配列インデックス、変数定義など)に注力し、P++の初回インストール時にそれらを全て利用可能にすることを目指します。
すなわち、新たなプロジェクトやフレームワークをすぐに開始することができることを目標としています。
それ以降にふたたび互換性を損なう変更が導入されて、一年後すぐに大幅な書き換えが必要になる、といった事態を避けるためです。
Editionsアプローチでは、PHPの要素を徐々に追加・置き換えていく方針となっています。

・ロールアウト戦略に関連して、Editionsアプローチでは方言を2種類だけに限定していません。
PHP2020方言とPHP2022方言に加えて、PHP2027方言も増えていきます。
それら全てを維持するとなると、メンテナンスコストはさらに増大します。

・このproposalではPHPとP++の後方互換性に対する戦略についても言及していますが、Editionsアプローチはそのことについて特に触れていません。

・Editionsアプローチにはポジショニングやマーケティングの側面がありません。

2つのアイデアは決して排他的なものではないことに注意しましょう。
P++を導入し、それをEditionsアプローチで進化させることも可能です。
特に、最初のP++インストール時に全ての変更を取り込むのが困難だった場合など。

What are the challenges?

課題はなにがありますか?

課題は尽きません。

まずは人材を確保する必要があります。
このアイデアは、PHPが完全な動的型付けになればいいという人と、PHPが完全な静的型付けになればいいという人の目的を諦め、異なる考え方をする人の考えを受け入れる必要があります。
これは存外に大きな課題のようです。

このアイデアが成功するためには、P++の最初のバージョンは、PHPと互換性のなくなる変更点の全て、あるいは少なくともそのほとんどを実装していなければなりません。
ひたすらswitchを埋め込む作業はおそらく相当に苦痛だと思いますが、一度開発が終わってしまえばその後はコードを全面的にリファインする必要はなくなるでしょう。
我々の手持ちの開発力では、その開発を一度でやりきるのは楽観的すぎるという懸念をいくつも見ます。
開発項目のリストについて、よりよく理解する必要があります。
P++の最初のバージョンで全てのアイデアを実装する必要があるわけではないことに注意してください。
ユーザサイドの大幅なコード書き換えが必要になる要素のみを優先付け、最初のリリース時はそれだけを注力して処理することになります。

そして最後に、このチャレンジングな挑戦に相応しい、この方言の正式名称を決める必要があります。

This is Hack all over again, isn't it? Why would it fair any better?

これHackだよね?

概念としては、P++とHackの動機は似ていますが、両者には少なくとも二つの大きな違いが存在します。

Hackはボランティアによるオープンプロセスではなく、ひとつの企業によって開発されたものです。
いくら背後に巨大なベンダーを抱えていたとしても、企業や個人はしばしばそのことを嫌がりました。

より大きな違いとして、HackやHHVMには実行環境を広く配布する手段がありませんでした。
ユーザにとって、Hackを試してみるというのは骨の折れる仕事でした。
その存在を知り、十分な関心を持って調べなければなりません。
たとえ使いたいと思ったとしても、PHPとは全く異なる方法ゆえ、セットアップからして苦戦しなければなりませんでした。

P++は全く異なります。
PHPが使えるということは、すなわちP++が使えるということです。
何かをインストールしたり、何かをセットアップしたりする必要は全くありません。
あらゆるLinuxディストリビューション、あらゆるWAMP/MAMPを使用している全てのユーザが、PHPを最新バージョンにバージョンアップすれば、それがつまりP++が使えるということです。

ユーザの認識としては、PHP7のパフォーマンス大幅向上(ほとんどのPHPerはそれに気付いていません)と同じように、P++は『PHP8の新機能』の一部となります。

もちろん、誰もがそれをすぐに使い始めるわけではありませんが、P++への参入障壁は、Hackへのそれよりも桁違いに低いものとなります。

What are the general concerns?

全体的な懸念点は?

Arnold Danielsが懸念点をまとめました
ここではそのいくつかにおいて回答します。

Converting PHP code to P++ code is not trivial

PHPコードをP++に変換するのは簡単ではない。

それは確かですが、最終的にはP++がどこまで独自仕様を導入するかによって決まります。

このproposalの前提は、そもそもPHPを現在のPHPとは大幅に異なる、静的で強力な型付けに変更したいと考えている大勢の開発者がいるということです。
PHPをより動的で、緩やかな型付けにしたい人たちとのゼロサム戦争にしたいのでないかぎり、これは悪いことではないはずです。

PHP tooling will not support P++

ツールがP++をサポートしないのでは?

ベンダーにとっては、P++のサポートはdeclareをサポートするより簡単です。

It's not possible to do a cleanup without breaking PHP compatibility

PHPとの互換性を損なわずに型付ける方法がありません。

それは確かです。
しかし、むしろそれこそがこの新しい言語を導入する理由です。
厳格PHPの支持者の多くは、下位互換性を破棄してでもより大きな実を手に入れることを望んでいます。
これはすなわち、互換性を守っていきたい開発者との選択肢としては、ゼロサムゲームしかありません。
最近はこのような互換性を切る事例が散見されますが、将来的にはさらに多くの切り捨てが待ち受けています。

Andyが言及した一部事例に関して回答しておくと、
array()を削除してもP++やPHPの互換性は途切れません。それは[]のシンタックスシュガーです。
・関数のグローバル名前空間を削除すると、それはP++にのみ影響します。PHPでは引き続き存在します。

これらの回答は議論を経たものではないため、P++に導入されるかもしれないしされないかもしれません。

The popularity of Python doesn't have to do with typing

Pythonは型付けとは縁がないのに人気です。

このドキュメントおよびproposalでは、強い静的型付けが正しいとか悪いとかは一切主張していません。
どちらが正しいかではなく、PHPユーザには相反する二つの考え方が存在することを認めることです。
このproposalが行うのは、効率的かつ生産的に、二つの考え方の両方に対応する方法を提供することです。
強い型付けをより良い考え方だと考える人が多いので、そのオプションを備えるということは、彼らのモチベーションをアップさせることに繋がるかもしれません。

Is there really a need for a different dialect?

本当に方言が必要なん?

厳格原理主義者が求めているのは、より強く、より静的に型付けされた言語であることがすなわち進歩した言語であるということであり、そして主な障害は、それをどのように実現するかです。
クラウドをレガシーなPHP7.4に維持したまま、PHP8でそれを実現することが可能でしょうか?
目的地に到着するまで、数年ごとに少しずつ変更をリリースし続けますか?

しかし同時に、厳格陣営の開発者が求めているのは、単にstrict_typesのように実用的な厳格性を使いたいということです。
P++は誰にとっても後退ではなく進歩であり、特に強い静的型付け言語を好む人にとっては大きな進歩です。
これこそが我々が目指す方向になるでしょう。
すなわち、とにかく方言を利用できるようにするということです。
実のところ、方言を2^N個持つか(granular declare()s)、N個持つか(Editions)、2個持つか(PHP/P++)というだけの違いです。

感想

PHP internalsでは、アバウトゆるふわなPHPでありたい勢と、ガッチガチstrictなPHPにしたい勢による武力闘争が長らく続いており、P++はその戦争を終わらせる最終手段として投入されました。
なにしろMLのタイトルがBringing Peace to the Galaxyですからね。
結論としては両方やればいいじゃんということで、要するにJavaScriptにTypeScriptを抱き合わせセットにしちゃおうぜみたいな話です。

strict_typesはPHPとの互換性を保った上でさらに厳密な記述を導入するというアプローチでした。
いわゆる上位互換であり、strict_typesなPHPは素のPHPでも完全に動作します。

しかしP++は、厳密性を導入する傍らで互換性を一部切り捨てます。
すなわち、P++のコードがPHPでは動かない、逆にPHPのコードがP++では動かない、といったことが発生します。

これまでのPHPの方針である『厳密に書くこともできる』を転換し、『厳密に書かなければならない』を強制するということで、なかなか思い切った方針転換ですね。
といっても適用はファイル単位なので、気分で使ったり使わなかったりが可能だったりはします。
ユーザ側としては、実のところstrict_typesとたいして変わらない使い方になりそうです。

あれば便利だとは思いますが、しかし、いくらforkではないと強弁したところで実装工数が相当に増えるのは間違いありません。
PHP本体の開発ですらわりかし手一杯なのに、そこからさらにP++にまで割くリソースがあるのかは正直疑問なところです。
特に、開発リソース不足を指摘しているのがかのNikitaですからね。
これからこのproposalをRFCにまとめ、投票で2/3の賛成を得て、軌道に乗るまで実装が進むか、というと相当微妙だと思います。

はい、現状これはRFCですらありません。
ただの思いつきのひとつに過ぎません。
個人的には、このproposalはRFCにすら辿り着かないか、RFCまで行ったとしてもDraftのまま塩漬けになるんじゃないかなと思います。

Browsing Latest Articles All 5 Live