PHPでComposerといえばパッケージの依存性管理を行うためのツールですが、パッケージ管理以外にオートロードの機能も備えています。
今回はcomposerを使って、何も依存パッケージを利用せず、オートロードの機能だけ利用したプログラムを作ってみます。
フォルダ構成
今回のプロジェクトでは、下記の3ファイルのみを用意します。
app/controller/UserController.php
composer.json
index.php
index.phpから、composerのautoload機能を使ってUserController.phpをロードしてみます。
各ファイルの内容説明
まずは、各ファイルの中身を説明します。
UserController.php
まずは、ロードされるUserControllerの中身です。
<?php
# app/controller/UserController.php
namespace App\Controller;
class UserController
{
public function test()
{
echo "hello" . PHP_EOL;
}
}
注意する点は、namespaceが指定されているぐらいで、他はごく普通のクラスです。ネームスペース名やクラス名、フォルダ構成は、PSR-4規格に準拠した形で作成しています。
index.php
次は、UserControllerの呼び出し元であるindex.phpです。
<?php
require 'vendor/autoload.php';
$userContoller = new \App\Controller\UserController();
$userContoller->test();
本来なら、require 'app/controller/UserController.php';
と書きたいところですが、autoloaderを利用するので、require 'vendor/autoload.php';
となっています。
vendor/autoload.phpファイルはまだ存在していませんが、この後composerコマンドを使って自動生成します。
composer.json
次が、autoloadの目的だけで使用するcomposerの設定ファイルです。
autoload以外の設定をすべてそぎ落とした、最小限の構成は、下記の定義となります。
{
"autoload": {
"psr-4": {
"App\\Controller\\" : "app/controller"
}
}
}
composerの設定
上記の状態でcomposer install(もしくはcomposer update)コマンドを実行します。
すると、vendorフォルダにcomposerのautoloadに関係するコードがダウンロードされます。依存パッケージを何も入れてないので、composer showコマンドを実行しても何も表示されません。
> composer install
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Generating autoload files
> composer show
> ls -lF
app/
composer.json
index.php
vendor/ # <= 追加された
プログラムの実行
実行すると、以下のようにautoloadの機能を利用して、UserControllerクラスがロードされ、test()メソッドが処理されました。
> php index.php
hello
これだけの作業でcomposerのautoloadの機能が使えるようになりました。
その他
autoloadに関するトラブルシューティングやTipsです。
autoloadするフォルダ(namespace)を追加する
例えば、Controllerに加えてModelクラスを用意したい場合、以下のように、composer.jsonファイルを書き換えればよいです。
{
"autoload": {
"psr-4": {
"App\\Controller\\" : "app/controller",
"App\\Model\\" : "app/model"
}
}
}
ただし、composer.jsonを更新しても、app/modelのファイルは読み込めるようになりません。
これは、'vendor/autoload.php'がjsonファイルを直接読み込んでいるわけでなないからです。
変更したjsonファイルの内容を反映させるためには、composer dump-autoloadコマンドを実行します。
> composer dump-autoload
Generating autoload files
コマンドを実行後に、/vendor/composer/autoload_psr4.phpファイルを開いてみると、以下のように定義が増えていることが核にできます。
(コメントに"@generated by Composer"と書かれているように、このファイルはcomposerによって自動生成されるので、手動で書き換えてはなりません)
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'App\\Model\\' => array($baseDir . '/app/model'),
'App\\Controller\\' => array($baseDir . '/app/controller'),
);
dump-autoloadしてもautoload出来ないときのデバッグ
定義も変更し、dump-autoloadしても思ったようにオートロードできない場合は、index.phpを下記のように書き換えると、プログラムの実行時に、どのようなオートロードが行われるかの定義を確認できます。
<?php
require 'vendor/autoload.php';
↓
<?php
$autoloader = require 'vendor/autoload.php';
// dump autoload setting.
echo json_encode($autoloader->getPrefixesPsr4(), JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES) . PHP_EOL;
実行結果は、以下のようになります。
どのネームスペースを指定したときに、どのディレクトリのファイルをautoloadするかを確認できませす。
> php index.php
{
"App\\Model\\": [
"C:\\work\\vendor\\composer/../../app/model"
],
"App\\Controller\\": [
"C:\\work\\vendor\\composer/../../app/controller"
]
}
ミスの原因は、スラッシュやバックスラッシュをつけすぎたり、逆に付け忘れたり...などがありがちなパターンです。
composer.jsonをもう少し整える
composer.jsonの定義は、今回作ったものでvalidな最小限の構成ですが、composer validateコマンドを実行すると、下記のようにワーニングがいくつか表示されます。
> composer validate
./composer.json is valid for simple usage with composer but has
strict errors that make it unable to be published as a package:
See https://getcomposer.org/doc/04-schema.md for details on the schema
name : The property name is required
description : The property description is required
No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license.
ワーニングが出ない程度にcomposer.jsonの内容を整えると、以下のようにname、description、licenseを追加すればよいです。
{
"name": "my-project/test01",
"description": "",
"license":"proprietary",
"autoload": {
"psr-4": {
"App\\Controller\\" : "app/controller",
"App\\Model\\" : "app/model"
}
}
}