[PHP]Composerをautoloadだけの目的で使う

カテゴリ: composer

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"
        }
    }
}
こちらもおススメ

コメントを残す

メールアドレスが公開されることはありません。