どんな内容か?
転職して、JavaからPHPの仕事をするようになり、PHPとSymfonyを学習して、Javaとの比較で気づいたことをまとめてみました。
PHPのようなスクリプト言語をやることで、Javaの特徴やメリットを改めて気づくことが多々ありました。ある段階までいくと、違う言語をやることで双方の理解がより深まるようです。
JavaとPHPの比較
PHPには返り値や変数の型を指定できない
Javaでメソッドを定義するときは、返り値や引数の型を次のように指定します。
public boolean isEnemy(User user) {
return ...;
}
PHPでやると、そんなものはなにひとつ書かなくてもよいです。
public function isEnemy($user) {
return ...;
}
ただ、引数については、5.x系ならタイプヒンティング、7.x系から型指定として、設定できるようです。
7.x系からはstring,intなどが指定できるようになったものの、5.x系ではjavaのように気軽に指定できないのは少し不安なところです。
IDEはPhpStormがおすすめ
IntelliJ IDEAと同じところが出していますから、そっちを使ったことがあれば慣れるのは早いです。
オーバーライドしているかを表示してくれる
Javaの場合、interfaceや親クラスのメソッドをオーバライドを明記するために、@overrideを付与できます。IDEAも、その箇所の左側にoマークが表示れます。
しかし、phpdocにはそれに相当するものはありません。でも、PhpStormならIDEAと同じようにoマークがでてくれます。
宣言箇所へのジャンプ、呼び出しもとのリストアップ
IDEAと同じように、メソッドや定数の宣言箇所へのジャンプや、それらが使われて居る箇所の一覧を表示することができます。DIしていたり、テンプレート内での使用箇所は流石に拾えないですが、それはjavaのときも一緒ですので。
型がわかるときはメソッドなどのサジェストがされる
$hoge = new Hoge()
みたいに、変数の型が特定できる箇所では、IDEAと同じように、そこからアクセスできるメソッドやプロパティがサジェストされます。
phpdocで引数や返り値の型を書いておくと、それと違ったときは警告がでる
下記のように、引数や返り値についてphpdocを書いておくと、引数に違う型を渡したりすると警告を出してくれます。
/**
*
* @param string $id
* @return boolean
*/
public function isStored($id) {
return ...;
}
foreachは右側に繰り返し要素
javaの拡張for文は左側にリストの要素
for(int index: list) {
///
}
arrayはリストも連想配列も多次元配列も扱えてしまう
javaのList型は、まさしくただのlistで、多次元配列にしようと思ったら、List>みたいなことや、そのための型を使うことになります。
けど、phpのarrayはある意味やりたい放題で、
$tmp = array(1 => array("a" => 2), 2 => "c")
などと、array使えば、どんどん連想配列をつくれてしまいます。
namespaceはpackageとは違う
javaのパッケージと違って、名前空間の棲み分けが主なようです。同じnamespaceにしたからといって、それらをautoloadしてくれるわけではないようです。そういうことをするためのライブラリなり設定なりを追加すればできるらしいですが。
javaはコンパイルしたり、jarで固めるときにその辺をよろしくやっているのだと、こういう時に気づかされます。
比較は罠が多い
===
を使った場合は、型の一致も含めての比較になるのですが、==
のときは、そうではないので、それでバグってしまうのがよくあるようです。
2a問題
超がつくほど有名らしいです。
$a = '2a';
$b = 2;
print ($a == $b);
// => true
javaでIDEを使っていたら、比較しようとした時点で「型がちゃうで」と怒られるので、まずありえないです。
0e問題
md5のハッシュ値の比較で有名のようです。
- http://stackoverflow.com/questions/22140204/why-md5240610708-is-equal-to-md5qnkcdzo
- http://peccu.hatenablog.com/entry/2015/05/23/000000
- https://twitter.com/sc00bzt/status/440759501973495808
$a = '0e678342453'
$b = '0e123435465'
print ($a == $b);
// => true
言ってる意味がわからない...
何が起きているかというと、eがあるせいで、指数表記と解釈されるようです。
0^673 = 0 = 0^123
ということで、両方とも0になるから、ゆるい比較だと同じになってしまうと...