まずは他の言語を始める
PHPは色々な言語をごちゃ混ぜにしたような言語である。
なので、勉強をするなら混ざる前のものから手を付ける方が理解しやすい。
C言語
C言語は文字列、構造体、ポインタが分かる程度のところまでやる。
関数ポインタまでやる必要はない。JavaやJavaScript等の他の言語をやったあとに戻ってくると何となく理解できるようになっている。
https://php.net/fopen
https://linuxjm.osdn.jp/html/LDP_man-pages/man3/fopen.3.html
https://php.net/strcoll
https://linuxjm.osdn.jp/html/LDP_man-pages/man3/strcoll.3.html
PHPはC言語からそのまま持ってきた関数が多いので、このようにC言語のマニュアルそのままの関数も多い。なので、何故このような関数になっているか?というような関数の成り立ちをPHPの中だけで考えても意味がない。PHPとしてファイル操作のためのfopen
を定義したわけではなく、単にC言語のfopen
をそのままPHPに持ってきただけなのだということを頭に隅に置きつつコードを書くべきである。
fopen
の r
や w+
は一見意味不明なインターフェースだが、C言語をやった後だと慣れで書ける。
PHPを作ったラスマス・ラードフ氏は
https://gihyo.jp/news/report/2015/12/1401?page=4
モジュール間での共通性には欠けるかもしれませんが,OCI拡張モジュールもMySQL拡張モジュールも,下で動いているC APIにほぼ1対1で対応している点において整合性があるといえます。MySQLドキュメントのC APIに関する部分を見てみれば,PHP開発者にとってはなじみ深く感じられるはずです。どの低レベル関数もPHP側の何かと対応しているからです。だからPHPは垂直方向に見れば整合性はあるのですが,多くの人から始終「PHPはまったく整合性がない」と言われます。整合性は確かにあるのです。ただ,人々が思っているような水平方向にはないというだけです。垂直方向に見れば,完璧な整合性があります。
このように言っている。
最近はバイナリセーフな関数が増えてきたとは言えるものの、まだバイナリセーフでない関数もある。初心者はそもそもバイナリセーフでないとはどういうことかと悩むところだが、C言語で文字列をやった後だと「あ〜Cのライブラリにそのまま渡してるからNULL終端なのね」ということがすぐに分かるだろう。
そのうち「あ、なんかC言語っぽい名前のマイナー関数だからバイナリセーフではないのかも?」と勘が働くようになるはずだ。
ポインタや構造体は必須ではないが、PHPの参照を理解する手助けになる。あと->
の記法に慣れる。
その後、C言語のつもりで参照を無駄に使って余計にパフォーマンスが下がるというところまでが1セットである。
Java
PHPのオブジェクト指向はJava由来のものが多い。
デザインパターンやDIコンテナ、インターフェースの設計、DDD、これらクラスベースのオブジェクト指向に真面目に取り組むなら、PHPでやるよりもJavaでやった方が良い。
PHPのためのJavaと考えるならJava 1.4で十分なので、最近Javaが取り入れている関数型っぽい機能の部分はスルーしてオブジェクト指向に関するプログラムをやるのが良い。
静的型付け言語特有のAOPや汎用プログラムとしてのスレッド処理などもスルーして、クラスとインターフェースの基本的な部分をやる。
共変性と反変性やジェネリクスについては現在のPHPではまず出てこないのでJavaでやっておいた方が良い。
ジェネリクスはPHP本体の機能としては使えないが、PHPStanのような静的解析ツールを使うことを考えると必要になる。
それから、SPLの中では比較的よく使うイテレーター https://php.net/spl.iterators もJavaでやっておいた方が良い。
Perl
スクリプト言語での文字列処理と言えば正規表現であり、スクリプト言語での正規表現と言えばPerlである。
https://php.net/pcre
PCREとはPerl Compatible Regular Expressions、つまりPerl互換正規表現のことなので、歴史も例題もPerlで調べた方が早い。
そのためにはある程度は使えるようになっておく必要がある。
Ruby
RubyというよりもRuby on Railsをサンプルアプリケーションを作れる程度にやっておく。
PHPに限らずWebアプリケーション用のフレームワークはRailsに影響を受けて作られたフレームワークがいくつもあるので、本家の思想を知っておくと理解が早い。かつ、他の言語のRails風フレームワークを使うときにもすぐに慣れることが出来るようになるメリットがある。
JavaScript
Webアプリを作るにはどうせ必要になるのだから先にやっておく。
JavaScriptでクロージャに慣れておき、共通パターンの一部だけ変更するような処理をabstract classで実装するのかインターフェースを使うのかコールバックで実装するのかという選択肢を増やしておく。
ちなみにPHPのシンプルな無名関数はstatic function(){}
である。static
無しの場合は$this
がbindされる。
PHPの無名関数はbindTo
メソッドでthisの差し替えもできるので、JavaScriptも今風のライブラリは使わずに素のbind
やapply
に慣れておく。
===
演算子にも慣れておきたいところだが、これはJavaScriptではあまり使われないのかもしれない。PHPほど厳密な比較云々という記事を見かけない。
その他
TypeScript, Haskell, Go, Rust等。
PHP8からunion型が使えるようになる、かもしれない。
静的型チェックをするなら現在でも使える。
そのためにunion型が使える言語をやる。
100
と100.0
と'100'
を全部受け取りたい といったときに後ろ向きな気持ちで int|float|string
と指定するのも有りと言えば有りだが、代数的データ型を使える言語で積極的に複数の型をアルゴリズムに組み込むのも良い。
public Left|Right $either;
が型レベルで保証されると、手抜きもしつつ安心感も増す。
プログラムの習慣としてPHPで使えそうなものもある。
例えば
function do_something($i)
{
if (!is_numeric($i)) return [null, 'invalid argument'];
return [$i + 1, null];
}
[$ret, $err] = do_something($_GET['i']);
というようなエラー処理方法でも良いわけである。
使ったことが無ければどちらが良いかという判断もできないので、まずは他言語のパターンというものも知る必要がある。
trait
に関しては、他の言語の経験がむしろ混乱の元になるかもしれない。
PHPでは珍しく正統派の(?)ものなので、mix-inとは若干使い方が異なる。
trait
のサンプルはScalaではなくSmalltalkになるようだ。
PHPを始める
ここまで来れば、PHP自体を一度も見たことがなくても大抵のPHPプログラムは読めるようになっている。
むしろPHP初心者を既に脱している。
最近はmagic_quotes_gpc
といった致命的な落とし穴も無いので、ハマることも少ない。
PHPの終了タグ?>
は書かないであるとか、static
変数はリクエスト毎に破棄されるとか、そんな程度である。
PHPというプログラミング言語特有の勉強が別途必要だということは無い。