ツイート
シェア
LINEで送る
B! はてぶでブックマーク
Pocketでブックマーク
RSSフィード

PHP composer, autoload機能を有効活用しよう!

php
イラストダウンロードサイト【イラストAC】
の画像をもとに加工しています。

PHPのオートロードはrequireを使わず、use演算子を定義して自動的にクラスをロードする機能です。

オートロードはPHPパッケージを管理するcomposerの一部で、PHPではかならず必要な機能です。

その機能の中身、使い方をくわしく、かんたんに、分かるように説明します。

オートロードってなんぞや?

オートロードは、requireなしで、use演算子を定義するだけで、PHPのクラスを使えるようにする機能です。

オートロードなしのクラスの使い方
<?php
require "TestClass1.php";
require "TestClass2.php";
require "TestClass3.php";

use TestClass1;
use TestClass2;
use TestClass3;

$test1 = new TestClass1();
$test2 = new TestClass2();
$test3 = new TestClass3();
オートロードのクラスの使い方
<?php
require vendor/autoload.php

use TestClass1;
use TestClass2;
use TestClass3;

$test1 = new TestClass1();
$test2 = new TestClass2();
$test3 = new TestClass3();

どこにもTestClass*を書いてないのに、TestClass*.phpを取り込んでいないのにエラーになりません。

TestClassはすでにオートロードがrequireしてくれたからです。

オブジェクト指向プログラミングでは大量のクラスを使います。そして、クラスは『1ファイル1クラス』というルールがあります。

オートロードがなければ、大量のrequireを書かないといけません。それをしないためにオートロードがあります。

autoloadを使ってみよう!

くわしい説明をする前にautoloadを使ってみましょう。

同じように作業するだけでいいです。

まず、composerがないと使えません。composerをPHP環境にインストールします。

composer.jsonファイルの作成

PHPのプロジェクトホームへ移動します。

ここでは、user-test/php-test-autoloadです。

...─ php-test-autoload
       ├─(空)

まだ、プロジェクトの中身は空っぽです。

ここでcomposerのコマンドを実行します。

composer.json作成コマンド
composer init

いろいろな入力を求められますが、とりあえず、ぜんぶ Enter でいいです。

...─ php-test-autoload
       ├─ composer.json

プロジェクトのホームにcomposer.jsonができました。

composer.json
{
    "name": "user-test/php-test-autoload",
    "authors": [
        {
            "name": "user-test",
            "email": "user-test@gmail.com"
        }
    ],
    "require": {}
}

authorsが空っぽでもいいです。これは、php.iniで設定していないと追加されません。

autoloadパッケージのインストール

プロジェクトにはcomposer.jsonしかありません。

つぎに、autoloadのパッケージをインストールします。

autoload インストールコマンド
composer install

autoloadパッケージがインストールされました。

...─ php-test-autoload
       ├─ vendor
       │    ├─ composer
       │    │    ├─ autoload_classmap.php
       │    │    ├─ autoload_namespaces.php
       │    │    ├─ autoload_psr4.php
       │    │    ├─ autoload_real.php
       │    │    ├─ autoload_static.php
       │    │    ├─ ClassLoader.php
       │    │    ├─ installed.php
       │    │    └─ LICENSE
       │    └─ autoload.php
       └─ composer.json

vendorディレクトリは、composer.jsonのrequireに追加するパッケージのインストール先です。

autoloadはcomposerの機能なので、vendor/composerディレクトリにインストールされました。

vendor/autoload.php

もありますね?

これをrequireするだけでオートロードすることができます。

autoloadはcomposerの基本機能なので、1回目のcomposer installコマンドで必ずインストールされます。

composer.jsonのrequireが空っぽでも同じ。

(compsoer.jsonのrequireはプロジェクトにインストールするパッケージリストです。)

PHPのサンプルプログラム作成

autoloadのパッケージがプロジェクトに追加されました。

こんどは、プロジェクトにサンプルプログラムを追加します。

...─ php-test-autoload
       ├─ src
       │    ├─ main.php
       │    ├─ TestClass1.php
       │    ├─ Test2
       │    │    └─ TestClass2.php
       │    └─ Test3
       │         └─ TestClass3.php
       ├─ vendor
       │    ├─ composer
       │    │    ├─ autoload_classmap.php
       │    │    ├─ autoload_namespaces.php
       │    │    ├─ autoload_psr4.php
       │    │    ├─ autoload_real.php
       │    │    ├─ autoload_static.php
       │    │    ├─ ClassLoader.php
       │    │    ├─ installed.php
       │    │    └─ LICENSE
       │    └─ autoload.php
       └─ composer.json
TestClass1.php
<?php

namespace Origin;

class TestClass1 {
    function __construct() {
        echo "new instance TestClass1\n";
    }
}
TestClass2.php
<?php

namespace Origin\Test2;

class TestClass2 {
    function __construct() {
        echo "new instance TestClass2\n";
    }
}

TestClass3も同じようにします。

TestClass1とTestClass2, TestClass3のnamespaceがちがうところに注意。

あとで出てきますが、今回はpsr4というコーディング規約を使います。psr4では、

  • クラスファイルはnamespaceが必須。
  • namespaceとディレクトリ構成、名称は一致させる。
  • namespace名は大文字からはじめる。

のルールがあります。

PSR (PHP Standards Recommendations)

https://www.php-fig.org/psr/

PHP標準勧告。PHPコーディングの標準化を目指す活動のこと。PHP-FIGが策定している。

PHP-FIG (PHP Framework Interop Group)

http://www.php-fig.org/

PHPフレームワーク相互運用グループ。PHPプロジェクトが集まって意見を出し合い、お互いの製品の互換性を調整する団体。

有名なプロジェクトが多く参加している。

main.php
<?php

require "vendor/autoload.php";


use Origin\TestClass1;
use Origin\Test2\TestClass2;
use Origin\Test3\TestClass3;

new TestClass1();
new TestClass2();
new TestClass3();

composer.jsonの編集

クラスファイルがあるディレクトリを、autoloadが取り込めるように登録します。

登録は、composerの設定ファイル、composer.jsonでおこないます。

composer.jsonにautoload登録
{
    "name": "user-test/php-test-autoload",
    "authors": [
        {
            "name": "user-test",
            "email": "user-test@gmail.com"
        }
    ],
    "require": {},
    "autoload": {
        "psr-4": {
            "Origin\\": "src/"
        }
    }
}

autoload{}で、srcディレクトリにあるクラスファイルはOriginからはじまるように登録しています。

psr4では、namespace名は大文字からはじめなければならないので、srcは使えません。

ここでは、クラスをロードするときにsrcをOriginに変換してnamespaceと一致させます。

ディレクトリ構成とネームスペース構成を一致させる

composerを使ってパッケージをインストールしたときにcomposer.jsonが更新されます。

パッケージのクラスは自動的にautoload{}に追加されます。自分で作業する必要はありません。

今回は、自作のプログラムでcomposerのパッケージではないので直接編集しました。

composer.jsonを直接編集したときは

composer validate

コマンドを必ず実行します。

これは、composer.jsonの構文チェックコマンドです。

エラーが出ると編集したところがまちがっています。

composerコマンドが使えなくなるので気をつけましょう。

autoloadのマップファイル更新

autoloadを更新します。

autoload アップデートコマンド
composer update

正確には、composer.jsonの設定を更新します。autoload{}を追加したので、autoloadも更新します。

autoloadの仕組みはかんたん。

composer install

composer update

composer require

のコマンドを実行すると、マップファイルを作成・更新します。

マップファイルの中身はただの配列で、クラスやネームスペースが定義されています。

オートロードってクラスをロードしているんじゃなくて定義されたクラスを参照しているだけなんですね?

...─ php-test-autoload
       └─ vendor
            └─ composer
                 ├─ autoload_classmap.php
                 ├─ autoload_namespaces.php
                 ├─ autoload_psr4.php
                 ├─ autoload_static.php
                 └─ installed.php

さっきみた、autoloadのこれらのファイルがマップファイルです。

composer.jsonで、psr4のautoload登録をしたので、

autoload_psr4.php
<?php

// autoload_psr4.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'Origin\\' => array($baseDir . '/src'),
);

こんなかんじで更新されます。

きちんとsrc -> Originの変換がマップに登録されてます。

composerコマンドでcomposer.jsonファイルを更新すると、autoload{}で定義した内容をautoloadのマップファイルに展開する。

vendor/autoload.phpは、すべてのマップファイルのまとめ役です。

だから唯一requireします。

プログラムを実行してみよう!

autoloadのサンプルプログラムが完成しました。これを実行してみましょう。

実行確認
php src/main.php
new instance TestClass1
new instance TestClass2
new instance TestClass3

プロジェクトのホームで実行して同じ結果が出たら、autoloadの使い方はバッチリです。

autoloadマップの更新

さっきは、

composer update

でマップファイルを更新しました。

でもこのコマンドは、composer.jsonファイルの更新に使うもので、マップの更新につかうものではありません。

たとえば、ソースコードを追加したときのクラスはマップに登録されていません。

composer.jsonを編集していないので"composer update"コマンドも使えません。

そのときは、

autoloadマップ更新コマンド
composer dump-autoload

をつかいます。

これは、autoloadのマップだけを再構築します。

Class not Found

が発生したら実行しましょう。

意外と、プログラムのバグではなくマップが更新されてないだけのときがあります。

dump-autoload -o を使うときは要注意!

autoloadの高速化
composer dump-autoload -o

autoloadには、

Autoloader Optimization

という高速に読み込むためのマップの最適化機能があります。

オプション-oをつけます。しかし注意が必要です。

このオプションをつけると、クラスマップを再構築するときpsr-4のルールを無視します。

psr-4に準拠しないnamespaceとディレクトリ構成のクラスファイルもクラスマップに登録されます。

とつぜん、

Class not Found

が出まくるときもあります。

オプションをつけてマップ更新していて、あるときオプションをつけずに更新したときに起きます。

意外とこのパターンは多いです。

Laravelではよく起きる現象なので注意が必要です。

開発環境はオプションなし

本番環境はオプションあり

という使い方をしたほうがいいでしょう。

クラス以外もオートロードできる

autoloadはクラス以外でもオートロードできます。

  • インタフェース
  • function
  • const
いろいろなautoload
<?php
require vendor/autoload.php;

use My\Full\ClassName as ClassName;
use My\Full\InterfaceName as IFName;

class Test extends ClassName implements IFName {
    // ...
}
 
// >= PHP 5.6
use function My\Full\functionName as func;

$ret = func();
 
// >= PHP 5.6
use const My\Full\CONSTANT CONST_A;

$val = CONST_A;

ただし、function, constはPHPのバージョンが5.6以降でないと対応していません。

Laravelにはすでに入っている

PHPのWebフレームワーク、Laravelにはcomposerが入っています。

composer.jsonもありますし、vendor/composerにはautoloadのパッケージもあります。

require vendor/autoload.php

も必要ありません。

すでに、public/index.phpに実装されています。

autoloadのまとめ

  • "require vendor/autoload.php"をソースコードに1回だけ書く。
  • use演算子でクラス、インタフェース、function、constがオートロードできる。
  • 設定はcomposer.json

autoloadの基本的な使い方はこれだけです。

『ここで終わり』と行きたいところですが、ちょっと上級編をつづけます。

composer.jsonのautoload{}でつかったpsr4の説明もしていませんでしたね?

そのほかの指定方法も解説します。

autoloadで指定する種類

composer.jsonのautoload{}は、psr-4以外にもいろいろな指定方法があります。

ひとつひとつ見ていきましょう。

files

"autoload": {
    "files": [
        "src/functions/func1.php",
        "src/const/const1.php",
    ]
}

.phpファイルからfunctionやconstをオートロードします。

クラスやインタフェース以外のときに使います。

マップファイル

vendor/composer/autoload_files.php

psr-4

"autoload": {
    "psr-4": { "Vendor\\": "src/vendor/" }
}
複数指定
"autoload": {
    "psr-4": { "Vendor\\": ["src/Vendor/", "lib/Vendor/"] }
}

Laravelなど、psrに準拠したものに使います。

psr-4はネームスペースとディレクトリ構成は一致させます。

そのトップレベルのネームスペースのディレクトリの位置を指定します。

[]で括って複数指定することもできます。

PHPではPSRに準拠することがふつうで、WordPressのように参加していないほうが珍しいです。

(といっても参加していないプロジェクトは多いが。)

psr-4でネームスペースとディレクトリ構成が一致しないとき、アプリケーション実行時に

Class not Found

が発生します。

パッケージ自体のエラーは発生しないので、あたかもアプリケーションにバグがあるかのように見えます。

autoloadのマップ情報が古いか、パッケージのバグの可能性があります。

psr-4には、psr-0で設定する内容も含まれます。

あとで説明するpsr-0の設定はいりません。

マップファイル

vendor/composer/autoload_psr-4.php

vendor/composer/autoload_static.php

vendor/composer/autoload_classmap.php

psr-0

"autoload": {
    "psr-0": {
        "Vendor\\": "src/Vendor/",
        "Vendor\\Namespace\\": "src/Vendor/",
        "Vendor_Namespace_": "src/"
    }
}

いまのpsrのレベルは4が主流です。

レベルが大きいpsrはそれ以下のレベルも含むのでpsr-0はほとんど使うことはありません。

数年前からつづいてきたプロジェクトなど、古いソースコードや、psr-2まで準拠しているもので使います。

composerのautoloadにはpsr-2はありません。

マップファイル

vendor/composer/autoload_classmap.php

classmap

"autoload": {
    "classmap": ["src/", "lib/", "Something.php"]
}

WordPressなど、psrに準拠しないときに使います。

マップファイル

vendor/composer/autoload_classmap.php

exclude-from-classmap

"autoload": {
    "exclude-from-classmap": ["/Tests/", "/test/", "/tests/"]
}

autoloadの除外設定をします。

テストクラスなど本番環境では使わないクラスを指定します。

マップファイル

vendor/composer/autoload_classmap.php

開発環境のautoload

開発環境のautoloadを設定します。

テストクラスなどを指定し、指定できるディレクトリはルートディレクトリだけです。

前の投稿
PHP composer, あれ?開発版がインストールされる。設定がそうなってた。
PHP composer, globalのホームパスはどこ?パッケージのインストール先を知りたい
次の投稿
コメントを残す

*