reserved.モダンなPHPの開発の学び方2016-05-24簡単なPHPのお仕事を頂きまして、ソースコードを見てみると、10年前に見たような中々レガシーな感じ。いえ、久々のPHPの仕事で、自分の知識もCakePHP1.Xを使用した当時で止まっているので、知識のアップデートがてら、ソースコードをリファクタリングすることにしました。その際に集めた情報ややったことなどを、列挙していきます。Wayまずは、みんなどういう開発をしてるんだろうなぁと調べる時のキーワードですが、こういう時は「最新」とかで調べても上手くヒットしません。「モダン」は割といいキーワードだと思います。PHP」とかで検索したところをざっと眺めます。◯◯」で調べると、◯◯関連の情報をまとめたドキュメントなどがあるのでそれも参考にします。Wayここを見とけば、一通りはOKなのではないでしょうか。このなかで、適用できそうなものをどんどん採用していくことにします。テンポラリbin/binには開発に便利なシェルスクリプトなどを置いておきます。どんなときでも使えそうなものはエイリアスを.bashrcに書いとくといいかも。今回はビルトインウェブサーバの起動スクリプトを書いておきます。etc/設定ファイルなどを入れておきます。今回の場合はphp.iniなどがあるでしょう。開発用と本番用などもまとめて入れておきます。src/今回作るPHPを入れておきます。できれば、ライブラリとしてなるべく汎用的にしていき独立させていきたいところですが、今回はある程度のところで止めておきます。tests/リファクタリングするには、まずテストを書きます。今回はユニットテストを書く意味はあまりなさそうなので、エンドツーエンドテストだけ書いておきます。tmp/作りかけとかいらなくなったものとかはtmp/にぶち込んでおきます。.gitignoreにはtmp/とだけ書いておけば、tmp/以下はリポジトリにはコミットされません。statusなどでも余計なファイルが表示されないようにします。README.mdプロジェクトの詳細や、インストール等の条件、サーバの詳細などはここに記載しておきます。githubなりbitbucketなりでトップページに表示される内容になるので、関係者に知らせたい項目や、コーディング規約等を書いておいたりします。ローカルサーバ以前はXAMPPとかローカルのApacheなどがありました。RailsでPowを使ってた場合などに併用に苦労した覚えがありますが、現在はビルトインウェブサーバがあるようなので、それを使用することにします。以下のようなファイルをワーキングディレクトリに配置して、./bin/phpdとかでサーバを起動するようにします。$script_dir/../public_html開発サーバの設定はetc/php.ini-developmentに配置しておきます。catchmailメールサーバ今回はメールを飛ばすプログラムなので、ダミーのSMTPサーバを用意しておきます。メールはテスト中に実際に飛んでいってしまうとトンデモナイことになることが多いので注意が必要です。Railsではletter_openerやhttp://mailtrap.io/などで対応していましたが、今回はローカルのsendmail(postfix)を使う代わりに、MailCatcherを使うことで対応します。php.ini-developmentの最下行に加えた一文でプログラムが送信したメールはMailCatcherが拾ってWebで確認できるようなります。以下のようなファイルをbin/に置いておくと、しばらく立って忘れたとき、思い出すきっかけになるので簡単なものでも作っておいたりします。http://localhost:1080/Composerライブラリの依存性管理は、最近はPEARは使わず、Composerというもので、venderディレクトリ以下にインストールするのが一般的だそうで、RubyでいうところのBundlerのようなもののようです。今回はPHPUnitとSeleniumを簡単に使えるFacebookのライブラリphp-webdriverを使って、E2Eのテストだけ書いておくことに。ここらへんは長くなりそうなので別途要望があれば書きます。元のファイルをみたところ、クラスの文字もないようなベタ書きのPHPスクリプトでした。これをどんどんクラス化していくなかで、今までの感じだと、require_onceを列挙してクラスを読み込むことになってしまう。現在は、命名規則とクラスローダーを使うことで煩雑な作業を省略することができる。クラスローダーをダウンロードしてきて、src/に配置すします。./public_html/phptest.phpというファイルを用意して、以下のように記述し、SplClassLoader.phpを読み込みます。\Test\Entry();$entry->run();./src/Test/Entry.phpを用意して、以下のように記述する。Worldと表示されたら成功。問題があれば、ウェブサーバのログを確認して修正する。Recommendations)というのに集約されつつあるようです。郷に入らば郷に従えなので、これに従って行きましょう。大体のポイントを抑えれば、大分綺麗になるようです。正確な記述はPSRを見てもらい、ここでは、以下のような感じで作っていきます。namespaceを作る。ベンダー名\パッケージ名\クラス名などがよさそう。ディレクトリ名はnamespaceと一致させる。ファイル名はクラス名と一致させる。ファイルはBOMなしUTF-8で、改行コードはLF。PHPのみのファイルは<?phpタグではじめて、閉じタグは書かない(閉じタグ後のスペースや改行が問題になることが多かった)。クラスは大文字で始める。‘1.0’のような形で記述する。関数、メソッドはキャメルケース。クラスとメソッドの{は宣言の次の先頭に。変数のない文字列はシングルクォーテーションでくくる。変数のある文字列はダブルクォーテーションでくくる。一行が80-120行以内ぐらいでおさまるように。if文は1行で書かない。protected)をちゃんとかく。(condition){あとはphp-cs-fixerやPHP_CodeSnifferというようなコーディングスタイルチェックツールに自動で訂正してもらうのに従うのが楽そう。今回は最終的に、php-cs-fixerを使ってます。コードの整形まずは、インデント等はツールにまかせて整形する。意味のわからない変数や省略された変数を変更する。$subject間違ってそうな変数などを変更する。$val途中で変更されない変数は定数に置き換える。booleanを0/1で判断しているものはtrue/falseに置き換える。true複雑すぎたり意味の分かりにくいconditionをメソッドや定数に置き換える。{深いネストはガード節を使用して早めに判断して抜ける。HTMLで記述されてるところを一つのメソッドにまとめる。class='caution'>「電話番号」は入力必須です。class='caution'>「".$key."」は入力必須です。break;...などなど。今回はネストが深すぎたのでガード節で抜けていったら相当シンプルになりました。まとめ3日位で、駆け足で調べてみましたが、さすがはPHPは開発者が多いこともあって情報も多く、最近は大分道が整備されてるように思えます。2016-10-16About東京在住、フリーランスのプログラマーです。プロジェクトの開発全般(ヒアリング、見積、設計から実装)をしています。部分的なお手伝いのご依頼も随時受け付けています。お仕事の依頼は、Twitter、メールもしくはお問い合わせフォームからお願いします。Contactメールアドレス(必須)メッセージ本文(必須)。