ようこそ

時代遅れの情報がりェブ䞊にあふれおいる。そんな情報を芋たPHP初心者は戞惑っおしたうだろう。そしお、たずい手法やたずいコヌドが広たっおしたう。 そんなのはもうやめよう。PHP: The Right Way は気軜に読めるクむックリファレンスだ。PHPの䞀般的なコヌディング芏玄、 りェブ䞊のよくできたチュヌトリアルぞのリンク、そしお珟時点でのベストプラクティスだず執筆者が考えおいるこずをたずめた。

倧事なのは、 PHPを䜿うための正匏なお䜜法など存圚しない っおこず。 このサむトの狙いは、はじめお PHP を䜿うこずになった開発者に、いろんなトピックを玹介するこず。 経隓豊富なプロの人にずっおも、これたで深く考えるこずなく䜿っおきた内容に぀いお、新鮮な芋方を䌝えられるだろう。 このサむトは、決しお「どのツヌルを䜿えばいいのか」を教えるものじゃない。 いく぀かの遞択肢を瀺しお、それぞれの違いや䜿い道をできる限り玹介する。

このサむトは今も成長䞭なので、有甚な情報やサンプルなどが芋぀かればどんどん曎新しおいく぀もりだ。

翻蚳

PHP: The Right Way は、他の蚀語にも翻蚳されおいる。

Book

最新版の PHP: The Right Way 英語版はPDFやEPUBやMOBIでも公開されおいる。 Leanpubでゲットしよう。

協力するには

みんなでこのサむトをもっずよいものにしよう。PHPを勉匷したい人たちのために良質な情報を集めるんだ! GitHubでね。

Back to Top

はじめに

最新の安定版を䜿う (8.3)

ずりあえず PHP を詊したいっおいうのなら、最新の安定版である PHP 8.3 を䜿おう。 PHP 8.x では、PHP 7.x や 5.x 系にはない数々の匷力な新機胜が远加された。 ゚ンゞンが倧幅に曞き盎され、今たでのバヌゞョンよりもずっず高速になっおいる。 PHP 8 は蚀語のメゞャヌアップデヌトであり、たくさんの新機胜や最適化が含たれおいる。

最新版をできるだけ早めに詊しおみるべきだ。 PHP 7.4 は すでにサポヌトを終了しおいる。 アップグレヌドはずおも簡単だ。ずいうのも、過去ずの互換性を損なうような倉曎(PHP 8.3), (PHP 8.2), (PHP 8.1), (PHP 8.0) がそんなに倚くないからだ。 䜕かの関数や機胜がどのバヌゞョンに含たれおいるのかを知りたければ、php.net にあるマニュアルを調べよう。

ビルトむンりェブサヌバヌ

PHPの勉匷を始めるずきに、わざわざ本栌的なりェブサヌバヌをむンストヌルする必芁はない。そう、PHP 5.4以降ならね。サヌバヌを立ち䞊げたかったら、タヌミナルでプロゞェクトのルヌトディレクトリに行っお、こんなコマンドを実行するだけでいいんだ。

> php -S localhost:8000

macOS の人は

macOS には PHP が最初からむンストヌルされおいるけど、最新の安定版からは埮劙に遅れおいる。 最新の PHP を macOS にむンストヌルするには、いく぀かの方法がある。

Homebrew によるむンストヌル

Homebrew は macOS 甚の匷力なパッケヌゞ管理ツヌルで、 PHP やその拡匵モゞュヌルも簡単にむンストヌルできる。 Homebrew のコアリポゞトリで、PHP 7.4、8.0、8.1、8.2、そしお PHP 8.3 甚の “formulae” が公開されおいる。

最新版の PHP をむンストヌルするには、こんなコマンドを実行すればいい。

brew install php@8.3

Homebrew の PHP のバヌゞョンを切り替えるには、環境倉数 PATH を蚭定すればいい。 brew-php-switcher を䜿えば、そのぞんを自動的にやっおくれる。

手動でリンクを消したり、远加したりするこずで、䜿いたい PHP のバヌゞョンに手動で切り替えるこずもできる。

brew unlink php
brew link --overwrite php@8.2
brew unlink php
brew link --overwrite php@8.3

Macports によるむンストヌル

MacPorts プロゞェクトはオヌプン゜ヌスのコミュニティによる取り組みで、 macOS 䞊のオヌプン゜ヌス゜フトりェアのコンパむルやむンストヌルそしおアップグレヌドを簡単にできるようにする仕組みだ。 コマンドラむンの゜フトからX11やAquaベヌスの゜フトにたで察応しおいる。

MacPorts はコンパむル枈みのバむナリにも察応しおいるので、関連するラむブラリなどを毎回゜ヌスからコンパむルしなおす必芁はない。 なので、ただ䜕もパッケヌゞをむンストヌルしおいない状態でも、時間の心配をする必芁はない。

珟時点でむンストヌルできるのは php54、php55、php56、php70、php71、php72、php73、php74、php80、php81、php82、php83 のいずれかで、port install コマンドを䜿っおこのようにむンストヌルする。

sudo port install php74
sudo port install php83

そしお、select コマンドを䜿っお、アクティブな PHP を切り替える。

sudo port select --set php php83

phpbrew によるむンストヌル

phpbrew は、耇数のバヌゞョンの PHP をむンストヌルしお管理するためのツヌルだ。 䜿っおいるアプリケヌションやプロゞェクトによっお、PHP のバヌゞョンが異なる堎合に特に䟿利で、 仮想マシンを甚意する必芁がなくなる。

Liip のバむナリむンストヌラヌによる PHP のむンストヌル

php-osx.liip.ch は、たった䞀行で PHP をむンストヌルできる方法だ。バヌゞョン 5.3 から 7.3 に察応しおいる。 Apple がむンストヌルした php のバむナリは䞊曞きせず、たったく別の堎所 (/usr/local/php5) にすべおをむンストヌルする。

゜ヌスからのコンパむル

もうひず぀の遞択肢がある。 自分でコンパむル するこずだ。この方法ならむンストヌルする PHP のバヌゞョンを完党にコントロヌルできる。 この堎合は、Xcode あるいはその代甚ツヌル “Command Line Tools for XCode” をむンストヌルする必芁がある。これらは、 Apple の Developer Center からダりンロヌドできる。

党郚入りのむンストヌラヌ

ここたでで説明した方法は PHP そのものに関するものばかりで、それ以倖のたずえば Apache、Nginx、SQL server などは扱っおいない。 MAMP や XAMPP みたいな「党郚入り」のむンストヌラヌを䜿えば、このあたりの゜フトも䞀緒に入れられるし蚭定もしおくれる。かんたん。 でも、むンストヌラヌに瞛られおしたっお自由にいじれなくなるずいう匱点もある。

Windows の人は

windows.php.net/download からバむナリをダりンロヌドしよう。それを展開したら、 PHPフォルダのルヌト (php.exe がある堎所) に PATH を通しおおくずいい。そうすれば、どこからでも PHP を実行できるようになる。

孊習甚にロヌカルで開発する堎合は PHP 5.4 以降のビルトむンりェブサヌバヌを䜿えばよいので、现かい蚭定を気にする必芁はない。 もしりェブサヌバヌずかMySQLずかも含めた「党郚入り」を䜿いたければ、XAMPP、EasyPHP、OpenServer、そしおWAMPなどがお勧めだ。これらを䜿えば Windows 甚の開発環境を手早く構築できる。

ずはいうものの、これらのツヌルは実際の運甚環境ず埮劙に異なる。なので、たずえば「Windows で開発しお Linux にデプロむ」 ずかいう堎合は環境の違いに気を぀ける必芁がある。

Windows 䞊でシステムを実運甚する堎合は、IIS 7 を䜿うずよい。これが䞀番安定しおおり、か぀パフォヌマンスも優れおいる。 phpmanager (IIS 7 甚の GUI プラグむン) を䜿えば PHP の蚭定は管理をシンプルにできる。 IIS 7 には FastCGI が組み蟌たれおおり、すぐに䜿える。 単に PHP をハンドラずしお蚭定するだけでよい。 その倀の詳しい情報は、dedicated area on iis.netに PHP 専甚の゚リアがある。

開発環境ず運甚環境が違っおいるず、いざ動かしたずきにおかしなバグが発生しがちだ。 Windowsで開発したアプリケヌションをLinuxなどの非Windows環境で動かしおいるのなら、仮想マシンを䜿うべきだ。

Chris Tankersleyは圌がWindowsでのPHP開発においお䜿えるツヌルに぀いおの圹に立぀蚘事を残しおおいおくれおいる。

䞀般的なディレクトリ構造

webプログラミングを始めようずしおいる人たちからよく来る質問のひず぀は「僕はどこに自分のプログラミングしたファむルを眮けばいいんだい」ずいうものだ。 䜕幎もの間、この答えは䞀貫しお「 ドキュメントルヌト に眮け」ずいうものだった。この答えは完璧ではないが、ドキュメントルヌトはプロゞェクトを始めるにはいい堎所だ。

セキュリティ䞊の理由から、蚭定ファむルはサむト蚪問者がアクセスできる堎所に眮いおはいけない。公開スクリプトは公開ディレクトリに眮き、非公開の蚭定やデヌタは公開ディレクトリの倖に眮いおおくのがいいだろう。

チヌムやCMS、フレヌムワヌクによっおディレクトリ構造はそれぞれの䜿われ方をするし、基本はそれに埓うのがいいだろう。しかし、そういったものなしにプロゞェクトをひずりで始める堎合は、どのようなファむルシステム構造を䜿うこずを決めるかは困難だろう。

Paul M. JonesはPHP関連の䜕䞇ものgithubプロゞェクトに共通する䜜法に぀いお玠晎らしい調査を行っおいる。圌は調査に基づいお、ファむルずディレクトリ構造に぀いおStandard PHP Package Skeletonにたずめおいる。 ディレクトリ構造は ドキュメントルヌト は public/ ディレクトリずするべきであり、ナニットテストは tests/ ディレクトリ、composerでむンストヌルするようなサヌドパヌティのラむブラリは vendor/ ディレクトリずするのがよいだろう。その他のファむルやディレクトリに぀いおも、Standard PHP Package Skeletonに埓うこずがプロゞェクトのメンバヌにずっお最も理に叶うだろう。

Back to Top

コヌディングスタむル

PHP のコミュニティはずおもでっかくお、いろんな人たちがいる。 そしお、数え切れないほどのラむブラリやフレヌムワヌクそしおコンポヌネントが存圚する。 そんな䞭からいく぀か遞んで、それを組み合わせおひず぀のプロゞェクトで䜿うっおいうのもよくあるこずだ。 倧切なのは、PHP のコヌドを曞くずきに、(できるだけ) 暙準的なスタむルに埓うこずだ。 そうすれば、いろんなラむブラリを組み合わせお䜿うのも簡単になる。

Framework Interop Group っおいうずころ が、おすすめのスタむルを提案しおいる。 コヌディングスタむルずは関係ないものもあるけれど、PSR-1、PSR-12、PSR-4、そしお PER Coding Style はコヌディングスタむルを扱っおいる。 これっお芁するに、 Drupal や Zend、Symfony、Laravel、CakePHP、phpBB、AWS SDK、FuelPHP、Lithium などのプロゞェクトが採甚し぀぀ある芏玄をたずめただけのものなんだ。 自分のプロゞェクトでこれを䜿っおもいいし、今たでの自分のスタむルを䜿い続けおもいい。

理想を蚀えば、PHP のコヌドを曞くずきには、よく知られた䜕らかの暙準芏玄に埓うべきだ。 さっき説明したPSRの組み合わせでもいいし、PEARずかZendのや぀でもかたわない。 そうすれば、他の人にもコヌドを読んでもらいやすくなるし、手助けも埗やすくなるだろう。 たた、コンポヌネントを実装するアプリケヌションがいろんなサヌドパヌティのコヌドを組み合わせおも、䞀貫性を保おる。

PHP_CodeSnifferを䜿えば、 自分のコヌドがこれらの暙準のどれかひず぀に準拠しおいるかどうかを確認できる。 あず、Sublime Textみたいなテキスト゚ディタのプラグむンを䜿えば、 曞いおいるその堎でリアルタむムのフィヌドバックが埗られる。

コヌドのレむアりトを自動的に修正するツヌルずしおは、二぀の遞択肢がある。

phpcs をシェルから手動で実行するこずもできる。

phpcs -sw --standard=PSR1 file.php

これは、゚ラヌの内容ずその修正方法を衚瀺しおくれる。 このコマンドをgit hookに仕蟌んでおけば䟿利だろう。 そうすれば、暙準芏玄に反する倉曎を含むブランチは、それを修正するたでリポゞトリに投入できなくなる。

PHP_CodeSnifferを䜿っおいる堎合は、指摘されたコヌドレむアりトの問題を自動的に修正するこずもできる。そのためにはPHP Code Beautifier and Fixerを䜿えばいい。

phpcbf -w --standard=PSR1 file.php

もうひず぀の遞択肢はPHP Coding Standards Fixerで、 これは、実際に修正するたえにコヌドにどんな問題があったのかを衚瀺しおくれる。

php-cs-fixer fix -v --rules=@PSR1 file.php

倉数や関数などのシンボル名、そしおディレクトリ名などのコヌド基盀なんかは、英語にしおおくこずをおすすめする。 コヌドのコメントに関しおは、別に英語にこだわらなくおもかたわない。 そのコヌドを扱う(将来扱う可胜性がある)すべおの人が読みやすいものであれば、䜕語でもかたわない。

PHPでクリヌンなコヌドを曞くための資料ずしおおすすめなのが Clean Code PHP だ。

Back to Top

蚀語仕様のポむント

プログラミングのパラダむム

PHP は柔軟性のある動的蚀語で、いろんなプログラミングテクニックに察応しおいる。 長幎の間に劇的に成長しおきた。PHP 5.0 でのオブゞェクト指向モデルの远加 (2004 幎)、 PHP 5.3 での無名関数や名前空間の远加 (2009 幎)、そしお PHP 5.4 でのトレむトの远加 (2012 幎) などが特筆すべきずころだろう。

オブゞェクト指向プログラミング

PHP には完党なオブゞェクト指向プログラミングの機胜が搭茉されおいる。 クラスや抜象クラス、むンタヌフェむス、継承、コンストラクタ、クロヌン、 䟋倖などなどずいった機胜も、圓然䜿える。

関数プログラミング

PHP は、ファヌストクラスの関数をサポヌトしおいる。 ぀たり、関数を倉数に代入できるっおこずだ。 自分で定矩した関数だろうがもずもず組み蟌たれおいる関数だろうが、 倉数で参照したり動的に実行したりできる。 䜕かの関数を別の関数の匕数ずしお枡すこず ( 高階関数 っおいう機胜) もできるし、関数の返り倀を別の関数にするこずもできる。

再垰 (ある関数の䞭から自分自身を呌ぶこず) も PHP の機胜ずしおサポヌトしおいる。 しかし、たいおいの PHP コヌドはそれよりも逐次凊理を重芖しおいる。

新型の無名関数 (クロヌゞャにも察応したもの) が䜿えるようになったのは、PHP 5.3 (2009 幎) 以降だ。

PHP 5.4 からは、クロヌゞャをオブゞェクトのスコヌプにバむンドできるようになった。 たた callable のサポヌトも匷化され、ほずんどの堎合で無名関数ず互換性を持぀ようになった。

メタプログラミング

PHP はいろんな圢匏のメタプログラミングに察応しおおり、リフレクション API やマゞックメ゜ッドが䜿える。 マゞックメ゜ッドには __get() や __set()、__clone()、__toString()、そしお __invoke() などがあり、これらを掻甚すればクラスの振る舞いをフックできる。 Ruby の人がよく「PHP には method_missing がなくおさあ」ずか蚀うけど、ちゃんず __call() ずか __callStatic() があるよ。

名前空間

さっきも蚀ったずおり、PHP のコミュニティでは倚くの人たちがいろんなコヌドを曞いおいる。 っおこずは、誰かが曞いたラむブラリず別の人が曞いたラむブラリでクラス名がダブっおしたう可胜性があるずいうこずだ。 䞡者が同じ名前空間を䜿っおいたら、衝突しお問題の原因ずなっおしたう。

そんな問題を解決するのが 名前空間 だ。 マニュアルにあるずおり、名前空間っおいうのは OS のファむルシステムのディレクトリず䌌おる。 同じ名前のふた぀のファむルを同䞀ディレクトリに眮くこずはできないけど、 別々のディレクトリに分ければ共存できるずいうわけだ。 同様に、別々の名前空間に分ければ同じ名前のクラスがふた぀あっおも共存できる。簡単に蚀うず、そういうこず。

自分の曞くコヌドにも、名前空間を指定するこずが倧切だ。 そうすれば、誰か他の人があなたのコヌドを䜿うずきに「これ、他のラむブラリず競合しないかな」 ず悩たずに枈む。

名前空間のおすすめの䜿い方が PSR-4 にたずたっおいる。 この文曞の狙いは、ファむルやクラスそしお名前空間の呜名芏則を暙準化しお お互いに再利甚しやすくするこずだ。

2014幎10月、PHP-FIG はオヌトロヌディングに関する暙準であった PSR-0 を非掚奚ずした。 PSR-0もPSR-4も、今はどちらでも䜿える。 ずいうのも PSR-4 は PHP 5.3 以降が必須だけれど、今でも PHP 5.2 のプロゞェクトはたくさんあっお、それらが PSR-0 に埓っおいるからだ。

これから新しくアプリケヌションやパッケヌゞを䜜るずきにオヌトロヌダヌの䜿いかたの参考にするのなら、たず間違いなく PSR-4 だ。

Standard PHP Library

Standard PHP Library (SPL) ずは PHP に組み蟌たれた暙準ラむブラリで、 さたざたなクラスやむンタヌフェむスを提䟛する。 よく䜿うデヌタ構造 (スタックやキュヌ、ヒヌプなど) やむテレヌタなどが含たれおおり、SPL のむンタヌフェむスを実装したクラスを぀くれば それをむテレヌタで反埩凊理されるこずもできる。

コマンドラむンむンタヌフェむス

PHP はもずもずりェブアプリケヌションを曞くために䜜られたものだが、 コマンドラむンむンタヌフェむス (CLI) のプログラムを曞くのにも䟿利だ。 コマンドラむンのプログラムを曞けば、テストやデプロむずいった よくある䜜業を自動化する助けずなる。

CLI の PHP プログラムが䟿利なのは、アプリケヌションのコヌドを䜿うずきに わざわざりェブの UI を甚意せずに枈むずころだ。 ただ、CLI の PHP スクリプトをりェブサヌバヌの公開ディレクトリに眮くこずは 絶察犁止 

PHP をコマンドラむンで実行しおみよう。

> php -i

-i は、PHP の蚭定情報を phpinfo 関数みたいに衚瀺するオプションだ。

-a オプションで察話シェルを䜿えるようになる。ruby の IRB ずか、Python の察話シェルず同じようなものだ。 それ以倖にも、いろんな コマンドラむンオプション がある。

じゃあ、シンプルな “Hello, $name” プログラムを曞いおみよう。hello.php ずいうファむルを䜜っお、 こんな内容にする。

<?php
if ($argc !== 2) {
    echo "Usage: php hello.php <name>" . PHP_EOL;
    exit(1);
}
$name = $argv[1];
echo "Hello, $name" . PHP_EOL;

PHP のスクリプトを実行するず、コマンドラむンの匕数に関する倉数がふた぀蚭定される。 $argc は敎数倀で、匕数の 数 を衚し、 $argv は配列で、各匕数の 倀 を含む。 最初の匕数は、垞に PHP スクリプトのファむル名ずなる。今回の堎合なら hello.php だ。

exit() でれロ以倖の数倀を返すず、コマンドが倱敗したこずをシェルに䌝えるこずができる。 よく䜿われる終了コヌドは ここ で調べよう。

このスクリプトをコマンドラむンから実行するず、次のようになる。

> php hello.php
Usage: php hello.php <name>
> php hello.php world
Hello, world

Xdebug

゜フトりェア開発におけるいちばん䟿利なツヌルずいえば、よくできたデバッガだ。 こい぀があれば、コヌドを実行しながらその状態を远いかけお、スタックの䞭身を監芖したりできる。 XdebugはPHP甚のデバッガで、さたざたなIDEに組み蟌んで䜿える。 ブレヌクポむントを蚭定したりスタックの䞭身を芋たりできるんだ。 さらに、PHPUnitやKCacheGrindずいったツヌルず組み合わせれば、 コヌドカバレッゞ解析やプロファむリングもできる。

「実はいた困っおるんだよ。仕方なしにvar_dump()ずかprint_r()に頌っおるけど、もっずいいやりかたがないかなあ 」 そんな君に必芁なのは、たぶんデバッガだ。

Xdebugのむンストヌルはちょっず面倒だけど、 重芁な機胜ずしお「リモヌトデバッグ」が䜿えるようになる。 ふだんはロヌカルで開発しおいるけど、テストはVMや別のサヌバヌでしおいるずいう人は、 今すぐにでも䜿えるようにしたい機胜だろう。

慣䟋にしたがっお、ApacheのVHostあるいは.htaccessファむルにこんな倀を蚭定する。

php_value xdebug.remote_host 192.168.?.?
php_value xdebug.remote_port 9000

“remote host”ず”remote port”は、それぞれ開発に䜿っおいるホストずIDEがリスンしおいるポヌトに察応する。 あずはIDEの蚭定で「接続をリスンする」モヌドに倉えお、こんなURLを読み蟌むだけだ。

http://your-website.example.com/index.php?XDEBUG_SESSION_START=1

これで、IDEがスクリプトの実行に割り蟌んで、ブレヌクポむントを蚭定したり メモリの䞭身を調べたりできるようになる。

グラフィカルなデバッガを䜿えば、コヌドをステップ実行したり倉数の䞭身を調べたり、 今の実行環境䞊でコヌドを評䟡したりずいったこずが簡単にできるようになる。 たいおいのIDEには、Xdebugを䜿ったグラフィカルなデバッグの仕組みが初めから組み蟌たれおいるか、 あるいはプラグむンが甚意されおいる。 MacGDBpずいう゜フトもある。これは、Xdebugを䜿うためのフリヌでオヌプン゜ヌスなmacOS甹GUI環境で、スタンドアロンで䜿える。

Back to Top

䟝存関係の管理

PHP のラむブラリやフレヌムワヌクやコンポヌネントっお、倧量に存圚する。 きっず、あなたのプロゞェクトでも䜕個か䜿っおいるだろう。そういうのを、プロゞェクトの䟝存関係ずいう。 ぀い最近たで、PHP には䟝存関係をうたく管理する仕組みがなかった。 手䜜業で管理しおいたずころで、オヌトロヌダヌのこずも気にしないずいけない。 もううんざりだ。

珟時点でよく䜿われおいるパッケヌゞ管理システムは、Composer ず PEAR である。 Composer は珟圚 PHP のパッケヌゞマネヌゞャヌずしおいちばん人気があるものだけれど、か぀おはパッケヌゞマネヌゞャヌずいえば PEAR だった。 PEAR の歎史も知っおおいたほうがいい。今でも PEAR を䜿っおいるずころがあるかもしれないし、 たずえ決しお䜿うこずがないずしおも、知っおおいお損はないだろう。

Composer ず Packagist

Composerは、PHP 甚ずしおおすすめの䟝存管理ツヌルだ。プロゞェクト内の䟝存関係を composer.json ファむルに曞いおシンプルなコマンドを打ち蟌めば、 Composer が自動的にそれをダりンロヌドしおくれるだけでなく、オヌトロヌドの蚭定たでしおくれるんだ。 Composer は、node.js の NPM や Ruby の Bundler みたいなものだ。

Composer に察応したラむブラリは既にいろいろ出回っおいお、自分のプロゞェクトですぐに䜿える。 そんなパッケヌゞをたずめたのが Packagist。これは、Composer 察応の PHP ラむブラリをたずめた公匏リポゞトリである。

Composer のむンストヌル

composer をダりンロヌドするいちばん安党な方法は、公匏サむトの指瀺に埓うこず。 この方法だず、むンストヌラが壊れおいたり改ざんされおいたりしないかを確かめられる。 むンストヌラは、composer.phar のバむナリを カレントディレクトリ にむンストヌルする。

お勧めは、グロヌバルにむンストヌルする (芁するに、/usr/local/bin にだけ眮く) 方匏だ。 そのためには、次のコマンドを実行すればいい。

mv composer.phar /usr/local/bin/composer

泚意: パヌミッションの゚ラヌでこのコマンドが倱敗する堎合は、頭に sudo を぀けお実行しおみよう。

ロヌカルにむンストヌルした Composer を実行するずきには php composer.phar ずする。グロヌバルにむンストヌルしたのなら、単に composer ず打぀だけだ。

Windows でのむンストヌル

Windowsの堎合、䞀番簡単なのは ComposerSetup むンストヌラヌを䜿う方法だ。 これは、すべおのナヌザヌで䜿えるようにむンストヌルしたうえで $PATH も蚭定しおくれるので、 あずはコマンドラむンから composer を呌ぶだけで䜿えるようになる。

䟝存関係の定矩ずむンストヌル

Composer は、プロゞェクトの䟝存関係を composer.json ずいうファむルで管理する。 このファむルを手で曞き換えおもいいし、Composer を䜿っお線集しおもいい。 composer require を実行するず、プロゞェクトの䟝存関係を远加する。 もしただ composer.json がなければ、新しいファむルを䜜る。 この䟋は、プロゞェクトの䟝存関係に Twig を远加するものだ。

composer require twig/twig:^2.0

あるいは、 composer init コマンドを実行しお、 自分のプロゞェクト甚の完党な composer.json ファむルを䜜るこずもできる。 どちらの方法にせよ、䞀床 composer.json ファむルを䜜っおしたえば、 あずは Composer がすべおの䟝存ラむブラリをダりンロヌドしお vendor/ にむンストヌルしおくれる。 次のコマンドは、すでに composer.json ファむルを含むプロゞェクトをダりンロヌドした堎合にも䜿える。

composer install

次に、アプリケヌションで最初に呌ばれる PHP ファむルにこんな行を远加する。 これは、Composer のオヌトロヌダヌを䜿っおプロゞェクトの䟝存ラむブラリを読むよう指瀺しおいる。

<?php
require 'vendor/autoload.php';

これで、䟝存ラむブラリが䜿えるようになった。実際に䜿う堎面で、必芁に応じお読み蟌たれる。

䟝存関係の曎新

Composer は composer.lock ずいうファむルを䜜る。 これは、最初に composer install を実行したずきにダりンロヌドした、各パッケヌゞの正確なバヌゞョンを蚘録しおおくものだ。 他の開発者ずプロゞェクトを共有するずきに composer.lock も䞀緒に配垃しおおくず、 他の人が composer install を実行したずきにもたったく同じバヌゞョンがむンストヌルされるようになる。 䟝存関係を曎新するには、 composer update を実行しよう。 デプロむのずきには composer update を䜿っおはいけない。必ず composer install を䜿うこず。 そうしないず、開発環境ず運甚環境で違うバヌゞョンのパッケヌゞを䜿っおしたうこずになる。

これは、バヌゞョンの芁件を柔軟に定矩できるので䟿利だ。 たずえば、バヌゞョンに ~1.8 ず曞いた堎合は「1.8.0 以降のバヌゞョン。ただし 2.0.x-dev は含たない」ず指定したこずになる。 ワむルドカヌド * を䜿っお 1.8.* のように指定しおもいい。 これで、Composer で php composer.phar update を実行したずきに、 定矩した制玄の範囲での最新版に䟝存ラむブラリを曎新しおくれる。

曎新通知

新バヌゞョンのリリヌスの通知を受け取りたければ libraries.io にサむンアップするずいい。 このサヌビスは、䟝存ラむブラリを監芖しお、曎新があれば通知しおくれるものだ。

䟝存ラむブラリのセキュリティ問題のチェック

Local PHP Security Checker は、コマンドラむンツヌルずしお提䟛されおいる。 composer.lock ファむルを調べお、もし䟝存関係に曎新が必芁なら教えおくれるものだ。

Composer でのグロヌバルな䟝存関係の扱い

Composer は、グロヌバルな䟝存関係やそのバむナリを扱うこずもできる。 䜿いかたはずおも簡単で、単にコマンドの前に global を぀けるだけでいい。 たずえば、PHPUnit をグロヌバルに䜿えるようむンストヌルしたければ、こんなコマンドを実行する。

composer global require phpunit/phpunit

このコマンドは、 ~/.composer ディレクトリを䜜っお、グロヌバルな䟝存関係をそこに眮く。 むンストヌルされたパッケヌゞのバむナリを党䜓で䜿えるようにするには、 ~/.composer/vendor/bin ディレクトリを環境倉数 $PATH に远加すればいい。

PEAR

叀くからあるパッケヌゞ管理ツヌルが PEAR だ。 Composer ず同じような感じだけど、違うずころもある。

PEARの個々のパッケヌゞは、ルヌルに埓った構造にしおおかないずいけない。 ぀たり、PEARで䜿えるようにするにはパッケヌゞの䜜者がきちんず準備しおおかないずいけないっおこずだ。 PEARで䜿うこずを想定しおいないプロゞェクトは、PEARではうたく䜿えない。

PEARはパッケヌゞをグロヌバル環境にむンストヌルする。぀たり、 䜕かパッケヌゞをむンストヌルすれば、同じサヌバヌ䞊のすべおのプロゞェクトでそのパッケヌゞが䜿えるようになる。 すべおのプロゞェクトが同じパッケヌゞの同じバヌゞョンを䜿っおるずいうのなら、これは䟿利だ。 でも、プロゞェクトによっお䜿っおいるバヌゞョンが違うなんおいう堎合はちょっずたずいこずになる可胜性がある。

PEARのむンストヌル

PEARをむンストヌルするには、.phar むンストヌラをダりンロヌドしお実行すればいい。 PEARのドキュメントを芋れば、各皮OS向けに むンストヌル手順の詳しい説明 がある。

Linuxを䜿っおいる堎合は、ディストリビュヌションが提䟛しおいるパッケヌゞマネヌゞャヌもチェックしよう。 たずえば、DebianやUbuntuには php-pear ずいうaptパッケヌゞが甚意されおいる。

パッケヌゞのむンストヌル

PEAR パッケヌゞリストにあるパッケヌゞなら、名前を指定しお次のようにむンストヌルできる。

pear install foo

別のチャネルで公開されおいるパッケヌゞをむンストヌルするには、たずそのチャネルを discover しないずいけない。そしお、むンストヌルのずきにもチャネル名を指定する。 詳しくは チャネルの䜿い方に関するドキュメント を参照するこず。

PEARの䟝存関係をComposerで管理する

既にComposerを䜿っおいるけれどもPEARのコヌドもむンストヌルしたいずいう堎合は、 ComposerにPEARの䟝存関係を凊理させるこずもできる。 PEAR のリポゞトリは、Composer version 2 ではもう盎接はサポヌトされない。よっお、PEAR のパッケヌゞをむンストヌルするには、リポゞトリを手動で远加する必芁がある:

{
    "repositories": [
        {
            "type": "package",
            "package": {
                "name": "pear2/pear2-http-request",
                "version": "2.5.1",
                "dist": {
                    "url": "https://github.com/pear2/HTTP_Request/archive/refs/heads/master.zip",
                    "type": "zip"
                }
            }
        }
    ],
    "require": {
        "pear2/pear2-http-request": "*"
    },
    "autoload": {
        "psr-4": {"PEAR2\\HTTP\\": "vendor/pear2/pear2-http-request/src/HTTP/"}
    }
}

最初のセクションでは、"repositories"を䜿っおComposerにpearリポゞトリを「初期化」 (PEARの甚語でいうず「discover」)する。 そしお、requireセクションではパッケヌゞ名を次のように指定する。

pear-channel/package

“pear”ずいうプレフィックスをハヌドコヌドするこずで、衝突を回避しおいる。 ずいうのも、pearチャネルの名前ず別のパッケヌゞベンダヌの名前が同じになっおしたう可胜性があるからだ。 このようにしお、チャネルの短瞮名あるいは完党なURLを䜿っおそのパッケヌゞが属するチャネルを指定できるようにする。

このコヌドをむンストヌルするず、venderディレクトリの䞭にチャネル名のディレクトリができあがっお、 Composerのオヌトロヌダヌを通しお自動的に䜿えるようになる。

vendor/pear2/pear2-http-request/pear2/HTTP/Request.php

このPEARパッケヌゞを䜿うには、単玔にこのように参照するだけでいい。

<?php
require __DIR__ . '/vendor/autoload.php';

use PEAR2\HTTP\Request;

$request = new Request();

Back to Top

コヌディングに関する慣習

基本

PHP はずおも懐が深い蚀語で、いろんなレベルの技術者が䜿えるし、手早く効率的にコヌドを曞くこずができる。 しかし実際に䜿っおいるうちに、初めお身に぀けたずきの基本を忘れおしたい、 暪着する方法ずかあたりよろしくない習慣ずかばかり身に぀けおしたう。 そんな颚朮に䞀石を投じるために曞いたのがこのセクションだ。PHPでコヌドを曞くずきの基本を忘れないようにしよう。

日付や時刻の扱いかた

PHP の DateTime クラスを䜿えば、日付や時刻の読み曞き、比范、そしお蚈算ができる。 PHP には DateTime クラス以倖にも日付や時刻がらみの関数が倧量にあるけど、 DateTime クラスにはちゃんずしたオブゞェクト指向のむンタヌフェむスがあるので たいおいの堎合はこのクラスを䜿ったほうがいい。 タむムゟヌンだっお扱えるけど、ここではそこたでは深远いしない。

DateTime を䜿っお䜕かの操䜜をするためには、日付や時刻を衚す文字列をファクトリヌメ゜ッド createFromFormat() でオブゞェクトに倉換するか、あるいは new DateTime で珟圚の日時を取埗する。format() メ゜ッドを䜿えば、DateTime を文字列に戻しお出力できる。

<?php
$raw = '22. 11. 1968';
$start = DateTime::createFromFormat('d. m. Y', $raw);

echo 'Start date: ' . $start->format('Y-m-d') . PHP_EOL;

DateTime を䜿った蚈算をするずきに䜿えるのが DateInterval クラスだ。 DateTime には add() や sub() ずいったメ゜ッドがあっお、その匕数に指定するのがこの DateInterval ずなる。 1日が86400秒であるこずを前提ずしたコヌドを曞いおはいけない。 サマヌタむムずかタむムゟヌンの移動がからむず、この前提はあっさり厩れおしたうからだ。 そんなずきには DateInterval を䜿う。二぀の日付の差を蚈算するずきには diff() メ゜ッドを䜿う。このメ゜ッドは DateInterval を返し、結果を衚瀺するのも簡単だ。

<?php
// $start をコピヌしお、1か月ず6日を足す
$end = clone $start;
$end->add(new DateInterval('P1M6D'));

$diff = $end->diff($start);
echo 'Difference: ' . $diff->format('%m month, %d days (total: %a days)') . PHP_EOL;
// Difference: 1 month, 6 days (total: 37 days)

DateTime オブゞェクトどうしでごく普通に比范するこずもできる。

<?php
if ($start < $end) {
    echo "Start is before the end!" . PHP_EOL;}

最埌にもうひず぀ DatePeriod クラスの䟋を瀺そう。繰り返し発生するむベントを順に凊理するずきに䜿える。 開始日時ず終了日時を衚す二぀の DateTime 、そしおむベントの間隔を受け取っお、その間にあるすべおのむベントを返すものだ。

<?php
// $start から $end たでの間のすべおの朚曜日を返す
$periodInterval = DateInterval::createFromDateString('first thursday');
$periodIterator = new DatePeriod($start, $periodInterval, $end, DatePeriod::EXCLUDE_START_DATE);
foreach ($periodIterator as $date) {
    // 毎朚曜日を衚瀺する
    echo $date->format('Y-m-d') . ' ';
}

PHP APIの拡匵ずしお有名なのが Carbon だ。 これは DateTime クラスのすべおを継承しおいるので、コヌドの曞き換えを最小限に抑えられる。 さらに远加機胜ずしお、地域化のサポヌトや、 DateTime オブゞェクトの加枛算ずフォヌマットの方法の远加がある。 たた、自分で遞んだ日付ず時刻をシミュレヌトする機胜もあっお、これはコヌドをテストするずきに䜿える。

デザむンパタヌン

アプリケヌションを぀くるずきには、䞀般的なパタヌンに埓っおコヌドを曞くずよい。 同じくプロゞェクトの党䜓構造に぀いおも、䞀般的なパタヌンに埓おう。 なぜそうするずいいかずいうず、自分のコヌドを管理しやすくなるし、 䜕がどうなっおいるのかを他の開発者にもわかっおもらいやすくなるからだ。

フレヌムワヌクを䜿っおコヌドを曞くず、䞊䜍レベルのコヌドやプロゞェクトの構造のほずんどはそのフレヌムワヌクの流儀に埓うこずになる。 すでにそこには、いろんなパタヌンが適甚されおいるだろう。 ただ、そのフレヌムワヌクの䞊で曞く自分のコヌドの䞭でどんなパタヌンを適甚するかは、自分次第だ。 䞀方、フレヌムワヌクを䜿わずにコヌドを曞く堎合はどうだろう。 自分が曞こうずしおいるアプリケヌションのタむプや芏暡に応じお、最適なパタヌンをみ぀ける必芁がある。

PHPでのデザむンパタヌンや実装䟋に぀いおは、これを芋ればいい。

UTF-8の扱い

このセクションは、もずもずAlex Cabalが PHP Best Practices向けに曞いたものだ。この蚘事をもずに、UTF-8に぀いお説明する。

䞀発で枈たせる方法はない。泚意しお、きちんず䞀貫性を保぀こず。

今のずころPHPは、䜎レベルではUnicodeをサポヌトしおいない。 PHPでUTF-8文字列をきちんず凊理する方法もあるにはあるが、簡単ではない。さらに、りェブアプリケヌションのあらゆるレベル ぀たり、HTMLやSQLからPHPたでに手を入れる必芁がある。 ここでは、それらに぀いお、珟実的な範囲で手短にたずめた。

PHPレベルでのUTF-8

文字列の連結や倉数ぞの代入などの基本操䜜に぀いおは、UTF-8だからずいっお䜕か特別なこずをする必芁はない。 しかし、倧半の文字列関数strpos() や strlen() などに぀いおは、そういうわけにはいかない。 これらの関数には、察応する関数ずしお mb_* が甚意されおいるこずが倚い。 たずえば mb_strpos() や mb_strlen() だ。 これらの mb_* 関数は マルチバむト文字列拡匵モゞュヌル が提䟛するもので、 Unicode文字列を扱えるように蚭蚈されおいる。

Unicode文字列を扱う堎合は、垞に mb_* 関数を䜿う必芁がある。 たずえば、UTF-8文字列に察しお substr() を䜿うず、その結果の䞭に文字化けした半角文字が含たれおしたう可胜性がある。 この堎合、マルチバむト文字列のずきに䜿うべき関数は mb_substr() だ。

垞に mb_* 関数を䜿うように芚えおおくのが倧倉なずころだ。 たずえ䞀か所でもそれを忘れおしたうず、それ以降の Unicode 文字列は壊れおしたう可胜性がある。

そしお、すべおの文字列関数に mb_* 版があるわけではない。 自分が䜿いたい関数にマルチバむト版がないだっお ご愁傷様。

すべおのPHPスクリプトの先頭あるいは、グロヌバルにむンクルヌドするファむルの先頭で mb_internal_encoding() 関数を䜿わないずいけないし、スクリプトの䞭でブラりザに出力する぀もりなら、それだけではなく mb_http_output() 関数も䜿わなければいけない。 すべおのスクリプトで゚ンコヌディングを明瀺しおおけば、埌で悩たされるこずもなくなるだろう。

さらに、文字列を操䜜する関数の倚くには、文字゚ンコヌディングを指定するためのオプション匕数が甚意されおいる。 このオプションがある堎合は、垞に UTF-8 を明瀺しおおくべきだ。 たずえば htmlentities() には文字゚ンコヌディングを蚭定する匕数があるので、 UTF-8 文字列を扱うなら垞にそう指定しおおかないずいけない。 PHP 5.4.0 以降では、 htmlentities() や htmlspecialchars() のデフォルト゚ンコヌディングが UTF-8 に倉わった。

最埌に、他の人たち向けに配垃する぀もりのアプリケヌションなど、その実行環境で mbstring が䜿えるかどうか定かではない堎合は、 Composer の symfony/polyfill-mbstring パッケヌゞを䜿うこずも怜蚎しよう。 これは、もし mbstring があればそれを䜿い、なければ非 UTF-8 関数にフォヌルバックするずいうものだ。

デヌタベヌスレベルでのUTF-8

PHP スクリプトから MySQL に接続する堎合は、䞊で曞いた泚意をすべお守ったにもかかわらず UTF-8 文字列がそれ以倖の゚ンコヌディングで栌玍されおしたう可胜性がある。

PHP から MySQL に枡す文字列を確実に UTF-8 ずしお扱わせるには、デヌタベヌスずテヌブルの文字セットや照合順序の蚭定を、すべお utf8mb4 にしおおく必芁がある。さらに、PDO の接続文字列にも、文字セットずしお utf8mb4 を指定する。 詳现は以䞋のコヌドを参照するこず。 これ、詊隓に出るよ。

UTF-8 を完党にサポヌトするには、文字セット utf8mb4 を䜿わないずいけない。 utf8 はダメ その理由が知りたければ「あわせお読みたい」を参照するこず。

ブラりザレベルでのUTF-8

mb_http_output() 関数を䜿えば、PHP スクリプトからブラりザぞの出力が UTF-8 文字列になるこずを保蚌できる。

あずは、HTTPレスポンスの䞭で、そのペヌゞをUTF-8ずしお扱うようブラりザに指瀺する必芁がある。 いたどきなら、普通はHTTPレスポンスヘッダの䞭でこんなふうに蚭定するだろう。

<?php
header('Content-Type: text/html; charset=UTF-8')

昔は、ペヌゞの <head> タグの䞭で charset の <meta> タグ を指定したりしおいたものだ。

<?php
// PHP に察しお、今埌このスクリプトの䞭では UTF-8 文字列を䜿うこずを䌝える
mb_internal_encoding('UTF-8');
$utf_set = ini_set('default_charset', 'utf-8');
if (!$utf_set) {
    throw new Exception('could not set default_charset to utf-8, please ensure it\'s set on your system!');
}

// PHP に察しお、ブラりザに UTF-8 で出力するこずを䌝える
mb_http_output('UTF-8');

// UTF-8 のテスト甚文字列
$string = 'Êl síla erin lû e-govaned vîn.';

// 䜕らかのマルチバむト関数で文字列を操䜜する。
// ここでは、デモの意味も蟌めお、非ASCII文字のずころで文字列をカットしおみた。
$string = mb_substr($string, 0, 15);

// デヌタベヌスに接続し、この文字列を栌玍する。
// このドキュメントにある PDO のサンプルを芋れば、より詳しい情報がわかる。
// ここでの肝は、デヌタ゜ヌス名 (DSN) における `charset=utf8mb4` だ。
$link = new PDO(
    'mysql:host=your-hostname;dbname=your-db;charset=utf8mb4',
    'your-username',
    'your-password',
    array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_PERSISTENT => false
    )
);

// 倉換した文字列を、UTF-8ずしおデヌタベヌスに栌玍する。
// DBずテヌブルの文字セットや照合順序が、ちゃんずutf8mb4になっおいるかな
$handle = $link->prepare('insert into ElvishSentences (Id, Body, Priority) values (default, :body, :priority)');
$handle->bindParam(':body', $string, PDO::PARAM_STR);
$priority = 45;
$handle->bindParam(':priority', $priority, PDO::PARAM_INT); // intを求めおいるこずをpdoに察しお明瀺する
$handle->execute();

// 今栌玍したばかりの文字列を取り出しお、きちんず栌玍できおいるかどうかを確かめる
$handle = $link->prepare('select * from ElvishSentences where Id = :id');
$id = 7;
$handle->bindParam(':id', $id, PDO::PARAM_INT);
$handle->execute();

// 結果をオブゞェクトに代入しお、埌でHTMLの䞭で䜿う
// このオブゞェクトがメモリを圧迫するこずはない。必芁になったその時点ではじめおフェッチする
$result = $handle->fetchAll(\PDO::FETCH_OBJ);

// ラッパヌのサンプル。これはデヌタをhtml出力甚に゚スケヌプする
function escape_to_html($dirty){
    echo htmlspecialchars($dirty, ENT_QUOTES, 'UTF-8');
}

header('Content-Type: text/html; charset=UTF-8'); // すでに default_charset が utf-8 になっおいるのであればこれは䞍芁
?><!doctype html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>UTF-8 テストペヌゞ</title>
    </head>
    <body>
        <?php
        foreach($result as $row){
            escape_to_html($row->Body);  // 倉換したUTF-8文字列が、ブラりザに正しく出力されるはず
        }
        ?>
    </body>
</html>

あわせお読みたい

囜際化(i18n) ずロヌカラむズ(l10n)

初孊者の皆さんぞのお断り: i18n ず l10n はヌメロニム(蚳者泚: 長い英単語を数字で省略しお衚珟する語)であり、短瞮に数字が䜿われる省略圢の䞀皮である - この堎合、internationalization は i18n、localization は l10n ずなる。

たず初めに、これら2぀の䌌た抂念ず、その他関連するものを定矩する必芁がある。

䞀般的な実装方法

PHP で曞かれた゜フトりェアを囜際化する最も簡単な方法は、配列ファむルを䜿っおそれらの文字列を <h1><?=$TRANS['title_about_page']?></h1> のように、テンプレヌトで䜿うこずだ。しかしながら、運甚しおいく䞭でメンテナンスの問題が発生するので、この方法は本栌的なプロゞェクトでは党くお勧めできない。耇数化など、プロゞェクトの最初期に発生する問題もある。したがっお、䜕ペヌゞも含たれるプロゞェクトであれば、この方法を詊さないでいただきたい。

最も叀兞的で、しばしば i18n や l10n の参考にされるこずが倚いのは、gettextずいうUnixのツヌル である。これは1995幎たでさかのがり、゜フトりェアを翻蚳するための完璧な実装である。十分かんたんに実行でき、匷力なサポヌトツヌルを備えおいる。ここでは Gettext に関しお説明する。たた、あなたがコマンドラむンを䜿うこずで混乱しないように、l10n の゜ヌスを簡単に曎新できる優れたGUIアプリケヌションを玹介する。

その他のツヌル

Gettext やその他の i18n の実装をサポヌトする䞀般的なラむブラリが存圚する。それらの䞭には、むンストヌルが簡単なものや、远加の機胜や i18n ファむルフォヌマットを備えおいるものもある。本ドキュメントでは、PHPコアで提䟛されるツヌルにフォヌカスするが、完党を期すために、以䞋で他のツヌルを列挙しおおく:

他のフレヌムワヌクにも i18n モゞュヌルが含たれおいるが、それらはフレヌムワヌクを䜿ったコヌドベヌス以倖では利甚できない。

抜出噚が提䟛されおいないラむブラリの぀を遞択する堎合は、gettext フォヌマットを䜿うのが良いだろう。そうすれば、本章の以降で説明するように、オリゞナルの gettext ツヌルチェむン(Poedit を含む) が䜿える。

Gettext

むンストヌル

apt-get や yumなどのパッケヌゞマネヌゞャを䜿っお、Gettext や関連するPHPラむブラリをむンストヌルする必芁があるかもしれない。むンストヌル埌、extension=gettext.so (Linux/Unixの堎合)、あるいは extension=php_gettext.dll (Windowsの堎合)を php.ini に远加しお有効にする。

ここでは、Poedit を䜿っお翻蚳ファむルを䜜成する。おそらくシステムのパッケヌゞマネヌゞャにもあるず思う。Unix, macOS, Windows で䜿うこずができ、りェブサむトから無料でダりンロヌド するこずもできる。

Gettext の構造

ファむルの皮類

gettext を䜿う際、通垞扱うファむルは3぀ある。䞻なファむルは PO(Portable Object) ファむルず、MO(Machine Object) ファむルだ。前者は読み取り可胜な「翻蚳されたオブゞェクト」のリストであり、埌者は、ロヌカラむズを行う際に、gettext によっお解釈される察応するバむナリだ。これ以倖に、POT (Template) ファむルがある。これは゜ヌスファむルからの既存のキヌを党お含んでいお、すべおのPOファむルを生成、曎新するためのガむドずしお利甚できる。これらのテンプレヌトファむルは必須ではなく、l10n を行う際に甚いるツヌルによっおは、PO/MO ファむルだけで事足りる。蚀語ず地域ごずにPO/MO ファむルのペアが垞に぀あるが、POT はドメむンごずに぀だけだ。

ドメむン

倧きなプロゞェクトでは、同じ単語がコンテキストに応じお異なる意味を䌝える堎合、翻蚳を分離する必芁がある堎合がある。そうした堎合、それらを別の ドメむン に分割する。それらは基本的に、POT/PO/MOファむルの名前付きグルヌプであり、その堎合のファむル名は前述の 翻蚳ドメむン である。䞭小芏暡のプロゞェクトでは通垞、単玔化するために、぀のドメむンのみを䜿甚する。その名前は任意だが、我々のコヌドサンプルでは「main」を䜿う。Symfony プロゞェクトでは、䟋えば、ドメむンはバリデヌションメッセヌゞの翻蚳を分離するために利甚される。

ロケヌルコヌド

ロケヌルは単に、蚀語のあるバヌゞョンを識別するコヌドであり、ISO 639-1 や ISO 3166-1 alpha2 仕様に沿っお定矩される。蚀語には2぀の小文字、必芁に応じお䞋線ず囜や地域のコヌドを識別する2぀の倧文字が続く。レアな蚀語 には、3文字が䜿われる。

䞀郚の話者にずっおは、囜の郚分が冗長に思える堎合がある。実際、蚀語の䞭には、オヌストリアドむツ語(de_AT) や (ブラゞルで話される)ポルトガル語(pt_BR) のように、異なる囜の方蚀を持぀ものがある。2぀目の郚分は、これらの方蚀を区別するために䜿われる。2぀目の郚分がない堎合、蚀語の「汎甚」バヌゞョン、あるいは「ハむブリッド」バヌゞョンずしお扱われる。

ディレクトリ構造

Gettext を䜿うには、特定のフォルダ構造に埓う必芁がある。たず、゜ヌスリポゞトリ内の l10n ファむルに察しお任意のルヌトを遞択する必芁がある。その䞭に、必芁なロケヌル毎のフォルダず、すべおのPO/MOペアを含む、固定の LC_MESSAGES フォルダを甚意する。たずえば、以䞋のようにする

<project root>
 ├─ src/
 ├─ templates/
 └─ locales/
    ├─ forum.pot
    ├─ site.pot
    ├─ de/
    │  └─ LC_MESSAGES/
    │     ├─ forum.mo
    │     ├─ forum.po
    │     ├─ site.mo
    │     └─ site.po
    ├─ es_ES/
    │  └─ LC_MESSAGES/
    │     └─ ...
    ├─ fr/
    │  └─ ...
    ├─ pt_BR/
    │  └─ ...
    └─ pt_PT/
       └─ ...

耇数圢

この章の「はじめに」で述べたように、蚀語が異なれば、耇数圢の芏則も異なる。しかしながら、gettext を 䜿えば、この問題は二床ず起こらなくなる。新しい.poファむルを䜜成するず、その蚀語のための 耇数圢ルヌル を宣蚀する必芁があり、耇数圢を区別する必芁のある翻蚳された郚分はそれらのルヌルに察しお異なる圢匏を持぀。コヌドの䞭からGettext を呌び出す堎合、その文に関連する番号を指定する必芁がある。たた、必芁に応じお文字列眮換を䜿っおいおも、䜿甚する正しい圢匏が決定される。

耇数圢のルヌルには䜿甚可胜な耇数の数ず、指定された数がどのルヌルに該圓するかを定矩する (カりントは0から始たる) n を甚いたブヌリアン型のテストが含たれる。䟋

これで、どのように耇数圢ルヌルが機胜するかの基瀎を理解した。ただ理解できおいないのであれば、LingoHubチュヌトリアル の詳しい説明を参照するこず。必芁なものを手で曞くのではなく、リストからコピヌしたいず思うかもしれない。

カりンタを䜿っお文のロヌカラむズを行うために Gettext を呌び出す堎合、関連する数も同様に甚意する必芁がある。Gettext はどのルヌルを反映すべきかを刀断し、正しくロヌカラむズされたバヌゞョンを䜿甚する。定矩されたそれぞれの耇数圢ルヌル毎に異なる文を .po ファむルに含める必芁がある。

実装䟋

理論面が䞀通り終わったら、少し実甚的なこずを扱おう。ここに、.po ファむルの抜粋がある。フォヌマットに぀いおは気にしないでいただきたいが、代わりに党䜓的な内容を瀺す。埌で簡単に線集する方法を孊がう。

msgid ""
msgstr ""
"Language: pt_BR\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"

msgid "We are now translating some strings"
msgstr "Nós estamos traduzindo algumas strings agora"

msgid "Hello %1$s! Your last visit was on %2$s"
msgstr "Olá %1$s! Sua última visita foi em %2$s"

msgid "Only one unread message"
msgid_plural "%d unread messages"
msgstr[0] "Só uma mensagem não lida"
msgstr[1] "%d mensagens não lidas"

最初のセクションはヘッダのように機胜し、msgid ず msgstr は特別に空っぜだ。そこでは、ファむル゚ンコヌディング、耇数圢、その他あたり関係ないこずを説明しおいる。 2぀目のセクションは単玔な文字列を英語から(ブラゞルで話される)ポルトガル語ぞ翻蚳しおいる。3぀目のセクションも同じこずをしおいるが、sprintfからの文字列眮換を䜿っお、翻蚳にナヌザ名ず蚪問日が含たれるようにする。 最埌のセクションは耇数化圢匏の䟋で、単数ず耇数のバヌゞョン英語でmsgidずしお、察応する翻蚳を msgstr 0ず1ずしお衚瀺しおいる耇数圢ルヌルで指定された数字に続く。ここで、文字列眮換も䜿われおいるので、数字は%dを䜿っお文の䞭で盎接参照するこずができる。耇数圢は垞に2぀のmsgid(単数ず耇数) があるので、翻蚳の゜ヌスずしお耇雑な蚀語を甚いないこずをお勧めする。

l10n のキヌに関する議論

お気づきかもしれないが、我々は英語の実際の文を゜ヌスIDずしお䜿っおいる。その msgid はすべおの.po ファむルで同じように䜿われおいる。これは぀たり、他の蚀語も同じフォヌマットず同じmsgidフィヌルドを持っおいるが、msgstr行は翻蚳されおいるずいうこずだ。

翻蚳キヌに関しおいえば、2぀の䞻芁な「流掟」がある。

  1. 実際の文ずしおの msgid. 䞻な利点は䞋蚘の通り
    • 特定の蚀語で翻蚳されおいない゜フトりェアがある堎合、衚瀺されるキヌは䜕らかの意味を保持しおいる。䟋英語からスペむン語に翻蚳したが、フランス語に翻蚳するのに助けを必芁ずする堎合、フランス語の文が欠けた新しいペヌゞを公開するず、そのりェブサむトの䞀郚が代わりに英語で衚瀺される。
    • 翻蚳者にずっおは、䜕が起こっおいるかを理解し、msgid に基づいお適切な翻蚳を行う方がはるかに簡単だ。
    • ある蚀語゜ヌス蚀語に察しお、「無料の」l10n を提䟛する。
    • 唯䞀の欠点は、実際のテキストを倉曎する必芁がある堎合、耇数の蚀語ファむルで同じ msgid を眮換する必芁があるこずだ。
  2. 䞀意な構造化されたキヌずしおの msgid これはアプリケヌション内の文の圹割を、構造化された方法で蚘述する。これには、文字列の内容ではなく、文字列が配眮されたテンプレヌト、あるいはその䞀郚が含たれおいる。
    • テキストの内容をテンプレヌトのロゞックから分離しお、コヌドを敎理するにはすばらしい方法だ。
    • しかしながら、翻蚳者がコンテキストを芋逃す問題が発生するかもしれない。゜ヌス蚀語ファむルは、他の翻蚳の基瀎ずしお必芁になる。䟋理想的な圢では、開発者は en.po ファむルを管理し、翻蚳者は、䟋えば fr.po に䜕を曞くかを理解するためにそれを読む。
    • 翻蚳がないず、意味のないキヌが画面に衚瀺される(前述の翻蚳されおいないフランス語のペヌゞでは、Hello there, User! ではなく、top_menu.welcome が衚瀺される)。 公開前に無理やり翻蚳を完成させるのはよいこずだが、翻蚳の問題は画面䞊で非垞にひどいものになるだろう。しかしながら、ラむブラリの䞭には、他のアプロヌチず同様の振る舞いをも぀特定の蚀語を「フォヌルバック」ずしお指定するオプションが含たれおいるものもある。

Gettextのマニュアル では、通垞、翻蚳者やナヌザがトラブルに芋舞われた堎合に簡単に察凊できるように、最初のアプロヌチを採甚しおいる。なのでここでもそのような䜜業を行う。しかしながら、Symfonyドキュメント では、キヌワヌドに基づく翻蚳を採甚しおいお、テンプレヌトに圱響を及がすこずなくすべおの翻蚳を個別に倉曎できるようにしおいる。

お決たりの䜿い方

䞀般的なアプリケヌションでは、ペヌゞに静的なテキストを曞く際にGettext関数を甚いる。これらの文は、.po ファむルに珟れ、翻蚳され、.mo ファむルにコンパむルされ、実際のむンタフェヌスをレンダリングを行う際にGettext によっお䜿われる。なので、これたで議論しおきた内容を順を远っお、サンプルコヌドでたずめおみよう。

1. いく぀かの異なる gettext 呌び出しを含む、サンプルテンプレヌトファむル

<?php include 'i18n_setup.php' ?>
<div id="header">
    <h1><?=sprintf(gettext('Welcome, %s!'), $name)?></h1>
    <!-- 可読性のためだけに、こういう颚にコヌドをむンデントしおいる -->
    <?php if ($unread): ?>
        <h2><?=sprintf(
            ngettext('Only one unread message',
                     '%d unread messages',
                     $unread),
            $unread)?>
        </h2>
    <?php endif ?>
</div>

<h1><?=gettext('Introduction')?></h1>
<p><?=gettext('We\'re now translating some strings')?></p>

2. サンプルセットアップファむル(䞊で甚いた i18n_setup.php)、正しいロケヌルの遞択や、Gettext の蚭定を行う

<?php
/**
 * 指定された $locale を、プロゞェクトでサポヌトしおいるかを確認する
 * @param string $locale
 * @return bool
 */
function valid($locale) {
   return in_array($locale, ['en_US', 'en', 'pt_BR', 'pt', 'es_ES', 'es']);
}

//参考情報ずしお、゜ヌスずなる/デフォルトのロケヌルを蚭定
$lang = 'en_US';

if (isset($_GET['lang']) && valid($_GET['lang'])) {
    // ロケヌルはク゚リストリングで倉曎できる
    $lang = $_GET['lang'];    //無害化すべき
    setcookie('lang', $lang); //再利甚できるように、cookie に保存
} elseif (isset($_COOKIE['lang']) && valid($_COOKIE['lang'])) {
    // cookie が存圚しおいる堎合、その倀を䜿う
    $lang = $_COOKIE['lang']; //無害化すべき
} elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
    // デフォルト: ナヌザヌが受け入れるずブラりザが蚀っおいる蚀語を探す
    $langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
    array_walk($langs, function (&$lang) { $lang = strtr(strtok($lang, ';'), ['-' => '_']); });
    foreach ($langs as $browser_lang) {
        if (valid($browser_lang)) {
            $lang = $browser_lang;
            break;
        }
    }
}

// 芋぀かった蚀語を指定しお、グロヌバルなシステムロケヌルをここで定矩する
putenv("LANG=$lang");

// こうしおおくず、たずえば日付関数(LC_TIME) や 通貚のフォヌマット(LC_MONETARY) で圹立぀かも
setlocale(LC_ALL, $lang);

// Gettext に ../locales/<lang>/LC_MESSAGES/main.mo を探すように指瀺する
bindtextdomain('main', '../locales');

// ファむルを読み出すずきに、どの゚ンコヌディングを䜿うかを指瀺する
bind_textdomain_codeset('main', 'UTF-8');

// アプリケヌションに远加で、翻蚳のドメむンがある堎合、既に説明したように、ここでバむンドしおおく
bindtextdomain('forum', '../locales');
bind_textdomain_codeset('forum', 'UTF-8');

// gettext() がコヌルされたずきに、応答するデフォルトのドメむンをここで指定する
textdomain('main');

// 以䞋のようにするず、main.mo ではなく、forum.mo にある文字列を探すようになる
// echo dgettext('forum', 'Welcome back!');
?>

3. 最初に実行するための翻蚳の準備

Gettext が独自フレヌムワヌクの i18n パッケヌゞに察しお持っおいる倧きな利点の぀は、広範で匷力なファむルフォヌマットだ。「ああ、Gettext のフォヌマットを理解し、手で線集するこずは非垞に困難だ。単玔な配列の方が簡単だ」間違いなく、Poedit のようなアプリケヌションが 倧いに 助けになる。圌らのりェブサむトからプログラムを入手するこずができ、すべおのプラットフォヌムで無料で利甚するこずができる。これは、簡単に䜿えるツヌルであり、同時に非垞に匷力なツヌルである - なぜなら、Gettext が䜿えるすべおの機胜を䜿っおいるからだ。このガむドは PoEdit 1.8 に基づいおいる。

最初の実行では、メニュヌから、「File > New 」を遞択する必芁がある。蚀語は盎接入力するように求められる。ここで翻蚳したい蚀語を遞択フィルタするか、en_US や pt_BR のような、前述した圢匏を䜿甚できる。

次に、先に説明したディレクトリ構造を䜿っおファむルを保存する。さらに、「Extract from sources」をクリックし、ここで抜出タスクず翻蚳タスクの様々な蚭定を行う。「Catalog > Properties」で、埌からこれらすべおを芋぀けるこずができるようになる。

これらのポむントを蚭定した埌、PoEditは゜ヌスファむルをスキャンしおロヌカラむズの呌び出しを党お掗い出す。スキャンするたびに、PoEdit は怜出されたものず゜ヌスファむルから削陀された内容のサマリを衚瀺する。新しい゚ントリは空のたた倉換テヌブルに入力され、ロヌカラむズされたバヌゞョンの文字列を入力し始める。それが保存されるず、.mo ファむルは同じフォルダに再び)コンパむルされ、プロゞェクトが囜際化される。

4. 翻蚳文字列

すでにお気づきかもしれないが、ロヌカラむズされた文字列には、2぀の䞻なタむプがある。単数のものずそれを耇数圢にしたものだ。1぀目は、゜ヌスずロヌカラむズされた文字列の2぀のボックスがあるだけだ。Gettext/Poedit には゜ヌスファむルを倉曎する暩限がないので、゜ヌス文字列は倉曎できない。゜ヌス自䜓を倉曎しお、再スキャンする必芁がある。ヒント翻蚳行を右クリックするず、その文字列が䜿われおいる゜ヌスファむルず行のヒントが衚瀺される。 他方、耇数圢文字列には2぀の゜ヌス文字列を衚瀺する2぀のボックスず、様々な最終圢匏が蚭定可胜なタブが含たれおいる。

゜ヌスを倉曎しお翻蚳を曎新する必芁がある堎合はい぀でも、Refresh をクリックするだけで Poedit はコヌドを再スキャンし、存圚しない゚ントリを削陀し、倉曎された゚ントリをマヌゞしお新しい゚ントリを远加する。あなたが行った他の翻蚳に基づいお、いく぀かの翻蚳を掚枬しようずする堎合もある。それらの掚論ず倉曎された゚ントリには「Fuzzy」マヌカヌが付䞎され、怜蚌が必芁であるこずが瀺され、リスト䞭に金色で衚瀺される。もし翻蚳チヌムがいお、誰かが䞍確かなこずを曞こうずする堎合にも䟿利だ。Fuzzy をマヌクするだけで、他の誰かが埌からレビュヌしおくれるからだ。

最埌に、「View > Untranslated entries first」マヌクを぀けおおくこずをお勧めする。これは、゚ントリを忘れないようにするのに 倧いに 圹に立぀からだ。このメニュヌから、必芁に応じお、翻蚳者たちにコンテキストの情報を残すこずができる UI をオヌプンするこずもできる。

ヒントずコツ

キャッシュが問題を起こすかも

PHP を Apache 䞊のモゞュヌル(mod_php) ずしお実行しおいる堎合、.mo ファむルがキャッシュされる問題に盎面するかもしれない。これは最初に読み蟌たれた時に発生し、曎新するには、サヌバを再起動する必芁がある。Nginx ず PHP5 では通垞、翻蚳キャッシュを曎新するのに、数ペヌゞを曎新するだけでよく、PHP7 ではほずんど必芁ない。

远加のヘルパヌ関数

倚くの人が奜むやり方だが、gettext() の代わりに、_() を䜿う方が簡単だ。フレヌムワヌクに備わっおいる倚くのカスタム i18n ラむブラリも、倉換されたコヌドを短くするために t() に䌌たものを䜿っおいる。しかしながら、これはショヌトカットを備えた唯䞀の関数だ。ngettext() のための__()や_n()をプロゞェクトに远加したり、華矎な _r() を gettext() や sprintf()の呌び出しに远加したくなるかもしれない。php-gettextのGettext のような他のラむブラリでも、これらのようなヘルパヌ関数が提䟛されおいる。

そうした堎合、それらの新しい関数から文字列を抜出する方法をGettextナヌティリティに指瀺する必芁がある。しかし恐れる必芁はない。ずおも簡単だ。そうした指瀺は .po ファむルにあるフィヌルド、あるいは Poedit の蚭定画面で行う。゚ディタでは、そのオプションは「Catalog > Properties > Source keywords」の䞭にある。芚えおおいおほしいのは、Gettext は倚くの蚀語のためのデフォルト関数がすでにわかっおいるので、そのリストが空っぜのように芋えおも恐れる必芁はない、ずいうこずだ。特定の圢匏 に埓っお、これらの新しい関数の仕様を含める必芁がある。

これらの新しいルヌルを.po ファむルに含めたあず、新たにスキャンを実行するず、以前ず同様、簡単に新しい文字列が取り蟌たれる。

リファレンス

Back to Top

䟝存性の泚入

Wikipediaによるず、

䟝存性の泚入ずは゜フトりェアデザむンパタヌンの1぀である。䟝存関係を゜ヌスコヌドから排陀しお、実行時あるいはコンパむル時にその䟝存関係を倉曎できるようにする。

ずのこずだが、この説明は必芁以䞊に小難しく蚀っおいるように思える。 䟝存性の泚入ずはコンポヌネントに䟝存関係を枡せる仕組みのこずで、コンストラクタで泚入したりメ゜ッド呌び出しをしたりプロパティを蚭定したりずいった方法がある。 それだけのこずだ。

基本的な抂念

考えかたを説明するために、シンプルな䟋を瀺そう。现かいずころは手を抜いおいるけどね。

ここに Database クラスがある。こい぀がデヌタベヌスずやりずりするためには、䜕らかのアダプタヌが必芁だ。 そこで、コンストラクタの䞭でアダプタヌのむンスタンスを䜜っおいる。アダプタヌの名前を盎接指定しおね。 こんな曞きかただず Database クラスを単䜓でテストするのが難しくなるし、 このクラスがアダプタヌず密接に結び぀いおしたう。

<?php
namespace Database;

class Database
{
    protected $adapter;

    public function __construct()
    {
        $this->adapter = new MySqlAdapter;
    }
}

class MysqlAdapter {}

このコヌドを曞き換えお䟝存性の泚入を䜿うようにすれば、この䟝存関係を緩やかにできる。 ここでは、コンストラクタに䟝存性を泚入するこずにし、クラスを暪断しおプロパティを䜿えるようにするために コンストラクタのプロモヌション を䜿うこずにしよう:

<?php
namespace Database;

class Database
{
    public function __construct(protected MySqlAdapter $adapter)
    {
    }
}

class MysqlAdapter {}

これで、䟝存関係を倖郚から Database クラスに枡せるようになった。このクラス自身に䜜らせる必芁がなくなったんだ。 コンストラクタで指定する以倖にも、䟝存関係を匕数で受け取っおそれを蚭定するようなメ゜ッドを新たに䜜っおもいいし、 あるいは $adapter ずいう public プロパティを䜜っお、䟝存関係を盎接蚭定できるようにしおもいい。

耇雑な問題

これたでに䟝存性の泚入に぀いお調べたこずがある人なら、 “制埡の反転IoCInversion of Control” や “䟝存関係逆転の原則DIPDependency Inversion Principle” ずいった蚀葉に芋芚えがあるだろう。これらは耇雑な問題で、䟝存性の泚入によっお解決できるものだ。

制埡の反転

制埡の反転ずは、文字通り、システムの「制埡を反転」するこずだ。システム党䜓の制埡を、オブゞェクトから切り離したたたで行う。 䟝存性の泚入の文脈では、䟝存関係の制埡や䜜成を、システム内のどこか別の堎所でやるっおこずを意味する。

PHPのフレヌムワヌクでも、制埡の反転は実珟されおきた。でも、実際のずころ、䜕の制埡を反転しおいるのだろう。そしお、反転した結果、制埡はどこに行っおしたったのだろう。 たずえば、たいおいのMVCフレヌムワヌクには、あらゆるコントロヌラの芪になる基底コントロヌラが甚意されおいる。 そしお、それを継承しなければ䟝存関係にアクセスできない。 これはこれで制埡の反転だが、でも、䟝存関係を緩くしたずいうよりは、単玔に䟝存関係を別の堎所に移しただけのこずだ。

䟝存性の泚入を䜿えば、これをもっずすっきりず解決できる。䟝存関係が必芁になったずきに、必芁なものだけを泚入すればいい。 ハヌドコヌディングする必芁はない。

S.O.L.I.D.

単䞀責任の原則

単䞀責任の原則は、アクタヌず高レベルなアヌキテクチャヌに関するものだ。これは “クラスを倉曎する理由は、ひず぀だけであるべきである” ずいう原則だ。これは、個々のクラスは、゜フトりェアが提䟛する単䞀の機胜のみに぀いお責任を持぀べきであるずいうこずだ。このアプロヌチを採甚する最倧の利点は、再利甚性を高めるこずができるこずにある。我々のクラスがひず぀のこずだけをしおいれば、他のプログラムでもそれを倉曎するこずなく䜿うたたは再利甚するこずができる。

開攟/閉鎖原則

開攟/閉鎖原則(Open/Closed Principle) は、クラス蚭蚈ず機胜の拡匵に関するものだ。これは”゜フトりェアの芁玠(クラスやモゞュヌル、関数など)は、拡匵に察しおは開いおおり、修正に察しおは閉じおいるべきである” ずいう原則だ。これは、新しい機胜が必芁になった時は、既存のコヌドを倉曎せず、既存のコヌドを䜿っお新しいコヌドを曞けるようにクラスやモゞュヌル、関数を蚭蚈すべきずいうこずだ。実甚的な蚀い方をするず、むンタヌフェむスに埓っおクラスを実装し、特定のクラスではなく、むンタヌフェむスを䜿っおタむプヒントを付けるべきずいうこずだ。

このアプロヌチを採甚する最倧の利点は、既存のコヌドを倉曎するこずなく、新しい機胜をサポヌトできるよう簡単に拡匵できるこずだ。こうするこずで、QA にかかる時間を削枛でき、アプリケヌションを実質的に壊しおしたうリスクや、悪い圱響を避けるこずができる。さらにこうするこずで、新しいコヌドを玠早く、自信をもっおデプロむできるようになる。

リスコフの眮換原則

リスコフの眮換原則は、サブタむピングず継承に関するものだ。これは “子クラスは、絶察に芪クラスの型定矩を壊しおはいけない” ずいう原則だ。Robert C. Martin の蚀葉を借りれば “サブタむプは、基底型を代替できなければならない” ずいうこずだ。

䟋をあげよう。embed() メ゜ッドを定矩したむンタヌフェむス FileInterface があるずする。そしお、このむンタヌフェむスを実装したクラス Audio ず Video があるずしお、embed() の䜿い方は垞に期埅通りであるずしよう。埌になっお、FileInterface を実装した PDF や Gist クラスを䜜るこずになっおも、embed() メ゜ッドが䜕をするかを我々はわかっおいるはずだ。このアプロヌチを採甚する最倧の利点は、柔軟性があり、簡単に蚭定可胜なプログラムを䜜れるこずだ。なぜなら、オブゞェクトの型 (ここでは FileInterface) を別の型に倉曎しおも、プログラムを倉曎する必芁はないからだ。

むンタヌフェむス分離の原則

むンタヌフェむス分離の原則(ISP)ずは、ビゞネスロゞックずクラむアントの通信に関するものだ。これは、”どのクラむアントも、自分が䜿わないメ゜ッドに䟝存しおはいけない” ずいう原則だ。これは、党おのクラスが埓い、実装する必芁がある単䞀のモノリシックなむンタヌフェむスを持぀のではなく、小さな、特定の抂念を持぀むンタヌフェむスの集合を提䟛し、クラスはそれらをひず぀以䞊実装すべきずいうこずだ。

䟋をあげよう。Car や Bus クラスは steeringWheel() メ゜ッドに関心があるずしよう。䞀方で、Motorcycle や Tricycle クラスはそのメ゜ッドに関心がないずする。反察に Motorcycle や Tricycle は handlebars() メ゜ッドに関心があるが、Car や Bus メ゜ッドはそのメ゜ッドに関心がないずする。この堎合、これら党おの車䞡の型が steeringWheel() ず handlebars() を䞡方サポヌトするために、これらのメ゜ッドを実装する必芁はない。むンタヌフェむスを分割すべきだ。

䟝存関係逆転の原則

䟝存関係逆転の原則は、耇数の具象クラスの間では、密結合しないようにする原則だ。これを守るず、異なるクラスを枡すこずで、新しい機胜を利甚できるようになる。 これは 「抜象に䟝存しろ。具象に䟝存するな」 ずいう原則だ。 簡単に蚀うず、䟝存関係はむンタヌフェむスや抜象クラスに察しお蚭定すべきものであり、それを実装したクラスに察しお蚭定しおはいけないっおこず。 先ほどの䟋をこの原則に沿っお曞き盎すず、こんなふうになる。

<?php
namespace Database;

class Database
{
    public function __construct(protected AdapterInterface $adapter)
    {
    }
}

interface AdapterInterface {}

class MysqlAdapter implements AdapterInterface {}

これで Database クラスは、具象クラスではなくむンタヌフェむスに䟝存するように倉わった。で、いったい䜕がうれしいんだろう。

こんな堎面を考えおみよう。君は今、ずあるチヌムの䞀員ずしお䜜業をしおいる。アダプタヌを䜜っおいるのは別のメンバヌだ。 最初の䟋だず、その人がアダプタヌを完成させるたでは、自分のコヌドのナニットテストのモックを䜜れない。 むンタヌフェむスに䟝存するようにした新しいバヌゞョンだず、そのむンタヌフェむスを䜿っおモックを䜜るこずができる。 同僚が䜜るアダプタヌもそのむンタヌフェむスに沿っおいるずわかっおいるからだ。

そんなこずより、もっずすばらしいメリットもある。こっちの方匏のほうが、コヌドがずっずスケヌラブルになるんだ。 仮に将来、別のデヌタベヌスに移行するこずになったずしよう。 そんな堎合でも、このむンタヌフェむスを実装した新しいアダプタヌを曞いたらそれでおしたいだ。 それ以倖は䜕もいじる必芁がない。 新しいアダプタヌがきちんず決たりごずに埓っおいるずいうこずを、むンタヌフェむスが保蚌しおくれるからだ。

コンテナ

DIコンテナに぀いおたず知っおおくべきなのは、DIコンテナを䜿っおさえいれば「䟝存性の泚入」ができるわけではないっおこずだ。 DIコンテナは、䟝存性の泚入を実珟するための䟿利な道具ずしお䜿える。 でも、䜿い方をミスっお、サヌビスロケヌションずいうアンチパタヌンを䜜っおしたっおいるこずも倚い。 DIコンテナをサヌビスロケヌタヌずしおクラスに組み蟌んでしたうず、 䟝存関係を別の堎所に移そうずしおいたはずなのに、よりき぀い䟝存関係を䜜り蟌むこずになる。 おたけにそのコヌドはわかりにくくなっおしたうし、テストもしづらくなる。

いたどきのフレヌムワヌクにはたいおいDIコンテナが甚意されおいお、䟝存関係をコヌド以倖のずころで蚭定できる。 芁するに、アプリケヌションのコヌドがすっきりず曞けお、フレヌムワヌク本䜓ずあたり密接に぀ながりすぎないようにできるずいうこず。

あわせお読みたい

Back to Top

デヌタベヌス

PHP のコヌドを曞いおいるず、情報を保存するためにデヌタベヌスを䜿うこずが倚くなる。 デヌタベヌスを操䜜するには、いく぀かの方法がある。 PHP 5.1.0 の時代たでは 、おすすめの方法は mysqli、pgsql、mssql などのネむティブドラむバを䜿うこずだった。

このデヌタベヌスしか䜿わないよっおいうのならネむティブドラむバもいい。 でもたずえば、MySQL を䜿っおいるけど䞀郚は MSSQL であるずか、 Oracle にも぀なぐこずがあるずか、そんな堎合は同じドラむバでは察応できない。 そしお、デヌタベヌスが倉わるたびに新しい API を芚えないずいけないこずになる。 ばかげた話だ。

MySQL 甚の拡匵モゞュヌル

PHP 甚の mysql 拡匵モゞュヌルは既に思いっきり叀くなっおいお、これらの拡匵モゞュヌルがその埌継になっおいる。

mysql 拡匵モゞュヌルの開発は倧昔に終了しおいるだけでなく、PHP 7.0.0で公匏に削陀されおいる 。

いた䜿っおいるモゞュヌルがどれなのかを知りたいなら、わざわざ php.ini の蚭定を調べるたでもない。 お奜みの゚ディタヌで mysql_* を怜玢しおみればいい。 mysql_connect() ずか mysql_query() みたいな関数がヒットしたら、 mysql モゞュヌルを䜿っおるっおこずだ。

圓面は PHP 7.x 以降を䜿う぀もりがないのだずしおも、今ちゃんず考えおおかないず、いざずいうずきに倧倉なこずになる。 いちばんいいのは、通垞の開発スケゞュヌルの䞭で、mysql モゞュヌルを䜿っおいる郚分を mysqli や PDO に埐々に眮き換えおいくこずだ。 そうすれば、埌になっおあせらずにすむ。

** mysql から mysqli ぞの移行に぀いお、単に「mysql_* を mysqli_* に眮換すればOK」などず曞いおいるような蚘事には甚心するこず。話を単玔化しすぎおいるだけではなく、mysqli ならではの利点パラメヌタのバむンドなど。これは PDO でも甚意されおいるの掻甚ができなくなっおしたう。 **

PDO 拡匵モゞュヌル

PDO はデヌタベヌスずの接続を抜象化するラむブラリだ。PHP 5.1.0 以降に組み蟌たれおいお、 いろんなデヌタベヌスを同じむンタヌフェむスで扱える。 MySQLを䜿うコヌドもSQLiteを䜿うコヌドも、基本的には同じようになるっおこずだ。

<?php
// PDO + MySQL
$pdo = new PDO('mysql:host=example.com;dbname=database', 'user', 'password');
$statement = $pdo->query("SELECT some_field FROM some_table");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['some_field']);

// PDO + SQLite
$pdo = new PDO('sqlite:/path/db/foo.sqlite');
$statement = $pdo->query("SELECT some_field FROM some_table");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['some_field']);

PDO は、SQL のク゚リをデヌタベヌスにあわせお倉換するものではないし、 もずもず存圚しない機胜を゚ミュレヌトするものでもない。 玔粋に、いろんなデヌタベヌスに同じ API で接続するためのものだ。

もっず倧切なこずは、PDO を䜿えば、倖郚からの入力 (ID など) を安党に SQL ク゚リに埋め蟌めるずいうこずだ。デヌタベヌスぞの SQL むンゞェクション攻撃を心配しなくおもよくなる。 そのためには、PDO ステヌトメントずバむンド倉数を䜿えばよい。

数倀の ID をク゚リ文字列ずしお受け取る PHP スクリプトを考えおみよう。 枡された ID を䜿っお、デヌタベヌスからナヌザヌ情報を取り出す。 最初に瀺すのは 悪い方法 だ。

<?php
$pdo = new PDO('sqlite:/path/db/users.db');
$pdo->query("SELECT name FROM users WHERE id = " . $_GET['id']); // <-- ダメ、れッタむ

こんな恐ろしいコヌドを曞いちゃいけない。 これは、ク゚リ文字列のパラメヌタを SQL に盎に埋め蟌んでいるこずになる。 あっずいう間に SQLむンゞェクション 攻撃を食らうだろう。 どこかのずるがしこい攻撃者が id に枡す内容をひず工倫しお http://domain.com/?id=1%3BDELETE+FROM+users みたいな URL を呌んだずしよう。 このずき倉数 $_GET['id'] の内容は 1;DELETE FROM users ずなり、党ナヌザヌが消えおしたうこずになる こんな曞き方ではなく、PDO のバむンド倉数で ID を受け取らないずいけない。

<?php
$pdo = new PDO('sqlite:/path/db/users.db');
$stmt = $pdo->prepare('SELECT name FROM users WHERE id = :id');
$id = filter_input(INPUT_GET, 'id', FILTER_SANITIZE_NUMBER_INT); // <-- たずデヌタのフィルタリングを行う ([デヌタのフィルタリング](#data_filtering) を参照)。特に INSERT や UPDATE などで重芁
$stmt->bindParam(':id', $id, PDO::PARAM_INT); // <-- PDOが自動的にSQLの゚スケヌプ凊理をする
$stmt->execute();

これが正しい方法だ。この䟋では、PDO ステヌトメントでバむンド倉数を䜿っおいる。 倖郚からの入力である ID が゚スケヌプされおからデヌタベヌスに枡るので、 SQL むンゞェクション攻撃を受けるこずがなくなる。

INSERT や UPDATE などの曞き蟌み操䜜の堎合は、たず デヌタをフィルタリング するこずが倧切だ。 その埌で、その他 (HTML タグや JavaScript など) の゚スケヌプを行う。 PDO はあくたでも SQL 甚の゚スケヌプを行うものであり、アプリケヌション党䜓の面倒をみおくれるわけではない。

あず、デヌタベヌスのコネクションはリ゜ヌスを䜿うずいうこずにも気を぀けよう。 コネクションを明瀺的に閉じるこずを忘れたせいでリ゜ヌスを食い぀ぶしおしたうなんお話は珍しくない。 ずはいえ、これは別にPHPに限った話でもないけどね。 PDOを䜿っおいる堎合は、オブゞェクトぞの参照をすべお削陀しお(Nullを代入するなどしお) オブゞェクトを砎棄しおしたえば、暗黙のうちにコネクションを閉じるこずが保蚌される。 オブゞェクトを明瀺的に砎棄しない堎合は、スクリプトの実行が終わった時点でPHPが自動的に接続を閉じる。 もちろん、持続的接続を䜿っおいる堎合は別だ。

デヌタベヌスずのやりずり

PHPを勉匷し始めたばかりの開発者がやっおしたいがちなのが、デヌタベヌスずのやりずりず画面衚瀺のロゞックをごちゃたぜにしおしたうこずだ。 たずえば、こんなコヌドになる。

<ul>
<?php
foreach ($db->query('SELECT * FROM table') as $row) {
    echo "<li>".$row['field1']." - ".$row['field1']."</li>";
}
?>
</ul>

これは、あらゆる意味でよろしくない。 たず䜕ず蚀っおも、デバッグしづらいし、テストもしづらいし、読みづらい。 あず、䜕も制限をかけおいない堎合に、倧量のフィヌルドを出力しおしたうこずになる。

同じこずをもっずすっきり行う方法はいろいろある。OOPが奜きな人向けのやりかたもあれば 関数型プログラミングが奜きな人向けのやりかたもある。 が、たずは、分離するこずからはじめよう。

これが第䞀歩だ。

<?php
function getAllFoos($db) {
    return $db->query('SELECT * FROM table');
}

$results = getAllFoos($db);
foreach ($results as $row) {
    echo "<li>".$row['field1']." - ".$row['field1']."</li>"; // BAD!!
}

少しはマシになった。この二぀を別々のファむルに分けおしたえば、きれいに分離できるだろう。

次に、このメ゜ッドを保持するクラスを甚意する。「モデル」だ。 そしお、シンプルな .php ファむルをもうひず぀䜜っお、そこに画面衚瀺ロゞックを入れる。「ビュヌ」だ。 これで、䜕ずなく MVC っぜくなった。これは、倚くの フレヌムワヌク で䜿われおいる、OOPのアヌキテクチャだ。

foo.php

<?php
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8mb4', 'username', 'password');

// モデルを読み蟌む
include 'models/FooModel.php';

// むンスタンスを䜜る
$fooModel = new FooModel($db);
// Fooのリストを䜜る
$fooList = $fooModel->getAllFoos();

// ビュヌを衚瀺する
include 'views/foo-list.php';

models/FooModel.php

<?php
class FooModel
{
    public function __construct(protected PDO $db)
    {
    }

    public function getAllFoos() {
        return $this->db->query('SELECT * FROM table');
    }
}

views/foo-list.php

<?php foreach ($fooList as $row): ?>
    <li><?= $row['field1'] ?> - <?= $row['field1'] ?></li>
<?php endforeach ?>

本質的にこれは、今どきのフレヌムワヌクがやっおいるこずず同じだ。それを手䜜業でやっおみた。 毎回こんなこずをする必芁はないかもしれないが、画面衚瀺ずデヌタベヌス操䜜を混圚させすぎるず、 ナニットテスト をしたくなったずきにやっかいな問題が発生しおしたう。

抜象化レむダヌ

倚くのフレヌムワヌクは、デヌタベヌスの抜象化レむダヌを甚意しおいる。PDOを利甚しおいるものもあれば、そうでないものもある。 あるデヌタベヌスには存圚するけれども別のデヌタベヌスには存圚しない機胜などを゚ミュレヌトするために、 ク゚リヌをPHPのメ゜ッドでラップしたりするものだ。 PDOではデヌタベヌスぞの接続の抜象化しかしないが、フレヌムワヌクの抜象化レむダヌは、それ以䞊のこずをしおくれる。 もちろんそれなりのオヌバヌヘッドが発生するだろう。 でも、MySQLでもPostgreSQLでもSQLiteでも動くようなアプリケヌションを曞いおいるのなら、 倚少のオヌバヌヘッドを割り匕いおでも、すっきりしたコヌドを曞けるほうがうれしいだろう。

以䞋の抜象化レむダヌは、 PSR-0 や PSR-4 で定められた暙準名前空間に埓っおいる。 これらはアプリケヌションを問わずに利甚できる。

Back to Top

テンプレヌト

テンプレヌトは、コントロヌラヌやドメむンロゞックを、プレれンテヌションロゞックから切り離すための䟿利な手段だ。 テンプレ—トには、アプリケヌションで䜿うHTMLを含めるこずが倚いが、それ以倖のフォヌマットXMLなどを含めるこずもある。 テンプレヌトのこずを「ビュヌ」ず呌ぶこずもある。いわゆる model–view–controller (MVC) パタヌンの、二番目の芁玠 の䞀郚 だ。

メリット

テンプレヌトを䜿う䞻なメリットは、画面に衚瀺する内容をアプリケヌションから切り離せるこずだ。 テンプレヌトは、フォヌマット枈みのコンテンツを衚瀺するずいう責務だけを負う。 デヌタを怜玢したり、デヌタベヌスに保存したりなどずいった、雑倚なタスクは気にしない。 このおかげで、すっきりしたリヌダブルなコヌドが曞けるようになる。チヌムで開発する際などには、これが特に有甚だ。 開発者はサヌバヌ偎のコヌドコントロヌラやモデル、そしおデザむナヌはクラむアント偎のコヌドマヌクアップ などずいう䜜業分担をしやすくなる。

テンプレヌトには、プレれンテヌションのコヌドの構造を改善するずいう効果もある。 テンプレヌトは䞀般的に「views」などのフォルダにたずめられお、それぞれ個別のファむルになっおいるこずが倚い。 こうしおおけばコヌドの再利甚がしやすくなる。倧芏暡なコヌドブロックを、小さめの再利甚しやすいパヌツパヌシャルず呌ばれるこずもあるに分割できるからだ。 たずえば、サむトのヘッダやフッタをテンプレヌトにしおおけば、各ペヌゞのテンプレヌトにそれをむンクルヌドできるようになる。

利甚するラむブラリによっおは、テンプレヌトを䜿うこずで、よりセキュリティを確保できるようにもなる。 ナヌザヌが䜜るコンテンツを自動的に゚スケヌプしおくれたりする機胜を持぀ようなテンプレヌトが、それにあたる。 さらに、サンドボックス機胜を提䟛するラむブラリもある。これは、デザむナヌが、あらかじめ蚱可された倉数ず関数しか利甚できないようにする仕組みだ。

プレヌンなPHPによるテンプレヌト

プレヌンなPHPによるテンプレヌトずは、単にPHPのコヌドを䜿ったテンプレヌトずいう意味だ。 ごく自然な遞択肢だずも蚀える。そもそもPHP自䜓がテンプレヌト蚀語だし。 あ、これっお単に、PHPのコヌドをHTMLずかにも埋め蟌めるよねっおいう以䞊の深い意味はないからね。 PHPの開発者にずっおは、新しい構文を芚えずに枈むずいうメリットがある。 どんな関数が䜿えるのかもわかっおいるし、ふだんPHPを曞いおいる゚ディタのシンタックスハむラむトや 自動補完機胜も、そのたた䜿える。 その䞊、プレヌンなPHPのテンプレヌトは高速であるこずが倚い。コンパむルが䞍芁だからだ。

いたどきのPHPフレヌムワヌクは、たいおい䜕らかの仕組みのテンプレヌトシステムを持っおいる。 その倚くでデフォルトになっおいるのが、プレヌンPHPによるテンプレヌトだ。 フレヌムワヌク以倖では、PlatesやAura.View ずいったラむブラリがプレヌンPHPテンプレヌトを䜿いやすくしおくれる。継承やレむアりト、拡匵などの䟿利なテンプレヌト機胜を甚意しおくれるんだ。

プレヌンPHPテンプレヌトのシンプルな䟋

Plates ラむブラリを䜿った。

<?php // user_profile.php ?>

<?php $this->insert('header', ['title' => 'User Profile']) ?>

<h1>User Profile</h1>
<p>Hello, <?=$this->escape($name)?></p>

<?php $this->insert('footer') ?>

プレヌンPHPテンプレヌトで継承を䜿う䟋

Plates ラむブラリを䜿った。

<?php // template.php ?>

<html>
<head>
    <title><?=$title?></title>
</head>
<body>

<main>
    <?=$this->section('content')?>
</main>

</body>
</html>
<?php // user_profile.php ?>

<?php $this->layout('template', ['title' => 'User Profile']) ?>

<h1>User Profile</h1>
<p>Hello, <?=$this->escape($name)?></p>

コンパむル圢匏のテンプレヌト

PHPはオブゞェクト指向蚀語ずしお成熟しおきおはいるものの、テンプレヌト蚀語ずしおは いたいち だ。 コンパむル圢匏のテンプレヌト、たずえば Twig や Brainy や Smarty* が、この穎を埋めおくれる。テンプレヌトに特化した、新しい構文を甚意しおくれるんだ。 自動゚スケヌプから継承や制埡構文たで、コンパむル圢匏のテンプレヌトは、いかに読み曞きしやすく、安心しお䜿えるかを重芖しお䜜られおいる。 さらに、コンパむル圢匏のテンプレヌトは、別の蚀語でさえも䜿うこずができる。Mustache がそのよい䟋だ。 テンプレヌトをコンパむルする時間がかかるので、倚少はパフォヌマンスに圱響する。 しかし、適切にキャッシュをすれば、その圱響は埮々たるものだ。

*Smartyには自動゚スケヌプ機胜があるけど、これはデフォルトでは無効になっおいる。

コンパむル圢匏のテンプレヌトのシンプルな䟋

Twig ラむブラリを䜿った。

{% include 'header.html' with {'title': 'User Profile'} %}

<h1>User Profile</h1>
<p>Hello, {{ name }}</p>

{% include 'footer.html' %}

コンパむル圢匏のテンプレヌトで継承を䜿う䟋

Twig ラむブラリを䜿った。

// template.html

<html>
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>

<main>
    {% block content %}{% endblock %}
</main>

</body>
</html>
// user_profile.html

{% extends "template.html" %}

{% block title %}User Profile{% endblock %}
{% block content %}
    <h1>User Profile</h1>
    <p>Hello, {{ name }}</p>
{% endblock %}

あわせお読みたい

蚘事やチュヌトリアル

ラむブラリ

Back to Top

゚ラヌず䟋倖凊理

゚ラヌ

䟋倖凊理を重芖するプログラミング蚀語では、䜕か問題が起こったらすぐに䟋倖を投げる。 それはそれでいいこずではあるが、PHPはそうではなく、「䟋倖凊理も䜿える」プログラミング蚀語だ。 PHPには䟋倖凊理の仕組みがあるし、コアの䞭でもオブゞェクトを扱うずきには䟋倖凊理を行うこずが増えおいる。 でも、PHPは基本的に、よっぜど臎呜的な゚ラヌが発生しない限りは䜕があろうず凊理を続行しようずする。

たずえば、こんなコヌドを考えおみよう。

$ php -a
php > echo $foo;
Notice: Undefined variable: foo in php shell code on line 1

単玔にnoticeレベルの゚ラヌになるだけで、PHPはそのたた凊理を続行する。 䟋倖凊理を重芖する䞖界からやっおきた人にずっおは、これは少しキモいず思うかもしれないね。 たずえばPythonなら、未定矩の倉数を参照しようずするず、䟋倖が発生する。

$ python
>>> print foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined

実際の違いは、こういうこずだ。 Pythonは、些现なこずにたでこだわるこずで、プログラマヌが䜙蚈な心配「もし○○だったら、その堎合は 」ず考えたり、゚ッゞケヌスを考慮したりなど をせずに枈むようにしおいる。 䞀方PHPは、どうしようもない゚ラヌが発生しないかぎりは、䞀応゚ラヌを報告したうえで凊理を続行する。

゚ラヌの深刻床

PHPの゚ラヌは、䜕段階かの深刻床レベルに別れおいる。PHPでよく䜿われるメッセヌゞの圢匏は、 ゚ラヌerrorず泚意noticeそしお譊告warningだ。 それぞれ別々の深刻床レベルが蚭定されおいお、 E_ERROR、E_NOTICE、そしお E_WARNING になる。 「゚ラヌ」は実行時の臎呜的な問題で、ふ぀うはコヌドの曞きかたがたずいせいで発生する。 これは修正しなければいけない。ずいうのも、これが発生するずPHPの実行がそこで止たっおしたうからだ。 「泚意」は助蚀みたいなもので、問題を起こす可胜性があるスクリプトを実行したずきに発生する。 スクリプトの実行は止たらない。 「譊告」は臎呜的ではない問題で、これもスクリプトの実行は止たらない。

もうひず぀、コンパむル時に発生する E_STRICT ずいう圢匏のメッセヌゞもある。 これは、盞互運甚性や将来のバヌゞョンのPHPずの互換性を考えたずきに、コヌドを曞き換えたほうがいいず提案するためのメッセヌゞだ。

PHPの゚ラヌ報告の挙動の倉曎

゚ラヌ報告の挙動は、PHPの蚭定で倉曎するこずもできるしPHPの関数で倉曎するこずもできる。 組み蟌みの関数 error_reporting() に゚ラヌレベル定数を枡せば、そのスクリプトの実行䞭に どのレベルの゚ラヌ凊理をするのかを蚭定できる。 たずえば、゚ラヌ(error)ずか譊告(warning)は衚瀺させたいけれども、別に泚意(notice)は芋たくないずいう堎合は、こんなふうにすればいい。

<?php
error_reporting(E_ERROR | E_WARNING);

画面に衚瀺するかしないか(開発時に有効)だけでなく、ログに出力するかしないか(運甚時に有効)も制埡できる。 詳现は ゚ラヌレポヌト を参照。

むンラむンでの゚ラヌの抑制

「ここでの゚ラヌは無芖するこず」ずPHPに指瀺するこずもできる。そのずきに䜿うのが、 ゚ラヌ制埡挔算子 @ だ。この挔算子を䜕かの匏の前に曞くず、 その匏で発生したあらゆる゚ラヌは黙っお揉み消される。

<?php
echo @$foo['bar'];

これは、もし $foo['bar'] が存圚すればその内容を出力するが、仮に倉数 $foo やキヌ 'bar' が存圚しなくおも゚ラヌにはならない。単玔に null を返しお䜕も衚瀺しないだけだ。 もし゚ラヌ制埡挔算子がなかったら、 PHP Notice: Undefined variable: foo だずか PHP Notice: Undefined index: bar のような゚ラヌになる。

䞀芋、よさげな機胜だず感じるかもしれない。でも、これを䜿うず、あたり望たしくない代償を払うこずになる。 たず、PHPでは、 @ ぀きの匏は @ なしの匏よりも凊理効率が萜ちおしたう。 「早たった最適化は諞悪の根源だ」ずはいうものの、 もしパフォヌマンスを重芖するアプリケヌションやラむブラリを䜜っおいるのなら、 ゚ラヌ制埡挔算子がパフォヌマンスに及がす悪圱響を知っおおくべきだ。

次に、゚ラヌ制埡挔算子を䜿うず、発生した゚ラヌが 完党に 隠蔜されおしたう。 画面にも衚瀺されなければ、ログに曞き出されるこずもない。 たた、運甚䞭のPHPシステムの゚ラヌ制埡挔算子を無効にする仕組みはない。 今芋おいる゚ラヌが仮に些现なものだずしよう。だずしおも、それ以倖に無芖できない゚ラヌが発生するかもしれない。 そんな゚ラヌも、同様に隠蔜されおしたう。

゚ラヌ制埡挔算子を䜿わずにすむ道があるなら、その方向で考えるべきだ。 たずえばさっきのコヌドなら、こんなふうに曞き盎せばいい。

<?php
// Null Coalescing Operator
echo $foo['bar'] ?? '';

゚ラヌの抑制を䜿うのが理にかなっおいる堎面ずしお考えられるのは、 たずえば fopen() を䜿っおいおファむルの読み蟌みに倱敗した堎合だ。 もちろん実際に読み蟌む前にファむルがあるかどうかをチェックするだろうが、 そのチェックが終わっおから実際に fopen() で読み蟌むたでの間に ファむルが削陀されるかもしれないたあありえないだろうけど、可胜性はれロではない。 そんな堎合、 fopen() が false を返し、 そしお ゚ラヌも発生する。 ほんずはPHP偎で䜕ずかしおもらいたいずころだけれど、珟状でぱラヌを抑制するくらいしか手がない。

さっき、皌働䞭のPHPシステムでぱラヌ制埡挔算子を無効化できないずいったけれど、 実は、 Xdebug の蚭定 xdebug.scream を䜿えば、゚ラヌ制埡挔算子を無効化できる。 php.ini に、こんなふうに曞けばいい。

xdebug.scream = On

実行時に蚭定するなら、 ini_set 関数を䜿えばいい。

<?php
ini_set('xdebug.scream', '1')

この機胜が圹立぀のは、コヌドのデバッグ䞭など、゚ラヌから情報を読み取りたいずきだ。 screamを䜿うずきには気を぀けお、あくたでも䞀時的なデバッグ甚のツヌルずしお䜿うようにしよう。 ゚ラヌ制埡挔算子を無効にしたたたでは正垞に動かないずいうラむブラリっお、結構倚いよ。

ErrorException

PHPは、䟋倖が倧奜きな人たちにも察応したプログラミング蚀語だ。 ほんの数行のコヌドを足すだけで、䟋倖に察応できる。 基本的に、゚ラヌが発生したずきには、 ErrorException クラスを䜿っお「䟋倖」を投げればいい。 このクラスは、 Exception クラスを継承したものだ。

これは、SymfonyやLaravelみたいな今どきのフレヌムワヌクでもよく䜿われおいる方法だ。 これらのフレヌムワヌクのデバッグモヌド (開発モヌド) は、 スタックトレヌス をいい感じに衚瀺しおくれる。

゚ラヌや䟋倖の凊理や衚瀺をうたい具合にやおくれるパッケヌゞもある。 たずえば Whoops! もそのひず぀だ。 これはLaravelをデフォルトでむンストヌルするず぀いおくるものだけど、ほかのフレヌムワヌクでも䜿える。

開発䞭は、゚ラヌを䟋倖ずしお投げるようにしおおくず、その凊理をしやすくなる。 開発䞭にもし䟋倖が発生したら、それをcatch文でラップしお、その状況に察応する凊理を曞くこずもできる。 䟋倖をひず぀キャッチするたびに、アプリケヌションはほんの少しず぀頑䞈になっおいく。

もっず詳しいこずが知りたい、あるいは ErrorException クラスを䜿った゚ラヌ凊理に぀いお調べたいずいう人は、 ErrorException クラス のドキュメントを読もう。

䟋倖凊理

最近はやりのプログラミング蚀語には、たいおい䟋倖凊理の仕組みがある。でも PHP の人は芋萜ずしがちだ。 たずえば Ruby なんかは䟋倖凊理を䜿いたくっおいる。 HTTP リク゚ストに倱敗したずきもデヌタベヌスぞのク゚リが倱敗したずきも、画像ファむルが芋぀からなかったずきでさえも、 Ruby のプログラム (あるいはその䞭で䜿っおいる gem) は䟋倖を投げる。 なので、画面を芋ればすぐに「ああ、䜕か間違えたんだな」ずわかる。

PHP はそのあたりが極めお緩くお、たずえば file_get_contents() が倱敗しおも単に FALSE を返しお譊告を出すだけだ。叀いフレヌムワヌクの倚くもそんな感じだ。 たずえば CodeIgniter の堎合は、単に false を返しおログファむルにメッセヌゞを曞き出すだけ。 原因を知りたければ $this->upload->get_error() みたいなメ゜ッドを実行するこずになる。 䜕が問題かずいうず、たず゚ラヌが発生したのかどうかを自分で調べないずいけないこず。 そしお次に、゚ラヌ情報を取埗する方法をドキュメントで調べないずいけないこず。 もっずはっきりわかるようにしおくれたらいいのに。

別の問題もある。䜕かのクラスが゚ラヌを画面に投げっぱなしにしおそのたた終わるような堎合だ。 そんなこずをすれば、゚ラヌがあったずきにプログラム䞭で動的に察応するこずができなくなっおしたう。 そんな堎合は、゚ラヌではなく䟋倖を発生させないずいけない。 䟋倖にしおおけば開発者が゚ラヌに気づけるし、プログラムの䞭で察応できるようになる。 たずえばこんな感じだ。

<?php
$email = new Fuel\Email;
$email->subject('タむトル');
$email->body('ごきげんいかが');
$email->to('guy@example.com', '誰かさん');

try
{
    $email->send();
}
catch(Fuel\Email\ValidationFailedException $e)
{
    // 怜蚌に倱敗した
}
catch(Fuel\Email\SendingFailedException $e)
{
    // ドラむバがメヌルを送れなかった
}
finally
{
    // 䟋倖が発生しおもしなくおも、ここは必ず実行される
}

SPL の䟋倖

汎甚的な Exception クラスには、開発者がデバッグするためのコンテキスト情報がほずんど含たれおいない。 これを改善するには、特化型の Exception を䜜ればいい。぀たり、Exception クラスのサブクラスを䜜るっおこずだ。

<?php
class ValidationException extends Exception {}

こんなふうにすれば、catch ブロックを耇数甚意しおそれぞれの䟋倖で別の凊理をできるようになる。 その結果、自䜜の䟋倖クラスが 倧量に できあがっおしたうかもしれないが、 SPL 拡匵モゞュヌル が甚意する䟋倖クラスを䜿えば少しはたしになるだろう。

たずえば、マゞックメ゜ッド __call() を䜿っおいるずきに、無効なメ゜ッドを芁求されたずしよう。 暙準の Exception クラスを䜿うのは曖昧すぎるし、そのためだけに専甚の䟋倖クラスを䜜るのも䜕だし、 ずいう堎合には単に throw new BadMethodCallException; ずすればよい。

Back to Top

セキュリティ

今たで芋たPHPのセキュリティに関する資料の䞭でいちばんだったのは、Paragon Initiative による The 2018 Guide to Building Secure PHP Softwareだ。

りェブアプリケヌションのセキュリティ

PHP開発者は党員、Webアプリケヌションセキュリティの基本 を孊ぶべきだ。内容ずしおはだいたいこんな感じになる。 down into a handful of broad topics:

  1. コヌドずデヌタの分離
    • デヌタをコヌドずしお実行するずきにはSQLむンゞェクションやクロスサむトスクリプティングやファむルむンクルヌド攻撃の恐れがある
    • コヌドをデヌタずしお衚瀺するずきには情報挏掩の恐れがある (゜ヌスコヌドが晒されおしたったり、C蚀語の堎合ならアドレス空間配眮のランダム化もある ASLR)
  2. アプリケヌションロゞック
    • 認蚌・認可の制埡䞍党
    • 入力の怜蚌
  3. 運甚環境
    • PHPのバヌゞョン
    • サヌドパヌティのラむブラリ
    • OS
  4. 暗号化の匱点

䞖の䞭には悪い人たちがいお、あなたの曞いたりェブアプリケヌションもきっず狙われおいる。 必芁な察策をしお、りェブアプリケヌションのセキュリティを固めおおくこずが倧切だ。 ありがたいこずに、The Open Web Application Security Project (OWASP) の人たちが、既知のセキュリティ問題ずその察策をたずめおくれおいる。 セキュリティが気になる開発者は必読だ。 Padraic Bradyが曞いたSurvive The Deep End: PHP Security も、 りェブアプリケヌションセキュリティに関しおPHP向けに曞かれたよいドキュメントだ。

パスワヌドのハッシュ凊理

誰もがい぀かは、ログむン機胜を持぀ PHP アプリケヌションを曞くこずになる。 ナヌザヌ名ずパスワヌド (のハッシュ) をデヌタベヌスに保存しお、 ナヌザヌのログむン時にそれを䜿っお認蚌するずいうや぀だ。

デヌタベヌスにパスワヌドを保存するずきは、適切に ハッシュ するこずが倧切だ。 ハッシュず暗号化は たったく違うもの なのに、混同されるこずが倚い。

パスワヌドのハッシュは䞍可逆な操䜜で、ナヌザヌのパスワヌドに察しお䞀方通行で行う。 できあがる結果は固定長の文字列で、元には戻せない。 ぀たり、このハッシュを別のハッシュず比范すれば元の文字列どうしが䞀臎するかどうかは刀断できるが、 元の文字列が䜕だったかはわからないっおこずだ。 パスワヌドをハッシュせずにデヌタベヌスに保存しおいるず、 䞇䞀第䞉者に䞍正アクセスされた堎合に、すべおのナヌザヌアカりントが乗っ取られおしたう。

ハッシュず違っお暗号化は元に戻せる (鍵さえ手元にあればね)。 暗号化そのものは䜿う堎面を遞べば䟿利なものだけど、こずパスワヌドの保存に関しおはうたい手段ではない。

パスワヌドには個別に ゜ルト が必芁だ。ランダムな文字列をパスワヌドに付けおからハッシュするっおこず。 そうしおおけば、蟞曞攻撃から守れるし「レむンボヌテヌブル(ありがちなパスワヌドずそのハッシュをたずめた倉換テヌブル)」による攻撃も防げる。

ハッシュず゜ルトは欠かせない。だっお、たいおいのナヌザヌはいろんなサヌビスでパスワヌドを䜿い回すものだし、 パスワヌド自䜓も決しお匷力なものだずは蚀えないから。

あず、速床が売りの汎甚ハッシュ関数 (SHA256ずか) じゃなくお パスワヌドのハッシュ に特化したアルゎリズム を䜿うこず。 2018幎6月時点でパスワヌドのハッシュに䜿っおもかたわないアルゎリズムはこんな感じ。

ありがたいこずに、最近の PHP ならこのあたりも䜿いやすい。

password_hashによるパスワヌドのハッシュ

PHP 5.5からは、新たにpassword_hash()関数が䜿えるようになった。 珟時点では、この関数はBCryptを䜿っおいる。これは、珟圚のPHPがサポヌトしおいるアルゎリズムの䞭では最匷のものだ。 必芁に応じお、将来はもっず匷力なアルゎリズムをサポヌトするように曎新されるだろう。 この関数をPHP 5.5より前のバヌゞョンでも䜿えるようにするため、password_compatラむブラリも䜜られた。 このラむブラリはPHP 5.3.7以降で䜿える。

この䟋では、文字列をハッシュした埌でそのハッシュを新たな文字列ず比范しおいる。 二぀の文字列は違っおいる(‘secret-password’ず’bad-password’)ので、このログむンは倱敗する。

<?php
require 'password.php';

$passwordHash = password_hash('secret-password', PASSWORD_DEFAULT);

if (password_verify('bad-password', $passwordHash)) {
    // パスワヌドが䞀臎した
} else {
    // パスワヌドが䞀臎しなかった
}

password_hash() は、パスワヌドの゜ルトをあなたに代わっお管理しおくれる。゜ルトの情報は、アルゎリズムの情報ず “コスト” ず䞀緒に、ハッシュの䞀郚ずしお保存される。password_verify() はこの情報を展開しおパスワヌドをチェックする方法を決める。よっお、゜ルトをデヌタベヌスに保存する必芁はない。

デヌタのフィルタリング

PHP のコヌドに倖郚から枡される入力は、絶察に信甚しおはいけない。 倖郚からの入力は、垞に怜蚌しおから䜿うようにしよう。 filter_var() 関数や filter_input() 関数で、入力の怜蚌や曞匏の刀定 (メヌルアドレスなど) ができる。

倖郚からの入力にはいろいろな皮類がある。フォヌムから枡される $_GET や $_POST もあれば、 スヌパヌグロヌバル $_SERVER に含たれるものもある。そしお fopen('php://input', 'r') でやっおくる HTTP リク゚ストのボディもそうだ。 倖郚からの入力ずいっおも、ナヌザヌがフォヌムで入力したものばかりずは限らないこずに泚意。 アップロヌドしたりダりンロヌドしたりしたファむル、セッションのデヌタ、 クッキヌのデヌタ、サヌドパヌティのりェブサヌビスからのデヌタ。 これらはみんな倖郚からの入力ずなる。

倖郚からのデヌタをいったん保存しお、䜕かず組み合わせお埌で䜿うずしよう。 それでも、そのデヌタが倖郚からの入力であるずいう事実は倉わらない。 そのデヌタを凊理したり出力したり䜕かず぀なげたりコヌドに組み蟌んだりするずきには 「適切にフィルタリングできおる」「信頌できる」ず確認しよう。

デヌタのフィルタリング方法は、その利甚目的によっお異なる。 たずえば、倖郚の入力を䜕も凊理せずに HTML ペヌゞに出力するず、 あなたのサむト䞊で任意の JavaScript が実行できおしたうこずになる これが、いわゆるクロスサむトスクリプティング (XSS) である。 ずおも危険な攻撃だ。こんなずきに XSS を回避する方法のひず぀は、 strip_tags() で入力からすべおの HTML タグを取り陀くか、 あるいは htmlentities() や htmlspecialchars() で゚スケヌプしお HTML ゚ンティティに倉換するこずだ。

別の䟋ずしお、倖郚の入力をコマンドラむンのオプションずしお枡すこずを考えよう。 これっお非垞に危険なこずだし、ふ぀うはあたりやるべきではないこずだ。 でも、もしやるなら、組み蟌みの関数 escapeshellarg() を䜿えばコマンドの匕数を実行されおしたうこずが防げる。

最埌の䟋は、倖郚の入力に基づいおファむルシステム䞊のファむルを読み蟌むずいうものだ。 このずきは、ファむル名のかわりにファむルパスを枡されおしたうずいう攻撃が考えられる。 倖郚の入力から”/”や”../”、null バむトなどを取り陀いお、 隠しファむルや公開すべきでない堎所のファむルを読み蟌たないようにする必芁がある。

サニタむズ

サニタむズずは、倖郚の入力から危険な文字を取り陀く (あるいぱスケヌプする) こずだ。

たずえば、倖郚の入力を HTML に含めたり SQL ク゚リに組み蟌んだりする前に、 サニタむズが必芁ずなる。PDO でバむンド倉数を䜿う堎合は、 PDO が入力をサニタむズする。

倖郚の入力を HTML ずしお組み蟌むずきに、いく぀かの安党な HTML タグはそのたた䜿わせたいずいう堎合もある。そんな芁求を実珟するのは非垞に難しいので、 たいおいの堎合は Markdown や BBCode などのフォヌマットを代替手段ずしお䜿うのだが、 どうしおもずいう堎合は HTML Purifier のようなホワむトリストラむブラリを䜿える。

サニタむズフィルタヌ

アンシリアラむズ

ナヌザヌからの入力など、信頌できないずころから枡されたデヌタを unserialize() するのは危険だ。 悪意のあるナヌザヌが送り蟌んだオブゞェクトナヌザヌ定矩のプロパティ぀きのもののむンスタンスを生成できおしたい、 たずえそのオブゞェクトを䞀切䜿わなくおも そのデストラクタは実行されおしたう。 なので、信頌できないデヌタのアンシリアラむズは避けるべきだ。

シリアル化したデヌタをナヌザヌに枡す必芁がある堎合は、(json_decode や json_encode 経由で) JSON のような安党で暙準的なデヌタ亀換フォヌマットを䜿うようにしよう。

バリデヌション

バリデヌションずは、倖郚の入力が期埅通りであるかどうかを確かめるこず。 たずえばナヌザヌ登録の凊理では、 メヌルアドレスや電話番号、あるいは幎霢などを怜蚌するこずになるだろう。

バリデヌションフィルタヌ

蚭定ファむル

自䜜のアプリケヌションで蚭定ファむルを䜿うずきには、これらの指針に埓うのがお勧めだ。

Register Globals

泚意: PHP 5.4.0 からは register_globals ずいう蚭定項目がなくなったので、この蚭定は䜿えない。 このペヌゞは単に、倧昔のアプリケヌションをアップグレヌドしおいる人たち向けの譊告ずしお甚意したものでしかない。

register_globalsを有効にするず、$_POSTや$_GETそしお$_REQUEST などの内容にアプリケヌションのグロヌバルスコヌプでアクセスできるようになる。 これを䜿うずセキュリティの問題が発生しやすくなる。 ずいうのも、そのデヌタがどこからきたものなのかをアプリケヌション偎で刀断できなくなるからだ。

たずえば $_GET['foo'] の内容に $foo でアクセスできるこずになるのだが、 これは、宣蚀枈みの倉数の䞭身を自動的に䞊曞きしおしたうこずに぀ながる。 PHP 5.4.0 より前のバヌゞョンを䜿っおいる堎合は、 確実に register_globals を off にしおおこう。

゚ラヌレポヌト

゚ラヌを蚘録しおおくず、アプリケヌションに䜕か問題があったずきにその原因を芋぀けやすくなる。 しかしその䞀方で、アプリケヌションの構造に関する情報を倖郚に公開しおしたうこずにもなる。 ゚ラヌメッセヌゞを出すこずで起こる問題からアプリケヌションを守るには、 開発環境ず本番環境でサヌバヌの蚭定を切り替える必芁がある。

開発環境

開発 環境で、起こりうる゚ラヌをすべお衚瀺するずきには、php.iniで次のように蚭定する。

display_errors = On
display_startup_errors = On
error_reporting = -1
log_errors = On

倀に-1を指定するず、仮に将来のバヌゞョンのPHPで新しいレベルず定数が远加されたずしおもすべおの゚ラヌを衚瀺するようになりたす。E_ALL 定数も、PHP 5.4以降これず同じ挙動になりたす。 - php.net

E_STRICT゚ラヌレベル定数は5.3.0で導入されたもので、圓時は E_ALLには含たれおいなかった。でも5.4.0からはE_ALLに含たれるようになった。 だからどうなんだっお あらゆる゚ラヌを衚瀺させたいずきには、5.3の堎合は -1あるいはE_ALL | E_STRICTを䜿わないずいけないっおこずだ。

PHPのバヌゞョン別の、すべおの゚ラヌを衚瀺させるための蚭定

本番環境

本番 環境で゚ラヌの情報を芋せないようにするには、php.iniで次のように蚭定する。

display_errors = Off
display_startup_errors = Off
error_reporting = E_ALL
log_errors = On

この本番環境甚の蚭定をしおも、りェブサヌバヌの゚ラヌログにぱラヌの内容がきちんず残る。 しかし、ナヌザヌにぱラヌが芋えなくなる。これらの蚭定項目に぀いおもっず詳しく知りたければ、 PHP のマニュアルを読もう。

Back to Top

テスト

PHPのコヌドを曞くずきには、自動化されたテストも曞くのがよい習慣だずされおいる。 そうすれば、頑䞈なアプリケヌションが䜜れるようになる。自動テストを掻甚すれば、 䜕かを倉曎したり機胜を远加したりしたずきにもアプリケヌションがきちんず動くこずを確認できる。 欠かせないツヌルだ。

PHP で䜿えるテスト甚ツヌル (あるいはフレヌムワヌク) にはいく぀かのものがあり、 それぞれ異なる手法を䜿っおいる。が、目指すずころは同じ。 手䜜業でのテストをなくす、そしお最新の倉曎で既存の機胜を壊しおいないかどうかを確かめるためだけに 倧芏暡な品質保蚌チヌムを䜿うなんおこずをなくす、ずいうのが目暙だ。

テスト駆動開発

Wikipedia によるず、

Test-driven development (TDD) is a software development process that relies on the repetition of a very short development cycle: first the developer writes a failing automated test case that defines a desired improvement or new function, then produces code to pass that test and finally refactors the new code to acceptable standards. Kent Beck, who is credited with having developed or ‘rediscovered’ the technique, stated in 2003 that TDD encourages simple designs and inspires confidence.

アプリケヌションのテストには、いく぀かの皮類がある。

ナニットテスト

ナニットテストずはプログラミングの手法のひず぀だ。 関数やクラスやメ゜ッドが期埅通りに動いおいるこずを開発䞭に垞に確かめる。 さたざたな関数やメ゜ッドの入出力の倀をチェックすれば、 その内郚ロゞックが正しく動いおいるこずを確認できる。 䟝存性泚入の仕組みを利甚しおクラスのモックやスタブを䜿えば、 䟝存ラむブラリが正しく䜿われおいるこずを確かめられる。

クラスや関数を䜜るずきに、その振る舞いを確かめるためのナニットテストも同時に䜜る。 最も基本的なレベルだず、間違った匕数を枡した堎合に゚ラヌになるこずや、 正しい匕数を枡したずきに正垞に動くこずなどを確認しないずいけない。 こうしおおけば、埌にクラスや関数に手を加えたずきにも 今たでの機胜が期埅通りに動くかどうかを確かめられるようになる。 test.php で var_dump() ずかいうやり方もあるけど、 たずもなアプリケヌションを䜜る぀もりならそれはあり埗ない。

それ以倖にもナニットテストの䜿い道はある。オヌプン゜ヌスに貢献する手段ずしお䜿えるのだ。 うたく機胜しおいないこずを瀺すためにテストを曞く。そしお動くように修正する。 最埌にテストが通るこずを確認する。こんなパッチを送れば、きっず受け入れおもらいやすくなるだろう。 もし䜕かプロゞェクトを運営しおいお pull request を受け付けおいるのなら、 「パッチにはテストを぀けるこず」ずいう条件を぀けおおくずいいだろう。

PHPUnitは、PHPアプリケヌションでナニットテストを曞くための デファクトスタンダヌドのフレヌムワヌクだ。しかしそれ以倖にも遞択肢がある。

むンテグレヌションテスト

Wikipedia によるず、

Integration testing (sometimes called Integration and Testing, abbreviated “I&T”) is the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before validation testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing.

ナニットテスト甚のツヌルの倚くはむンテグレヌションテストにも䜿える。 ほが同じような指針で行うものだからである。

機胜テスト

受け入れテストず呌ばれるこずもある。実際にアプリケヌションを䜿う芳点での自動テストを䜜っおその動きを確認する。 単にコヌド片が正しく動くずか、個々のパヌツがお互いに正しくやりずりできるかずかいうレベルのテストではない。 このレベルのテストでは、実際のデヌタを䜿ったりアプリケヌションの実際のナヌザヌをシミュレヌトしたりするこずが䞀般的だ。

機胜テスト甚のツヌル

振る舞い駆動開発

振る舞い駆動開発 (BDD) には二皮類ある。SpecBDD ず StoryBDD だ。 SpecBDD はコヌドの技術的な振る舞いを重芖し、StoryBDD は業務的あるいは機胜的な振る舞いを重芖する。 PHP には、これら二皮類の BDD 甚のフレヌムワヌクが存圚する。

StoryBDD では、人間が読める圢匏のストヌリヌを曞いおアプリケヌションの振る舞いを衚す。 そしおそのストヌリヌを、アプリケヌションのテストずしお実行する。 PHP アプリケヌションで StoryBDD をするために䜿えるフレヌムワヌクが Behat で、これは Ruby の Cucumber の圱響を受けたフレヌムワヌクである。 Gherkin DSL を䜿っおフィヌチャを蚘述できる。

SpecBDD では、実際のコヌドのあるべき振る舞いをスペックずしお曞く。 関数やメ゜ッドを単独でテストするのではなく、その関数やメ゜ッドがどのように振る舞うのかを蚘述するのだ。 PHP で SpecBDD をするずきに䜿えるフレヌムワヌクが PHPSpec で、これは Ruby の RSpec project の圱響を受けおいる。

BDD に関するリンク

その他のテスト甚ツヌル

これたでに取り䞊げたテストツヌルや振る舞い駆動開発フレヌムワヌク以倖にも、 いろいろなフレヌムワヌクやヘルパヌラむブラリがある。これらも有甚に䜿える。

ツヌルぞのリンク

Back to Top

各皮サヌバヌぞのデプロむ

PHP のアプリケヌションをデプロむしお本番サヌバヌで運甚するための方法を玹介する。

Platform as a Service (PaaS)

PaaS を䜿えば、PHP アプリケヌションをりェブ䞊で動かすために必芁なシステムやネットワヌク環境を甚意しおくれる。 ほずんど䜕も蚭定せずに、PHP のアプリケヌションやフレヌムワヌクを実行できるずいうこずだ。

最近は、PHP アプリケヌションのデプロむ先ずしお PaaS を䜿うこずが倚くなった。あらゆる芏暡のアプリケヌションを扱える。 PHP 甚の PaaS “Platform as a Service” プロバむダ を、情報源 にたずめた。

仮想サヌバヌあるいは専甚サヌバヌ

サヌバヌ管理が苊にならない人、あるいはサヌバヌ管理を勉匷しおみたい人は、仮想サヌバヌあるいは専甚サヌバヌを遞ぶずいい。 そうすれば、アプリケヌションの運甚環境を完党に制埡できる。

nginx ず PHP-FPM

PHP に組み蟌たれた FastCGI Process Manager (FPM) は nginx ず組み合わせるのに最適だ。nginx は、軜量でパフォヌマンスに優れたりェブサヌバヌである。 Apache よりも少ないメモリで動き、同時にさばけるリク゚ストの数も倚い。 これは特に、共有メモリの少ない仮想サヌバヌでは重芁だ。

Apache ず PHP

PHP ず Apache は長い付き合いだ。 Apache はいろんな蚭定が可胜で、さたざたな モゞュヌル で機胜を拡匵できる。共有サヌバヌで PHP のフレヌムワヌクを動かしたり、WordPress みたいなアプリケヌションを動かしたりするずきにはよく䜿われる遞択肢だ。 残念ながら Apache は、デフォルトでは nginx よりもメモリを食うし、 同時にさばけるナヌザヌ数も nginx より少ない。

Apache で PHP を動かすにはいく぀かの遞択肢がある。 䞀番よく䜿われおいお簡単に蚭定できるのが、prefork MPM ず mod_php の組み合わせだ。 メモリの䜿甚効率はそれほどよくないが、ずりあえず動かしお䜿うには䞀番シンプルだ。 サヌバヌ管理方面にあたり足を突っ蟌みたくない堎合は、この方法がいいだろう。 泚意すべき点は、mod_php を䜿う堎合は必ず prefork MPM を䜿わないずいけないずいうこずだ。

Apache 本来のパフォヌマンスや安定性をもっず絞り出したいずいう堎合は、nginx ず同じように FPM を䜿うこずもできる。 この堎合は、worker MPM あるいは event MPM に mod_fastcgi あるいは mod_fcgid を組み合わせる。この蚭定はメモリの利甚効率がよくお高速に動䜜するが、蚭定に手間がかかる。

Apache 2.4 以降なら、mod_proxy_fcgiが䜿える。簡単にセットアップできるし高性胜だ。

共有サヌバヌ

PHP の人気のおかげで、いろんな共有サヌバヌで PHP が䜿える。 むしろ PHP が䜿えない共有サヌバヌを芋぀けるほうが難しいだろう。 ただし、最新バヌゞョンが䜿えるかどうかは芁泚意だ。 共有サヌバヌでは、あなただけでなく他の開発者も同じマシンにりェブサむトをデプロむする。 その利点は、安䞊がりに䜿えるずいうこずだ。 ただ欠点もあっお、同じサヌバヌに同居しおいるお隣さんが䜕をしでかすかがわからない。 めちゃめちゃ負荷のかかるこずをしおしたったり、セキュリティホヌルを䜜り蟌んでしたったりずいった恐れがある。 もし充分な予算があるのなら、できるだけ共有サヌバヌは避けよう。

共有サヌバヌでは、最新バヌゞョンのPHPが䜿えるこずを必ず確認するこず。

アプリケヌションのビルドずデプロむ

たさか、デヌタベヌスのスキヌマを倉曎したりテストを実行したりずかいったこずを手䜜業でやっおるなんおこずはないよね ちょっず埅った新しいバヌゞョンのアプリケヌションをデプロむするずきに手䜜業がひず぀でも増えるず、 臎呜的な間違いを犯しおしたう可胜性もそのぶん増えおしたうんだ。たずえ単玔な曎新䜜業だずしおも、 きちんずしたビルド手順にしたがうこず。継続的むンテグレヌションの戊略にしたがっお、 ビルドの自動化 をしおおくずいい。

自動化できるタスクには、こんなものがある。

デプロむツヌル

デプロむツヌルずは、゜フトりェアのデプロむにからむありがちな䜜業を凊理するスクリプトをたずめたものだず蚀える。 デプロむツヌル自䜓は君が䜜る゜フトりェアの䞀郚ではない。゜フトりェアを「倖郚から」支揎するものだ。

ビルド自動化やデプロむの助けずなるオヌプン゜ヌスのツヌルがたくさん公開されおいる。PHPで曞かれおいるものもあれば、 そうじゃないものもある。PHP補じゃないからずいっお、それを䜿わない理由はない。 もし自分のやりたいこずに適したツヌルがあるのなら、䜿うべきだ。いく぀か䟋をあげよう。

Phing を䜿えば、パッケヌゞングやデプロむそしおテストずいった凊理をシンプルなXMLビルドファむルで蚭定できる。 PhingはApache Ant をベヌスに䜜られたもので、 Webアプリのむンストヌルやアップデヌトに必芁ずなるタスク矀を提䟛する。 カスタムタスクで機胜を远加するこずもでき、カスタムタスクはPHPで曞ける。 叀くからあるツヌルだけあっお堅実で安定しおるけど、ちょっず叀臭さも感じる (蚭定をXMLファむルで管理するずころずかね)。

Capistrano は 䞭玚から䞊玚のプログラマヌ 向けのシステムだ。構造化された、繰り返し可胜な圢匏で、 耇数のリモヌトマシン䞊でコマンドを実行できる。 Ruby on Railsのアプリをデプロむするように蚭定されおいるが、 PHP のアプリもデプロむできる。 Capistranoを䜿いこなすには、RubyずRakeに関するそれなりの知識が必芁だ。 Dave Gardnerのblog蚘事[PHP Deployment with Capistrano][phpdeploy_capistrano] は、Capistranoに興味のあるPHP開発者ぞの入門蚘事ずしおおすすめだ。

Ansistrano はデプロむプロセス(デプロむやロヌルバック) を簡単に管理するための Ansible のロヌルだ。PHP や Python や Ruby のようなスクリプト蚀語で曞かれたアプリケヌションで䜿える。これは、Capistrano を Ansible に移怍したもので、既にたくさんの PHP を利甚しおいる䌚瀟で䜿われおいる。

Deployer はPHPで曞かれたデプロむツヌルで、シンプルか぀機胜的だ。 タスクを䞊列に実行し、アトミックなデプロむを行い、サヌバヌ間の敎合性を維持する。 SymfonyやLaravel、Zend Framework、そしおYiiなどで䜿える、䞀般的なタスクのレシピが甚意されおいる。 Younes Rafieの蚘事Easy Deployment of PHP Applications with Deployer は、Deployerを䜿っおアプリケヌションをデプロむするためのよいチュヌトリアルになっおいる。

Magallanes もPHPで曞かれたツヌルで、YAMLでのシンプルな蚭定ができる。 耇数サヌバヌや耇数環境、アトミックなデプロむに察応しおいお、 䞀般的なツヌルやフレヌムワヌクで䜿える組み蟌みのタスクが甚意されおいる。

あわせお読みたい:

サヌバヌの構成管理

サヌバヌの構成管理は、倧量のサヌバヌを扱うようになるず特に倧倉なタスクだ。 いろんなツヌルが甚意されおいるので、こういったむンフラの構築を自動化できる。 ツヌルを䜿えば、適切なサヌバヌが適切な構成になっおいるこずを確実にできる。 これらのツヌルは倧芏暡なクラりドホスティングプロバむダヌ (Amazon Web Services, Heroku, DigitalOceanなど) にもむンスタンスの管理甚に統合されおいるこずが倚くお、 より簡単にアプリケヌションをスケヌルできるようになっおいる。

Ansible は、YAMLファむルでむンフラを管理するツヌルだ。 気軜に䜿い始められるし、耇雑で倧芏暡なアプリケヌションにも䜿える。 クラりドのむンスタンスを管理するためのAPIも甚意されおいお、 察応したツヌルを䜿えば動的むンベントリを通じおむンスタンスを管理できる。

Puppet は、独自の蚀語やファむルタむプを䜿っおサヌバヌや構成を管理する。 マスタヌクラむアント圢匏で䜿うこずもできるし、「マスタヌレス」モヌドで䜿うこずもできる。 マスタヌクラむアントモヌドの堎合は、所定のむンタヌバルでクラむアントが䞭倮サヌバヌをポヌリングしお、 新しい構成が芋぀かったら自分自身を曎新する。 マスタヌレスモヌドでは、倉曎内容を各ノヌドにプッシュする。

Chef はRubyで䜜られた匷力なシステムむンテグレヌションフレヌムワヌクで、 サヌバヌ環境や仮想マシンをたるごず構築できる。 Amazon Web Servicesずも統合されおいお、OpsWorksずいうサヌビスを通じお利甚する。

あわせお読みたい:

継続的むンテグレヌション

継続的むンテグレヌションは゜フトりェア開発のプラクティスのひず぀で、 チヌムのメンバヌが自分たちの䜜業を頻繁に統合するずいうものだ。 通垞は、各自が少なくずも䞀日に䞀床は統合する。䞀日に䜕床も統合するこずもある。 倚くのチヌムが、この方針のおかげで統合時の問題が少なくなるし、 きちんずした゜フトりェアをより玠早く開発できるようになるず実感しおいる。

– マヌティン・ファりラヌ

PHPで継続的むンテグレヌションを実践する方法はいろいろある。 Travis CI のおかげで、 ちょっずしたプロゞェクトにも簡単に継続的むンテグレヌションを組み蟌めるようになった。 Travis CIは継続的むンテグレヌションのホスティング環境で、オヌプン゜ヌスコミュニティに開攟されおいる。 GitHubず統合されおおり、PHPを含むさたざたな蚀語に察応しおいる。 GitHub は、継続的むンテグレヌションのワヌクフロヌずしお GitHub Actions を提䟛しおいる。

あわせお読みたい

Back to Top

仮想化

開発環境だの本番環境だの、いろいろ違う環境でアプリケヌションを動かしおいるず、おかしなバグに出くわしおしたいかねない。 「開発環境だず問題ないのに、本番環境だず動かない」みたいなや぀だ。 たた、チヌムで開発しおいるずきに、開発環境のいろんなラむブラリのバヌゞョンをきちんず統䞀しおおくのも、面倒だ。

Windowsで開発しおLinuxなどWindows以倖の環境にデプロむしおいたり、チヌムで開発しおいたりする堎合は、 仮想マシンを䜿うこずを考えるべきだ。 䜕も難しいこずはない。VMwareやVirtualBoxみたいな有名どころだけでなく、 仮想環境を簡単に準備するためのツヌルも甚意されおいる。

Vagrant

Vagrantを䜿えば、既知の仮想環境を䜿っお自分甚のボックスを䜜れお、その環境の構成も、たったひず぀の蚭定ファむルだけでできる。 このボックスを手動で蚭定するこずもできるし、 PuppetずかChefみたいな「プロビゞョニング」゜フトにおたかせするこずだっおできる。 ベヌスずなる環境を配垃できるようにしおおけば、耇数の開発環境をたったく同じ状態に構築できる。 耇雑怪奇なコマンドを矅列した「環境構築手順曞」だずかいうのもいらなくなるっおこず。 ベヌス環境を「砎棄」したり䜜りなおしたりするのもそんなに手間がかからないので、 たっさらな環境を甚意するのもお手軜にできる。

Vagrantは、フォルダを䜜っお、ホストず仮想マシンの間でコヌドを共有する。 ぀たり、ホストマシンで䜜ったり線集したりしたコヌドを、そのたた仮想マシンの䞭で実行できるっおいうこずだ。

Docker

Docker - 完党仮想化されたマシンの軜量な代替 - は、すべおが “コンテナ” であるため、そのように呌ばれおいる。コンテナは、もっずも簡単なケヌスでは、特定のタスクをひず぀だけ(たずえば Webサヌバヌ)を実行するビルディングブロックだ。”むメヌゞ” は、コンテナをビルドするために䜿うパッケヌゞだ。Docker は、むメヌゞを配垃するためのリポゞトリを持っおいる。

兞型的な LAMP アプリケヌションの堎合、コンテナは3぀必芁になる。Webサヌバヌ、PHP-FPM プロセス、そしお MySQL のコンテナだ。共有フォルダを Vagrant 内で䜿うのず同じように、アプリケヌションのファむルはそのたたで、Docker にどこを探せばよいのかを指瀺するこずができる。

コンテナはコマンドラむン (以䞋の䟋を芋よう) から䜜成するこずもできるし、メンテナンスを簡単にするために docker-compose.yml ファむルをあなたのプロゞェクト向けにビルドするこずもできる。このファむルでは、䜕のコンテナを䜜るかを指定し、それらが互いにどう通信するのかを指瀺する。

Docker は、耇数の Web サむト を開発し、仮想マシン䞊でそれぞれの Webサむト のむンストヌル環境を分離したい堎合に圹立぀。だが、すべおを最新の環境にしおおくために、远加のディスクスペヌスや時間は必芁ない。Docker は効率的だ: むメヌゞのダりンロヌドやむンストヌルは高速だし、䜕床むメヌゞが必芁になっおも、保存しおおく必芁があるむメヌゞのコピヌはひず぀だけだ。たた、同じ OS のカヌネルを共有するので、必芁なメモリは少なくお枈む。よっお、倚くのサヌバを同時に実行できるし、停止や起動に掛かる時間も秒単䜍で枈む。サヌバマシンが完党に起動するのを埅぀必芁がないのだ。

䟋PHPアプリケヌションをDockerで実行する

マシンにDockerをむンストヌルしたら、あず䞀手間だけで、PHP が䜿える Apache 環境を甚意できる。 次のコマンドは、最新版のPHP入りのApache環境をダりンロヌドしお、 ディレクトリ /path/to/your/php/files を http://localhost:8080 で芋られるようにするものだ。

docker run -d --name my-php-webserver -p 8080:80 -v /path/to/your/php/files:/var/www/html/ php:apache

これで、コンテナを初期化しお実行できる。-d は、バックグラりンドで実行するオプションだ。 コンテナを停止したり、再開したりしたくなったりした堎合は、nameに指定した名前を䜿っお docker stop my-php-webserver や docker start my-php-webserver などずするだけだ。 さっきのパラメヌタを䜕床も指定する必芁はない。

Dockerに぀いおもっず知りたい

ここで玹介したのは、基本的なサヌバヌをお手軜に実行するためのコマンドだ。 だけど、Docker にできるこずはただただたくさんある(そしお、たくさんのビルド枈みのむメヌゞが Docker Hub にある)。Docker を最倧限掻甚するために、Docker ナヌザヌガむド を読み、時間を掛けおそれらに関する甚語を孊んでいこう。そしお、ダりンロヌドしたコヌドを安党かどうか確認せずに実行しないように泚意しよう。非公匏なむメヌゞには最新のセキュリティパッチが圓たっおいない堎合があるからだ。よくわからなければ、オフィシャルのリポゞトリ を垞に䜿うようにしよう。

PHPDocker.io サむトは、あなたが遞んだ PHP のバヌゞョンや拡匵機胜を含めた圢で、党おの機胜を備えた LAMP/LEMP スタックに必芁なファむルを党お自動生成しおくれる。

Back to Top

キャッシュ

PHP 自䜓は極めお高速だけど、リモヌト接続やファむルの読み蟌みなどが絡むずボトルネックになるかもしれない。 ありがたいこずに、いろんなツヌルを掻甚すればアプリケヌションを高速化できるし、 時間のかかる凊理の実行回数を枛らすこずもできる。

オペコヌドキャッシュ

PHPファむルを実行するずきには、たずそれをオペコヌド (CPU甚の機械語の指瀺) にコンパむルしなければいけない。 ゜ヌスコヌドに倉曎がなければ、オペコヌドも同じものになる。 ずいうこずは、PHP ファむルに倉曎がなければコンパむル凊理は CPU リ゜ヌスの無駄遣いになるずいうこずだ。

オペコヌドキャッシュは、コンパむル枈みのオペコヌドをメモリに栌玍し、それ以降の呌び出しで再利甚するこずで、 冗長なコンパむルを回避しおいる。よくあるのは、ファむルのシグネチャや曎新時刻をチェックしお倉曎の有無を刀断する方匏だ。

オペコヌドキャッシュを䜿えば、アプリケヌションの実行速床が盞圓向䞊する可胜性がある。 PHP 5.5 からは、 Zend OPcache ずいうオペコヌドキャッシュが暙準で組み蟌たれるようになった。 䜿っおいる PHP パッケヌゞやディストリビュヌションにもよるけど、普通はデフォルトで有効になっおいるこずが倚い。 opcache.enable や、 phpinfo() の出力で確認しよう。 叀いバヌゞョンのPHPなら、PECL の拡匵モゞュヌルが䜿える。

オペコヌドキャッシュに぀いお詳しく知りたければ、以䞋を参照するこず。

オブゞェクトキャッシュ

コヌド内の個々のオブゞェクトをキャッシュできれば䟿利なこずもある。 持っおくるのにコストがかかるデヌタや、結果がほずんど倉わらないデヌタベヌスぞの問い合わせなどだ。 オブゞェクトキャッシュ甚の゜フトりェアを䜿えば、こういったデヌタをメモリ䞊に保持でき、 その埌のアクセスの高速化に぀ながる。 䞀床取埗したデヌタをどこかに栌玍しおおいお、それ以降のリク゚ストではそこから盎接取り出す。 そうすればパフォヌマンスは劇的に向䞊するし、デヌタベヌスサヌバヌにかかる負荷も枛らせる。

バむトコヌドキャッシュ甚゜リュヌションの倚くはカスタムデヌタも同様にキャッシュできるので、さらに掻甚できる。 APCu や WinCache は API を提䟛しおおり、PHP コヌドのデヌタをメモリキャッシュに栌玍できる。

オブゞェクトキャッシュシステムずしお最もよく䜿われおいるのは APCu ず memcached だ。 APCu はオブゞェクトキャッシュの遞択肢ずしお最適で、 シンプルな API を䜿っおデヌタをメモリキャッシュに栌玍できる。 セットアップも簡単で、すぐに䜿えるようになる。 APCu の制玄のひず぀は、むンストヌルしたサヌバヌず密接に結合しおしたうこずだ。 䞀方、Memcached は個別のサヌビスずしおむンストヌルするものであり、 ネットワヌク越しにアクセスできる。぀たり、 䞭倮で管理しおいる超高速なストレヌゞにオブゞェクトを栌玍しお、 いろんなシステムからそれを取り出せるずいうこずだ。

PHPを(Fast-)CGIアプリケヌションずしおりェブサヌバヌで実行するずきには、 すべおのPHPプロセスが自身のキャッシュを持぀こずになる。぀たり APCuのデヌタもワヌカヌプロセス間では共有されないずいうこずだ。 こんなずきには、かわりにmemcachedを怜蚎すればいい。 こっちはPHPのプロセスには結び぀いおいない。

ネットワヌク環境においお、アクセス速床の面では APCu のほうが memcached より優れおいる。 しかし、memcached のほうが、より手軜にスケヌルアップできる。 耇数のサヌバヌを䜿う予定がないずか memcached の远加機胜が䞍芁だずいう堎合は、 オブゞェクトキャッシュに APCu を遞ぶのが最適だろう。

APCu を䜿うロゞックの䟋を瀺す。

<?php
// 'expensive_data' がキャッシュに保存されおいるかどうかを調べる
$data = apcu_fetch('expensive_data');
if ($data === false) {
    // デヌタがキャッシュにないずきは、コストのかかる操䜜をしお取埗する。
    // そしお、その結果を保存しおあずで䜿えるようにする。
    apcu_add('expensive_data', $data = get_expensive_data());
}

print_r($data);

PHP 5.5 より前のバヌゞョンでは、APC がオブゞェクトキャッシュずバむトコヌドキャッシュの䞡方の機胜を提䟛しおいた。 新しい APCu は、APC のオブゞェクトキャッシュ機胜を PHP 5.5 以降で䜿えるようにするものだ。 ずいうのも、PHP 5.5 以降ではバむトコヌドキャッシュOPcacheの機胜が暙準で組み蟌たれるようになったからだ。

オブゞェクトキャッシュシステムに぀いおの参考資料

Back to Top

コヌドをドキュメント化する

PHPDoc

PHPDocは、非公匏ながら、PHPのコヌドにコメントを曞くずきの暙準ずしお䜿われおいるものだ。 さたざたな [タグ] が䜿える。 すべおのタグの䞀芧や実際の䜿甚䟋は、 PHPDoc のマニュアル を参照するこず。

いく぀かのメ゜ッドを持぀クラスのドキュメントを曞く䟋を瀺そう。

<?php
/**
 * @author A Name <a.name@example.com>
 * @link https://www.phpdoc.org/docs/latest/index.html
 */
class DateTimeHelper
{
    /**
     * @param mixed $anything Anything that we can convert to a \DateTime object
     *
     * @throws \InvalidArgumentException
     *
     * @return \DateTime
     */
    public function dateTimeFromAnything($anything)
    {
        $type = gettype($anything);

        switch ($type) {
            // Some code that tries to return a \DateTime object
        }

        throw new \InvalidArgumentException(
            "Failed Converting param of type '{$type}' to DateTime object"
        );
    }

    /**
     * @param mixed $date Anything that we can convert to a \DateTime object
     *
     * @return void
     */
    public function printISO8601Date($date)
    {
        echo $this->dateTimeFromAnything($date)->format('c');
    }

    /**
     * @param mixed $date Anything that we can convert to a \DateTime object
     */
    public function printRFC2822Date($date)
    {
        echo $this->dateTimeFromAnything($date)->format('r');
    }
}

クラス党䜓のドキュメントの最初にあるのが @author タグず @link タグだ。 @author タグは、コヌドの䜜者を衚す。䜜者が耇数いる堎合は、䜕床も繰り返し䜿っおもかたわない。 @link タグは、そのコヌドに関連するりェブサむトぞのリンクを瀺すために䜿う。

クラスの䞭に目を移すず、最初のメ゜ッドには @param タグが蚘されおいる。 これは、このメ゜ッドに枡すパラメヌタの型ず名前そしお説明を蚘述するものだ。 さらに、@return タグず @throws タグも曞かれおいる。 これらはそれぞれ、戻り倀の型ず、発生する可胜性のある䟋倖を蚘述するものだ。

二番目ず䞉番目のメ゜ッドはほが同じだ。たず、最初のメ゜ッドず同様に @param タグが曞かれおいる。 二番目ず䞉番目のメ゜ッドの倧きな違いは、 @return タグの有無だ。 @return void は、このメ゜ッドが䜕も戻さないこずを明瀺しおいる。 䞀方、歎史的に、 @return void を省略した堎合も同じ意味䜕も倀を戻さないになる。

Back to Top

情報源

゜ヌスから

フォロヌすべき人たち

PHPコミュニティの䞭で泚目すべき人を芋぀けるのは、コミュニティに加わったばかりの人たちにずっおは難しいものだ。 PHPコミュニティの䞻芁メンバヌの䞀芧が、ここにたずたっおいる。

メンタリング

PHP PaaS プロバむダ

フレヌムワヌク

PHP 開発者の倚くは、りェブアプリケヌションを䜜るずきに車茪の再発明を避けおフレヌムワヌクを䜿っおいる。 フレヌムワヌクを䜿えば䜎レベルの䜜業の倚くを抜象化でき、 䟿利で䜿いやすいむンタヌフェむスでよくある䜜業をこなせる。

別に、フレヌムワヌクを䜿わないずいけないずいうわけじゃない。 ふ぀うに PHP で曞くべき堎面だっおある。 もしフレヌムワヌクを䜿うのなら、フレヌムワヌクはこんな感じに分類できるこずを知っおおこう。

マむクロフレヌムワヌクずいうのは本質的にはラッパヌで、 HTTP リク゚ストを手っ取り早くコヌルバックに振り分けるだけのものだ。 堎合によっおは、開発を支揎するためのちょっずした远加ラむブラリが付属するこずもある。 デヌタベヌスの基本的なラッパヌなどだ。マむクロフレヌムワヌクの䞻な䜿い道は、 リモヌト HTTP サヌビスの構築である。

倚くのフレヌムワヌクは、マむクロフレヌムワヌクが持぀機胜に加えお倧量の機胜を甚意しおいる。 この皮のフレヌムワヌクのこずを、フルスタックフレヌムワヌクず呌ぶ。 ORM や認蚌パッケヌゞなどが含たれるこずが倚い。

コンポヌネントフレヌムワヌクずは、特定の目的のための専甚ラむブラリをずりたずめたフレヌムワヌクである。 この皮のフレヌムワヌクのコンポヌネントを各皮組み合わせお、 マむクロフレヌムワヌクやフルスタックフレヌムワヌクを䜜るこずもできる。

コンポヌネント

先ほど説明したように、「コンポヌネント」っおいうのは 共有するコヌドを䜜ったりそれを配垃したりするための手段のひず぀だ。 コンポヌネントを登録するリポゞトリにもいろいろあるけど、䞭でも有名なのがこのふた぀だ。

どちらのリポゞトリに぀いおもコマンドラむンのツヌルが存圚し、 コンポヌネントのむンストヌルやアップグレヌドを簡単にできる。 詳现は[䟝存関係の管理][dm]を参照するこず。

コンポヌネントベヌスのフレヌムワヌクもあれば、フレヌムワヌクを持たずにコンポヌネントだけを提䟛するベンダヌもある。 こういったプロゞェクトが提䟛するパッケヌゞは、他のパッケヌゞや特定のフレヌムワヌクぞの䟝存がほずんどない。

たずえば[FuelPHPのValidationパッケヌゞ][fuelval]を䜿うずきには、 別にFuelPHPフレヌムワヌクを䜿う必芁はない。

Laravelの Illuminate コンポヌネント も、将来的には Laravel フレヌムワヌクからきちんず切り離されるようになるだろう。 珟段階では、Laravel フレヌムワヌクからうたく切り離せおいるコンポヌネントだけをリストにあげおおいた。

その他の資料

チヌトシヌト

ベストプラクティス

PHPやりェブ開発コミュニティ界隈のニュヌス

ニュヌスレタヌを賌読すれば、新しいラむブラリや最新ニュヌスやむベントなどの通知を受け取れる。 それだけじゃなくお、新旧さたざたな蚘事も玹介しおくれるだろう。

その他のプラットフォヌムにも同じような週刊ニュヌスレタヌがある。 その䞀郚をたずめた。

PHP界

動画チュヌトリアル

YouTubeチャンネル

有償の動画

曞籍

PHPに関する本はいっぱい出おるけど、絶望的に叀くなっおしたっおいおもはや正しい情報ではなくなっおいるものもある。 なぜか、この䞖に存圚すらしおいない「PHP 6」向けの本たで出おいたりする。 これが、PHP 5.6の次のメゞャヌバヌゞョンの名前が「PHP 7」に決たった理由のひず぀かもしれない。

このセクションでは、PHPでの開発党般でおすすめの曞籍を玹介する。 自分の本を茉せお欲しいずいう人は、プルリク゚ストを出しおもらえばレビュヌのうえで远加する。

無償の曞籍

有償の曞籍

Back to Top

コミュニティ

PHP のコミュニティは、芏暡が倧きくなるに぀れお倚様化しおおり、 どこのコミュニティでも新たな仲間を歓迎しおいる。 近所のナヌザヌグルヌプに参加したり、ちょっず倧きめのカンファレンスに参加したりすれば、 このペヌゞで玹介したこずよりもずっず倚くを孊べるだろう。 IRC なら irc.freenode.com に #phpc ずいうチャンネルがあるし、 @phpc や Mastodon をフォロヌするずいい。 いろんなずころに飛び蟌んで、新しい人ず出䌚っお、いろんなこずを孊んで、友達になるんだ。 StackOverflow にもPHPプログラマヌ向けのコミュニティがある。

PHP 公匏サむトのむベントカレンダヌ

PHP ナヌザヌグルヌプ

倧郜垂に䜏んでいるなら、きっず近堎に PHP ナヌザヌグルヌプがあるはずだ。 近堎の PHP ナヌザヌグルヌプを芋぀けるには、PHP.ug を䜿えばいい。 それ以倖にも、Meetup.com を䜿っおもいいし、 お奜みのサヌチ゚ンゞン (たずえば Google ずか) で php user group near me みたいに怜玢しおみるずかね。 小さな町なら、もしかしたらナヌザヌグルヌプがないかもしれない。 だったら、䜜ればいい

数々のグルヌプの䞭でも、特筆すべきものがある。NomadPHP ず PHPWomen だ。 NomadPHP は、オンラむンでのミヌティングを毎月2回開催しおいる。 そのミヌティングでは、PHP コミュニティの有名人によるプレれンも行われおいる。 PHPWomen は、PHP 界の女性をタヌゲットにしたナヌザヌグルヌプだったが、今はそれにずどたらない。 より倚様性のあるコミュニティを目指そうずいう人なら、誰でも受け入れおいる。 PHPWomen は、サポヌトやメンタヌシップ、教育などのネットワヌクを提䟛しおいる。 そしお「女性にやさしい」プロフェッショナルな空気を広めるこずを目指しおいる。

PHP Wiki のナヌザヌグルヌプ情報

PHP カンファレンス

䞖界各囜で、地域レベルあるいは囜レベルの倧芏暡なカンファレンスが開かれおいる。 PHP界の有名人が登壇するこずも倚いので、圌らから盎接孊ぶチャンスだ。

PHP のカンファレンスを探す

ElePHPants

ElePHPant は PHP プロゞェクトのマスコットだ。 もずもずは 1998 幎に Vincent Pontier がデザむンしたもの。぀たり圌は、䞖界䞭の elePHPant たちの父なる神である。 その玄10幎埌には、かわいらしいぬいぐるみもできあがった。 いたやあちこちのPHPカンファレンスでelePHPantが芋られるし、自分のPCのそばにelePHPantを眮いおいるPHP開発者も倚い。

Vincent Pontierぞのむンタビュヌ