それが僕には楽しかったんです。

僕と MySQL と時々 MariaDB

【PHPのお話】PSRって知ってますか?

はじめに

どうも、最近ヴァイオレット・エヴァーガーデンの5話にメンタルブレイクされたけんつです。

最近、さらなるスキルアップを目指してサーバサイドで別の経験を積もうとしている。
それでGoとか調べていると、PHPが盛大にディスられていて悲しい気持ちになっている。

確かにPHPはバグとかを生み出しやすい感じは自分で書いていても思うが、そういう記事ほどPSRについて触れていない。
なので、こういう便利なものが標準であるんだよということを今回は書いていきたい。

PSRとは

PSRとは、PHP Standards Recommendations の事で PHP-FIG(PHP Framework Interop Group = PHPフレームワーク相互運用性グループ)が策定しているPHPコーディング規約のことを指す。
The PHP League とか、PHPで使えるOSSをリリースしているところではPSRを厳守する様に書かれていて、これにはいくつかの種類がある。

現状で承認されているPSRは以下の通り

  • PSR-1 Basic Coding Standard(基本的なコーディング標準
  • PSR-2 Coding Style Guide(コーディングスタイルガイド)
  • PSR-3 Logger Interface(ロガーインタフェース)
  • PSR-4 Autoloader(オートローダー)
  • PSR-6 Caching Interface(キャッシングインターフェイス
  • PSR-7 HTTP Message Interface(HTTPメッセージインターフェイス
  • PSR-11 Container Interface(コンテナインタフェース)
  • PSR-13 Hypermedia Links(ハイパーメディアリンク)
  • PSR-15 HTTP Handlers(HTTPハンドラ)
  • PSR-16 Simple Cache(シンプル・キャッシュ)
  • PSR-17 HTTP Factories(HTTPファクトリー)


これらをざっくりと、ところどころ重要なものはある程度詳細に書いていく。

PSR-1 Basic Coding Standard

自分はあまり意識することが少ないが PSR-1 は最低限準拠することが求められるコーディング規約を示している。
といっても、本当に基本的なことなので次にくる PSR-2 を満たす過程で自動的に満たしている事が多い。

詳しいことは以下のドキュメントを参照して欲しい。

www.php-fig.org

PSR-2 Coding Style Guide

これはPHPで何かOSSを書くときや、その開発に参入するときや業務で使うときなど
ありとあらゆる場合で絶対といってもいいぐらいに使う最高に重要なコーディングおよびコーディングスタイル規約。

公式DocにあるOverviewを一部、紹介すると

  • 一行は80文字以下が望ましい
  • namespace のあとには空行をいれる
  • クラスを宣言している中括弧はclass キーワードを含む行におく必要がある

などなど、結構色々ある。

公式DocにあるPSR-2を満たしたコーディングを以下に引用する。

<?php
namespace Vendor\Package;

use FooInterface;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class Foo extends Bar implements FooInterface
{
    public function sampleMethod($a, $b = null)
    {
        if ($a === $b) {
            bar();
        } elseif ($a > $b) {
            $foo->bar($arg1);
        } else {
            BazClass::bar($arg2, $arg3);
        }
    }

    final public static function bar()
    {
        // method body
    }
}

ただ、こんなこと毎回意識していられないので自動でfixしてくれるツールをいつも使っている。

github.com

基本的にPHPを用いた開発ではcomposerを使うので、requireしたあとはコミットする前に

$ ./vendor/bin/php-cs-fixer fix . --verbose

を走らせる。


これは、多くの PHP 製の OSS で満たされている。

以下が公式Doc

www.php-fig.org

PSR-3 Logger Interface

これも普段あまり意識することがない。
なぜなら、大抵error_log関数にまかせてしまうからだ。

PSR-3 はロギングに関する規約となっている。

これを満たすのはOSSではあまり見たことないので詳しいことは割愛。

以下が公式Doc
www.php-fig.org

PSR-4 Autoloader

これは、最高に重要な規約の一つでファイルパスからクラスをオートロードするための規約。
PSR-0っていう削除予定の規約もあるが、こっちは現役バリバリで使える。

むしろ、これを満たさないと本当にuse を使うのがしんどかったり
composerを使っている場合なら、そもそもオートロードされないとかっていう最高にヤバい問題が起き始める。

  • 完全修飾クラス名は、「ベンダーの名前空間」として知られているトップレベルの名前空間名を持っている必要がある
  • 完全修飾クラス名は、1つ以上のサブ名前空間名を持つことがある
  • 完全修飾クラス名は終端クラス名を持つ必要がある
  • アンダースコアは、完全修飾クラス名のいずれの部分にも特別な意味を持たない。英字は小文字と大文字の任意の組み合わせで構わない。
  • すべてのクラス名は大文字と小文字を区別して参照する必要がある。
\<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>


例を以下にしめす。

Abraham\TwitterOAuth\TwitterOAuth;

vendor name\(sub namespace)\class name となっているものをよくみる。

composerの設定を書くときもオートロードの設定はこれがベースになっているから
知らないとオートロードではまりがちなポイントが出来上がる。

公式Docは以下の通り
www.php-fig.org

PSR-6 Caching Interface

割と基本的な機能が完成された場合はまず意識することがなくライブラリで自動的に対処されている場合があるのでここもさくっと書く。

PSR-6はキャッシュに関する規約がまとまっている。
キャッシュを扱う際にこれだけは最低限用意して欲しいというメソッドが固まった interface を指す。

公式Docは以下

www.php-fig.org

PSR-7 HTTP Message Interface


これは、色々なプロダクトを触るのに最高に重要なHTTPのリクエスト、レスポンスに関する規約。
HTTPリクエスト、レスポンスを扱う上で絶対にこれだけは用意してくれっていう関数群がinterfaceとなっている。

これは、Laravelでも標準のリクエスト、レスポンスクラスをPSR-7のInterfaceに置き換えることが出来たりするぐらいWebフレームワークでは対応していることが多い。

あと、HTTPが絡んだOSSをテストする際にこれらのInterfaceをモックする場合もある。

書いていることはそんな大した量じゃないが最高に重要な役割を持つ規約の一つである。


これがベースになっていることが多い

github.com


公式Docは以下
www.php-fig.org

PSR-11 Container Interface

これは、あまり注目されていないけど実は重要でOSSではよく使われている。
というのもPSR-11はDIコンテナに関する規約がまとまっているからだ。

これを満たしている、利用しているPHP製のOSSは意外と多い。

うだうだ語るよりも以下の記事を見れば大体わかる。

rabbitfoot141.hatenablog.com

ルーティングやバッチ系のライブラリで使われているのをよく見る。

公式Docは以下
www.php-fig.org



PSR-13、普段はめったに考えることないけどハイパーメディアリンクに関する規約。
これもハイパーメディアリンクを扱う上で必要な関数群を定義しているがこのあたりのライブラリを見たり実装をすることがないから本当にわからない

なので公式Docだけ晒しておく
www.php-fig.org

PSR-15 HTTP Handlers


これは、PSR-7と関連して満たされる場合が多いためさくっとまとめる。
PSR-15はHTTPハンドラーの規約になっている。

HTTPハンドラーと言っても、リクエストハンドラとミドルウェアに関するコンポーネントが含まれている。

が、これを自前で実装することはなくLaravelなどのFWで最初から組み込まれていることが多い。

それなりに重要なはずなんだけど、よく見えないところに隠されていることが多いため
意識しなくても使っている場合がある

以下が公式Doc
www.php-fig.org

PSR-16 Simple Cache

これはキャッシュに関する規約になっている。
キャッシュ系のライブラリを作ることは少ないと思うが使う際には、この規約にあるインターフェースを利用することになる。

中にはメソッドからキャッシュとして保持する必要のあるデータ型などが書いてある。

以下が公式Doc
www.php-fig.org

PSR-17 HTTP Factories

PSR-17はHTTPファクトリ、つまりPSR-7準拠のHTTPオブジェクトの作成方法についての規約となる。
これができるまでは、HTTPメッセージに関しての規約(PSR-7)しかなく、そのオブジェクトについてはバラバラだったため
それらの規格を統一するためにある。
これも同様にインターフェースなどが定められている。

こういった部分はよくFWの内部に埋もれがちになってしまっている。

以下が公式Doc
www.php-fig.org

おわりに


途中、FWに隠れがちで実例を示すのが難しい部分はかなり説明を端折ってきたが
特に有名なOSSやプロダクトの裏ではこのように制定された規約の上に成り立っていることが多く
これらを満たすことで、快適に開発することができる。