PHPを使う上で忘れてはいけないこと

初心者を戒めるPHP - Qiitaという記事を読んだので、自分なりにまとめておこうと思う。

PHPDocは必ず書く

他人が容易に応用できるように型を明示的にする。
ヘッダだけを読んでメソッドの仕様が理解でき、またはコードを読む助けになるようなコメントを書こう。

実装に取り掛かる前に、入力(引数)と出力(返り値)について、必ず型を決めておこう。

/**
 * 入力値をFizzBuzz文字列化する
 *
 * @param  int    $num
 * @return string FizzBuzz文字列
 *
 * このメソッドは $num が3の倍数なら"Fizz"、5の倍数なら"Buzz"、7の倍数なら"Nass"、
 * これらの数の公倍数ならば、少ない数から該当した順に連結して返す。
 * どの数の倍数でもなければ、 $num を10進数として文字列化した値を返す。
 *
 *     toFizzBuzzNass(1);  // => "1"
 *     toFizzBuzzNass(3);  // => "Fizz"
 *     toFizzBuzzNass(15); // => "FizzBazz"
 *     toFizzBuzzNass(21); // => "FizzNass"
 *     toFizzBuzzNass(35); // => "BazzNass"
 */
function toFizzBuzzNass($num)
{
    static $fizzbuzz_table = [
        'Fizz' => 3,
        'Buzz' => 5,
        'Nass' => 7,
    ];

    $str = '';
    foreach ($fizzbuzz_table as $s => $n) {
        if ($num % $n === 0) {
            $str .= $s;
        }
    }

    return ($str === '') ? "{$num}" : $str;
}

PHPは「配列または文字列を返す」という事ができる。(PHPDocには@return array|stringと書く)
しかし、そうすると受け取り側でis_array()チェックなどをする必要がある。
面倒なので、型をどちらかに統一するか、必要に応じてメソッドを分割したほうが面倒くさくない。

Composerを導入しよう

PEARのライブラリが必要ならComposerを使ってインストールできる。
zipをダウンロードしてファイうrをinludeするのは面倒。
Composerなら勝手にオートロードしてくれる。

error_reporting(E_ALL)しよう

PHPは未定義変数や配列の存在しないインデックスを参照するとE_NOTICEエラーを出す。
このエラーはバグの温床になる(開発環境では出るようにしておこう)

フレームワークを利用しよう

フレームワークの作法にのっとってコードを書けば、たいていの問題はフレームワークがどうにかしてくれる(セキュリティとか脆弱性とか)

テンプレートとロジックは分けよう

画面を描画する機能とそれ以外を明確に分けよう。
例えば、「データベースの内容をHTMLのtableで表示する」プログラムが書きたい場合は、
「データベースからデータを取り出して配列にする」部分と「配列をHTMLのtableで表示する」部分を分ける。
PHPはてーんプレートエンジンじゃない。
自動エスケープ機能があるTwigとかBladeとかを使うと、PHPより多少は安全になる。

PHPしかファイルに書かない場合は、最後に?>は書かないようにしよう。

安易にキャストはしてはいけない

(int)とかintval()を書いてはいけない。
PHPでは"3"==3がtrueになる。

$a = [];
$b = $a + 1; // この場合はFatal errorになるが、

$b = (int)$a + 1; // これはエラーにならない

上記のようにキャストしたせいで、バグに気付けなくなってしまう場合がある。

リファレンス(参照)はやめておこう

引数のリファレンス私はやめておこう(ちゃんと返り値で返すようにしよう)
foreachのリファレンス、リファレンス代入とかはやめておこう。

<?php

// だめなパターン (リファレンス使用)
$ary = range(1, 5);
foreach ($ary as &$a) {
    $a = $a * 2;
}
var_dump($ary); //=> [2, 4, 6, 8, 10]

// 許されるパターン (リファレンス不使用)
$bry = range(1, 5);
foreach ($bry as $i => $b) {
    $bry[$i] = $b * 2;
}
var_dump($bry); //=> [2, 4, 6, 8, 10]

コードの一番下に$a=100; var_dump($ary);を追加してみよう。  ←多分代入されてる

一見して未使用変数を使っているように見えるので、使わないようにしよう。

継承も安易に使わないようにしよう

クラスの差分によるプログラミングは他人に把握してもらうのが難しい。
interfaceと必要があれば以上を使用することでシンプルに実現できる。

array_map

// array_mapを使ったパターン
$ary = array_map(
    function ($n) { return $n * 2; },
    range(1, 5)
);
var_dump($ary);

// foreachを使ったパターン
$bry = range(1, 5);
foreach ($bry as $i => $b) {
    $bry[$i] = $b * 2;
}
var_dump($bry); //=> [2, 4, 6, 8, 10]

下のコードの方が分かりやすい。

foreachが嫌ならnikic/iterを使って徹底的にやろう。

<?php
use function iter\fn\operator as op;

$ary = iter\toArray(iter\map(op('*', 2), iter\range(1, 5)));

foreachを使っておくのが無難

参考文献

初心者を戒めるPHP - Qiita