PHP

phpでプログラミングをする上での(My)ベストプラクティス

# はじめに
とりあえず現状自分がやってて感じたPHPでのベストプラクティス集です。
あくまで現状感じているもので定石というわけではないので随時変更する可能性があります。
PHPに限らないものも含むけれど、数ある言語そんな使い込んでるわけでもないし◯◯の言語ではこういうケースでうんぬんいわれてもアレなのでPHP用としてまとめています。
# 大前提 phpstormなどのIDEもしくはそれに準ずるものを使う(特殊なフレームワークつかっていてIDE対応していないとか使えない理由がなければ)
適切にカスタマイズしたものを使うならともかく、テキストエディタなどでやるのは控える。
自分でカスタマイズする場合も、IDEを基準とする。
具体的にはメソッドの定義元や使用箇所を確認したり、private関数のクラス外からの利用など諸々簡単なエラーチェックはエディタでできていないとつらい。
-> 「IDEを使ってない人もいることを考えろ!」とかいうくらいなら自分がカスタマイズで解決する。できないなら素直にIDE使う。
# 1クラス1ファイル
1つのファイルに複数のクラス定義を書かない
また、クラス定義のファイルにはクラスのことしかかかない(読み込んだだけで実行するとかは絶対にしない)
# エスケープは出入り口で処理する
PHP->DB であればDBに保存する際にDB用のエスケープのみをかける
DB内にHTML用のエスケープをした状態で保存したりは絶対にしない(やると後で多重エスケープ他諸々で地獄を見る)
HTMLのエスケープはテンプレートでもよい。が、基本的にはプログラマーとデザイナーの分業のためテンプレート化しているはずなのでエスケープ済みの変数をテンプレートに渡す方がよい(デザイナーがユーザ入力に基づく値なのかを全て正確に判断するのは困難)
ただし、混ざると多重エスケープやエスケープ漏れの原因となるので統一されていることが優先
既にテンプレートでエスケープするようになっているなら異端なことはしない
# global変数は使わない
global変数はカオスの元
defineもglobal汚染の一種で処理コストも重いので使わない
代わりにclassのconstで行い、組み合わせなどconstで定義できないものはget~メソッドを作る
# エラー制御演算子(@)は書かない
全員が完全に理解しているなら書いてもいいっちゃいいけど本来使わずにエラー制御演算子は使わずに制御できるはず
必要なエラーが無視されるという事態が発生したり対策でコーディング規約をごちゃごちゃするくらいなら最初からエラー制御演算子を利用禁止する方がいい
# $_POST, $_GETなどについて
基本的に$_POST, $_GETは使わず、filter_input()メソッドを使う( $_POST['hoge'] なら代わりに filter_input(INPUT_POST, "hoge") )
それもコントローラで使うのみでクラス内では使わない(クラスやメソッドには変数を渡す)
具体的には、実行するファイルに記載してクラス内には$_*やfilter_inputを書かない
ただし、検証・整形のためのクラスであれば$_*系のデータをまるっと渡す前提の設計はあり
# DOC
・クラスにはPHPDOCを必ず書く
何のクラスか、の説明をしっかりと記載し、クラス名と説明と処理がかけ離れないようにする
・メソッドも基本的にはDOCを書くが、getterなどのようにメソッド名ぱっと見で処理がわかるものであればその限りではない
・非推奨になったものは @deprecated を記載してなぜ使わないのか、使わずにどうすればいいのかを書く 適宜@see も使う
# 継承について
・基本は「迷うなら継承しない」
-> "継承する方がベターなケース"で継承しなくてもコスト増加は少ないが、"継承すべきでないもの"を継承したときのコスト増加は大きい
あるメソッドがあったとして、継承していなければそのクラスのそのメソッドの利用箇所だけチェックすればよいが、基底クラスを変更すると継承先での同メソッド利用箇所も全て検証が必要。継承の継承の継承の...となるとどの段階でオーバーライドしているかも確認しなければいけないので更に大変
また、継承するということは基本的に同様の動作を期待しているはずなので
・publicな新メソッドはできるだけいれたくない(禁止ではないが)
-> 特に、簡単に似た名前の別メソッドをつくったりしない
・オーバーライド時は継承元と同じ仕様
コンストラクタもメソッドも継承するからには受け取る引数や返り値の数や型はすべてあわせる
(false返したりnull返したりバラバラだとつらい)
-> それができないなら継承ではなくクラス内でnewして保持する方がベター
できればインターフェースがあるものだけ継承などルール決めたほうが後々楽(らしい)
# インターフェースについて
基本的には外部に何かを提供する(お互いに触れない、触らない範囲がある)ときに使う
-> これに沿って実装してね
とかなんとか書いたが正直使いどころがわからない
返り値の型を強制できない時点で使いにくい...それならabstractクラスで、ってなる DOCで書くしか...
多重継承(実装)できる利点はあるがそれするときってクラス分けた方がいいときなきもする
多重実装してまで一つのクラスでやりたいとき...?
ファクトリーメソッドパターンと相性がよさそうなことは書いてた(というかそれ以外で使いみちない?)
それ以外はabstractなどのクラスでよさげ
# 参照渡しをしない
可読性とかメモリとか色々理由あるけどPHPでは参照渡しをしないほうがいい
理由のうちの一つ(参考): http://tanakahisateru.hatenablog.jp/entry/2013/12/12/012728
# その他注意点/小技
・in_array()は第三引数trueを指定する
https://qiita.com/tadsan/items/2a4c3e6b0b74a408c038 "apple"==0 true がひどい
http://php.net/manual/ja/language.types.string.php#language.types.string.conversion <- 要はこれが曲者
・ファイルの最後を?>で閉じない
その後にスペースなどあれば出力され、headerが動作しなかったりする
どうしても閉じるならその前にexit;をおく
・クラス内でリダイレクトしない。
エンドポイントとなるphp(コントローラ)以外で極力しない。メソッド実行して戻り値が帰ってこず、勝手にリダイレクトされるとデバッグしづらい。
・コールバックは使わない
phpでコールバックを使う方がメリットのあるケースってない気がする
IDEがメソッド利用箇所を探せなくなったり地味なデメリットがありバグがでやすくなる
・stateなど、数がはいるフラグをつくるときは0をいれない
上記in_arrayなど、phpは0と簡易比較すると面倒なことになる処理が多いので。
・テンプレートに数字をかかない
そうすることでプログラムの変更があってもテンプレートの編集漏れがなくなる
数字ということはバージョンアップやロジック変更で変更になる可能性が高い箇所
正確には"変更の可能性がある部分をテンプレートに直書きしない"だがひとまずは数字を書かないと考えておく方が漏れにくい
テンプレートに数字を書かざるをえないケースもないとは言わないが基本は定数化して変数としてテンプレートに渡す
・仮のものはtodoなどつけてコメントかいておく
・テーブルのカラム名と値を定数化
カラム名はいらないっちゃいらないけれど、これをしてると"テーブルクラス::定数"という記述や細かいコメントつけたりができるので「あぁこのテーブルのこのカラム名とキーあわせてるのか」とかがわかりやすくなる
最初から用意する必要はないのでテーブルのカラムに紐づく値がでたときに定数追加する程度でいい
カラム名はconst COLUMN_HOGEHOGE
そのカラムの取り得る値はconst HOGEHOGE_DEFAULT = 1など
# おわりに
phpはなるべくエラーを出さないで処理を通すようになっている
そのため簡単に作るにはいいがエラー処理などをきっちりやるにはかえって不便なところもある
しっかりとしたものを作るにはきちんと特性を把握して対応することが必要となってくる

-PHP

Copyright© F27P , 2021 All Rights Reserved Powered by AFFINGER5.