パーフェクトPHPの「Part2 PHPの言語仕様」が楽しかった

パーフェクトPHPを読んでる。好きな感じ。やんくさん教えてくれてありがとう。

books.rakuten.co.jp

2010年12月に初版だからPHP5.3の頃なのかな。読み終わったあとは、PHPのその後の変更を追いかけとこう。

## Part2 PHPの言語仕様

とりあえず、今日までで「Part2 PHPの言語仕様」を読んだのでメモ。ポイントは

  • 普段はJavaエンジニアなのでJavaとの違いで把握
  • 隅っこの機能は興味なくて普通に使う機能だけでいい
  • IntelliJが教えてくれるだろうことはあんまり気にしない
  • フレームワークの動きを把握したい気持ちもあるので、これは使われてそうかもーってのは名前を覚えておきたい

## 2.2 変数

可変変数面白いな。アプリケーションのコードではあんまり出会いたくない気はするけど。

php > $var = 111;
php > $var_name = 'var';
php > echo $$var_name;
111
php > 

んで

globalキーワードとか、$GLOBALSにはあんまり関わらずにすごせたら嬉しいな。

## 2.3 定数

define関数とconstキーワードがあるのか。

php > define('SAMPLE', 'foobar');
php > echo SAMPLE;
foobar
php > const SAMPLE2 = 'barfoo';
php > echo SAMPLE2;
barfoo
  • 昔からのやつはdefineで定義してあって
  • 今だとネームスペース使いつつconstキーワード

なのかな。

文字列から定数を取得するにはconstants()が使えるって書いてるからやってみたら

php > $myconst = 'SAMPLE2';
php > echo constants($myconst);
PHP Warning:  Uncaught Error: Call to undefined function constants() in php shell code:1
Stack trace:
#0 {main}
  thrown in php shell code on line 1

Warning: Uncaught Error: Call to undefined function constants() in php shell code:1
Stack trace:
#0 {main}
  thrown in php shell code on line 1

php > echo constant($myconst);
barfoo

constant()やないか。最後のsいらん。ちゃんと手を動かしてるかを試されてるw

PHP: constant - Manual

それから

  • 定義済み定数と
  • マジック定数がある

定義済み定数はget_defined_constants()で確認できる。マジック定数はログ出すときに便利そう。

## 2.4 エラー

元々はエラーしかなくて、後から例外が追加されたんやね。

ということは

  • 昔からあるような関数はエラーを使ってて
  • 最近のフレームワークとかアプリケーションは例外を使ってるのかな

php.iniで

  • どのエラーをレポートするか
  • エラーを画面に表示するか
  • エラーをログに出力するか、そのログファイルのパス

を指定できる。本番では画面には出さずにログにだけ出すんよ。って感じだな。

## 3.1.2 整数

へー。整数はlongとかなくてintだけなのか。で、最大値に1足すとfloatになるの面白い。

php > echo PHP_VERSION;
7.2.9
php > echo PHP_INT_MAX;
9223372036854775807
php > var_dump(PHP_INT_MAX);
php shell code:1:
int(9223372036854775807)
php > var_dump(PHP_INT_MAX + 1);
php shell code:1:
double(9.2233720368548E+18)

## 3.1.3 浮動小数

こっちも、floatとdoubleとかなくて、floatだけ。だけど、実際にはdouble。か。

## 3.1.4 文字列

変数名の区切りが必要なときは括弧でくくる。

php > $age = 14;
php > echo "$ageyears old.";
 old.
php > echo "${age}years old.";
14years old.

そういえばこの前読んだ本は内側にダラーマークがあったなーと思って叩いてみたら動いた。どっちでもいいのか。

php > echo "{$age}years old.";
14years old.

外側にダラーマークがある方が好きだな。

2018-09-17 追記 Toyさんありがとうございます!

## 3.1.5 論理型

全体的にPHPのキャストには気をつけた方が良い雰囲気ある。

## 3.1.9 null

  • 変数が未定義
  • 変数が定義されてるけどnullが入ってる

の状態があるのかー。むむー。最初のうちは混乱しそう。

## 3.2 演算子

  • 文字列の連結はドット
  • 論理演算子は短絡評価される
  • 比較演算子===!==は安心。けどそれ以外はキャスト考慮つらそう。それとswitchも気をつけておいた方が良いのかな
  • Groovyでいうところのエルビス演算子がある
  • 演算子の優先順位に注意。テストを書くのと、括弧を書くのが良さそう
  • エラー制御演算子は自分では使わんやろな。どっかで使ってるのは見かけてしまうのかも
  • 実行演算子はあんまり見たくないなー
php > echo `ps`;
  PID TTY          TIME CMD
    1 pts/0    00:00:00 php
   20 pts/0    00:00:00 sh
   21 pts/0    00:00:00 ps

## 3.3 配列

  • 添字配列と連想配列のどっちも「配列」なのかー。で、順序が保証されてる
  • 複数の型が入り混じるような配列も作れるのか・・・やらんで欲しいな
  • キーを持たない要素と、キーを持つ要素を混ぜて定義することも可能です・・・か。やらんで欲しいな
  • 多次元配列も、あんまり使わない方が好きだな
  • 配列の演算か。結合の演算子は使うもんなのかなぁ?
php > $a = array(1,2,3);
php > $b = array(4,5,6);
php > $c = $a + $b;
php > $d = array_merge($a, $b);
php > print_r($a);
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
)
php > print_r($b);
Array
(
    [0] => 4
    [1] => 5
    [2] => 6
)
php > print_r($c);
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
)
php > print_r($d);
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
    [4] => 5
    [5] => 6
)

ほほー。そういう動作かー。・・・使うときは雰囲気でやらずに、ちゃんとドキュメント読んだり細かくユニットテスト書いたりしようと思った。

## 4.1 制御構造

  • elseifはelseとifが繋がってる
  • コロンとendxxxでブロックを表現することもできる。のは見かけるとしてもテンプレートくらいなのかな
  • require/require_onceとinclude/include_onceがある。でもCakePHPが良い感じにやってくれてそう
  • gotoはできれば会いたくない

## 4.2 関数

  • 引数にデフォルト値を与えることができる。定数値のみ。デフォルト値をもたない引数より後に定義する
  • タイプヒンティングある。特定のクラスか配列に限定可能
  • 可変関数もあるのかー。面白い
php > $var = 'sss';
php > echo $var;
sss
php > function sss() 
php > {
php { echo 'sss!!!';
php { }
php > $var();
sss!!!
  • call_user_func()call_user_func_array()は可変関数より高度な関数呼び出しができる
  • コールバック関数は文字列で渡すのか。へー。メソッド参照みたいなのはないのかな?
  • 参照による引数と返り値・・・。ライブラリーとかでは使うかもだけど、アプリケーションではたぶん使わないだろうな
  • 無名関数は使うと思う
  • クロージャ。んー。なんか色々広がりそうだけど、僕にはムズいな。でてきたら勉強しよっと
php > $my_pow = function($times) {
php { return function($v) use (&$times) { return pow($v, $times); };
php { };
php > $cube = $my_pow(3);
php > echo $cube(2);
8
  • get_defined_functions()で定義済みの関数が一覧できる。自分で定義したやつも含めて
php > print_r(get_defined_functions());                                                                                                                                                                
Array                                                                                                                                                                                                  
(                                                                                                                                                                                                      
    [internal] => Array                                                                                                                                                                                
        (                                                                                                                                                                                              
            [0] => zend_version                                                                                                                                                                        
            [1] => func_num_args                                                                                                                                                                       
            [2] => func_get_arg                                                                                                                                                                        
            [3] => func_get_args  

            (中略...)

            [1400] => cli_set_process_title
            [1401] => cli_get_process_title
        )

    [user] => Array
        (
            [0] => bar
            [1] => bar2
            [2] => bar3
            [3] => sss
        )

)
php >

## 5.1 クラス

  • ネームスペースがなかった時代は、モジュール名などをアンダースコア区切りで前につけてた
  • メソッドの呼び出しはアロー演算子
  • インスタンスを複製したい場合はcloneキーワードを使用する。んー。でもこれ、どこまで複製されるんか気になるな。使うときはちゃんと見とくか
$suzuki = clone $yamada;
  • クラス定義時に宣言していないプロパティへの読み書きも可能。へー
  • $thisはプロパティやメソッドにアクセスするときには常に使うっぽい。Javaと違うとこだな
  • staticある。メソッドも、プロパティも
  • finalはメソッドだけなんかな。プロパティの方には書いてないや
  • selfはstatic用の$thisっぽいな
  • コンストラクター__construct。古いやつだとクラス名と同じ名前がコンストラクターになってるみたい
  • デストラクターもあるけど、そっちは使わんやろな
  • 継承ある。多重継承はなし
  • 抽象クラスある

## 5.2 インターフェイス

## 5.3 クラスとオブジェクトの機能と特徴

  • マジックメソッド
    • オブジェクトに対する特定の操作に対するフック
    • アクセス不能なプロパティやメソッドが参照されたときの動きをオーバーロードすることが可能
    • CakePHPとかのフレームワークではいっぱい使われてそうだな
  • 遅延静的束縛
    • 名前がなんか必殺技みたいでかっこいい
    • 便利だけど使われてたらちょっと混乱しそうだな。僕が
  • オートロード

## 5.4 名前空間

  • バックスラッシュ区切り
  • 名前空間を定義したら、グローバルな関数やクラスは戦闘にバックスラッシュをつける(例:\Exception)
  • クラス、関数、constで定義した定数、が影響を受ける
  • 変数、defineで定義した定数、には適用されない
  • 1つのファイルに複数の名前空間を定義する。・・・んー。僕はしないと思う
  • インポートはuseで。名前空間まででも、クラス名まででもOK
  • asを使うと別名をつけられる

## 5.5 例外

  • Javaに似てる。Exceptionをthrowしてtry catchで捕まえる
  • フレームワークがエラーハンドラーでErrorExceptionを投げるようにしてないか気をつけて見とこうかな

## 5.6 参照

  • 参照は便利だけどアプリケーションを作るときにはあんまり使わないだろうなー
  • 循環参照をGCする機能はPHP5.3から入ったのか。それまでは大変だっただろうなー
  • コピーオンライトの動きはPHP7で変わったんだっけ

## メモ

  • 配列のマージをするときはちゃんと動作を確認する
  • クロージャ使うときは勉強する
  • clone使うときはちゃんと調べる

## 面白かったー!!

次は「Part 3 実践Webアプリケーション」だな。