PHP
初心者

独習PHPを読んだまとめ1

はじめに

業務では中々できない基礎固めとして、独習PHP3版を読んだので学んだ内容を謎の上から目線で分類してメモしておきます。

長くなってしまったので分割します。

使えそうだなと思った

  • ヒアドキュメント p.58
$msg = <<<EOD
五月雨を
集めて早し
最上川
EOD;

デリミタで囲んだ部分をまるっと文字列リテラルと認識してくれる。
改行を含めても大丈夫だし、変数展開もやってくれるが終端文字の前に空白やタブ文字が入っているとエラーが出たりして、結局インデントが崩れて見づらくなったりもする。

デリミタをシングルクオートで囲むと変数展開されなくなり、NowDoc構文とか呼ばれたりするらしい。

配列のカンマ p.62

$hoge = [
    'a',
    'b',
    'c',
];

配列の要素が複数行になるときは最後の要素にもカンマをつけなさい。忘れるから。ということでした。でもjsonでこれをやると怒られる…

任意精度数学関数 p.82

print floor((0.1 + 0.7) * 10); //7

$add = bcadd(0.1, 0.7, 1);
$mul = bcmul($add, 10, 1);
print floor($mul); //8

いわゆる初心者殺しの浮動小数点数を何とかするやつ。前2つは引数にStringを取るんだね。なんでintで書いてあるんだこの本。

厳密な等価演算子 p.89

PHPの==はガバガバだから基本的にこっちを使いましょうね。ここが詳しかった。
===はガバをなくせる上早いので頼りになる。

条件演算子 p.93

//左辺がtrueならそのまま左辺を返し、falseなら右辺を返す
$hoge = '';
print $hoge ?: '空です'; //空です

// isset($fuga) ? $fuga : 'ノーコメント'; と同じ
pritn $fuga ?? 'ノーコメント';  //ノーコメント

特にnull合体演算子(下の方)は配列参照エラーを防ぐためのisset地獄から抜け出すのに使えそうなのがいい。PHP7からなので案件によっては使えなくて糠喜びさせられた。

論理演算子 p.96

$x = true;
$y = false;
$x xor $y //true

左右のいずれかがtrueかつ、双方ともtrueでないときにtrue
ifのネストが減らせるかも

mb_strpos()

mb_strpos自体は特定の文字位置を検索するだけのメソッドなんだけど、ある単語が含まれているか調べたい時に、==を使ってしまうと、見つからなかった時のfalseと文頭に見つかった時の0との区別が付かなくなるので気をつけましょう

配列操作関数のうち、引数に必ず変数を指定しなければならないもの p.167

戻り値に処理結果のarrayを返すもの(array_mergeなど)、参照渡しされた配列をいじるもの(arsort, array_push)などがあり、大体戻り値を受け取り忘れたり、引数に直接配列を書いちゃったりして怒られるので気をつけましょう

関係あるようでないですが、配列内の文字コードを扱った時にhttp_build_queryとmb_convert_variablesの違いに苦しめられたことがあります。

引数、戻り値の型宣言 p.218

function getTriangleArea(float $base, float $height): float {
    return $base * $height / 2;
}

今業務で扱っているのがPHP5系なせいもあって、あまり使えていないけれど7をやるときには使いたい機能。ちなみに5ではタイプヒンディングと呼ばれ、戻り値では型宣言が使用できず、引数で使用できるのは配列とオブジェクトだけという仕様。

仮引数のデフォルト値 p.231

function getTriangleArea(float $base = 5, float $height) {
    return $base * $height /2;
}//エラー

仮引数にデフォルト値を指定できるのは、それより後方に仮引数がない場合だけ。
引数の数が正しく判断できなくなるので、当たり前といえば当たり前なのだけれども、array $hoge = []とかわけも分からず書いてた時に意識してなくてエラーを起こしたことがあったので。

可変長引数 p.235

function sum(float ...$args): float {
    $result = 0;
    foreach($args as $arg) {
        $result += $arg;
    }
    return $result;
}
print sum(7, 3, 10); //20
print sum(11, -5, 4, 88); //90

こういうの5だったらそもそもの引数を配列とかにしちゃうんだけど、型宣言ができるようになるとまた違ってくるのではないかと思って。ちなみに5ではfunc_get_args()を使い、仮引数は書かないらしいです。

use命令 p.247

クロージャで親スコープから変数を引き継ぐときに使う

Laravelのメール処理のときにクロージャを使う必要があり、変数の渡し方が分からず困った時があったので。array_filterとかでも使ったりするのではなかろうか。

使いどころがイマイチ…

declare, enddeclare p.48

ここが一番分かりやすかったのだが、要するに関数を登録しておいて、declare内の処理をticks回分行うごとに、登録しておいた関数が呼ばれる、ということのよう。

マジカルインクリメント p.81

$i = 'Z';
print ++$i; //AA
$j = 'T8';
print ++$j; //T9

末尾がアルファベットであれば次の文字へ、数字であれば1足す。それぞれ最後の数字、文字であれば繰り上がる。英数字混在の連番コードとか使いたくないし、マジカルデクリメントみたいなのもない。名前は可愛い。

ビット演算子

ここを読んでください。
DBに格納されてるflagがTINYINTとかで、それをそのまま条件分岐に使いたい〜みたいな時とかに使えそう?

実行演算子 p.101

バッククオート( ` )で囲んだブロックをシェルコマンドとして実行する。
`dir`でdirコマンドを実行したのと同じ。使いどころはありそうだけど、代替手段がありそうだし、まだその場面に遭遇出来てない。

エラー制御演算子 p.102

式の前に@をつけるとその命令で発生したエラーメッセージを抑制する。
僕は最初、bladeの@がこれだと思っていて混乱した覚えがあります。

switch命令でのcontinue命令 p.134

switch命令は挙動の上では条件分岐構文だが、PHPの中では繰り返し構文として扱われるので、continue命令はbreak命令と同じようにswitch文から抜け出すのみとなる。forループとかと使うときに気をつける?

ジェネレータ p.248

function myGen(){
    yield 'あいうえお';
    yield 'かきくけこ';
    yield 'さしすせそ';    
}
foreach(myGen() as $value) {
    print $value . '<br />';
}

yield命令はreturnとよく似ていて、戻り値を返すという点は同じなのだけれども、returnの場合そこで処理が終了するのに対して、yieldは一時停止するという違いがある。

なので上の出力は

あいうえお<br />
かきくけこ<br />
さしすせそ<br />

となる。

使わない方が良さそう

参照による代入

$a = 8;
$b = &$a;
$a = 10;
print $b; //10

単品で使うと間違いの元なんだけど、オブジェクトのコピーは参照による代入がデフォルトだったりするので知っておく必要がある。

比較演算子 p.88

7 <> 7 //false !=と同じ意味
7 <=> 10 //-1 左辺が右辺より小さければ-1,等しければ0,残り1

下のやつは宇宙船演算子というらしい。可愛いけど可愛さだけで分かりにくいからシーソー演算子とかに改名したほうがいい

配列の比較 p.91

  1. 要素数で比較
  2. 要素数が等しい場合、同じキーを持つ要素同士で値の大小を比較し、より大きい(小さい)要素が見つかったところで終了
  3. 1.2の比較がすべて等しい場合両者は等しいとみなされる

うーん、<>はともかく==は使うべきでは無さそうかな…
===は並び順まで見るらしい。

global命令 p.226

$x = 10;
function checkScope(){
    global $x;
    return ++$x;
}
print checkScope(); //11
print $x //11

ローカル変数を強制的にグローバル変数に割り当てる。関数の中からグローバル変数にアクセスしたい時に使うらしい。けど副作用がどうの参照透過性がどうの、みたいな話はよく理解しきれていないなりに、何か災いを引き起こしそうだなという感じはしている。

static命令も同じかな…

間違ってない?

メールアドレス判定の正規表現 p.196

/[a-z0-9\.\-]+@([a-z0-9\-]+\-)+[a-z0-9\-]+/i

というのがメールアドレス判定として練習問題の一部に使われていたのだが、これってどうなんでしょうね…とりあえず僕の環境では判定できなかったし、まぁ色んな所であれやこれや言われている理由がちょっと分かりました。

自信がある人は自前で調べて書けばいいし、filter_var($mailaddress, FILTER_VALIDATE_EMAIL)みたいに書くのもコストが低くていいかなと思います