- PHP
PHP namespaceとuseの使い方|名前空間とPSR-4を図解
PHPの名前空間(namespace)とは、クラス・関数・定数の名前に「住所」をつけて、同じ名前どうしがぶつからないようにする仕組みです。 use はその長い住所つきの名前を、ファイルの中で短い名前で呼べるようにする宣言です。そして PSR-4 は、「名前空間の住所」と「ファイルの置き場所」を対応させる決まりで、Composer のオートロードがこの決まりに沿ってクラスのファイルを自動で読み込みます。
この3つは別々に説明されることが多いのですが、つまずきの大半は「3つの対応がどこかでずれている」ことから起こります。この記事では、ディレクトリ構成・composer.json・namespace 宣言・use 文の対応を1つの図にまとめ、そのまま動く最小サンプルを PHP 8.4.21 と Composer 2.8.12 で実行した結果を載せています。「Class not found」も原因別に再現し、実際のエラーメッセージと直し方を並べました。
namespaceとuseの早見表
use 文の書き方の一覧です。
| やりたいこと | 書き方 | そのあとの呼び方 |
|---|---|---|
| 名前空間を宣言する | namespace App\Model; |
(ファイルの先頭に1つ) |
| クラスを取り込む | use App\Model\Item; |
new Item() |
| 別名をつける | use App\Model\Item as Product; |
new Product() |
| まとめて取り込む(グループ use) | use App\{Model\Item, Service\CartService}; |
new Item()、new CartService() |
| 関数を取り込む | use function App\Support\with_tax; |
with_tax(100) |
| 関数に別名をつける | use function App\Support\with_tax as tax; |
tax(100) |
| 定数を取り込む | use const App\Support\TAX_RATE; |
TAX_RATE |
| 名前空間そのものを取り込む | use App\Support; |
Support\with_tax(100) |
| use せずに直接呼ぶ | (なし) | new \App\Model\Item() |
| 組み込みのクラスを呼ぶ | use DateTimeImmutable; または先頭に \ |
new \DateTimeImmutable() |
| クラスの完全な名前を文字列で得る | Item::class |
"App\Model\Item" |
名前の書き方は3種類あり、解決のされ方が違います(namespace App\Demo; のファイルの中で書いた場合)。
| 名前の種類 | 見分け方 | 例 | 解決される名前 |
|---|---|---|---|
| 完全修飾名 | 先頭が \ |
\App\Model\Item |
App\Model\Item(書いたとおり) |
| 修飾名 | 途中に \ がある |
Model\Item |
App\Demo\Model\Item(今の名前空間が前につく) |
| 非修飾名 | \ がない |
Item |
use があればその名前、なければ App\Demo\Item |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「PHP namespaceとuseの使い方|名前空間とPSR-4を図解」
名前空間とは何か
PHP では、同じ名前のクラスを2つ定義できません。自分で作った Item クラスと、導入したライブラリの中の Item クラスが同じ名前だと、読み込んだ時点で止まります。
名前空間を使うと、クラスの正式な名前は「名前空間 + クラス名」になります。
| 宣言 | クラスの正式な名前 |
|---|---|
namespace App\Model; の中の class Item |
App\Model\Item |
namespace Vendor\Catalog; の中の class Item |
Vendor\Catalog\Item |
どちらも短い名前は Item ですが、正式な名前が違うので共存できます。フォルダが違えば同じ名前のファイルを置けるのと同じ考え方です。区切りの記号は \(バックスラッシュ)です。
名前空間に入るのは、クラス・インターフェース・トレイト・列挙型・関数・定数(const で定義したもの)です。変数は名前空間の影響を受けません。
ディレクトリ構成・composer.json・namespace・useの対応図
ここからは、実際に動くサンプルで対応を見ていきます。題材は、商品をカートに入れて税込みの合計を出す小さなプログラムです。
shop/
├── composer.json
├── public/
│ └── index.php … 入口(オートローダーを読み込む)
├── src/ … composer.json で App\ に対応させる場所
│ ├── Model/
│ │ └── Item.php … App\Model\Item
│ ├── Service/
│ │ └── CartService.php … App\Service\CartService
│ └── Support/
│ └── helpers.php … App\Support の関数と定数
└── vendor/ … composer dump-autoload で作られる
└── autoload.php
4つの要素の対応は次の図のとおりです。
flowchart LR
A["composer.json<br>psr-4: App\\ を src/ に対応"] --> B["ディレクトリ<br>src/Model/Item.php"]
B --> C["namespace 宣言<br>namespace App\Model;<br>class Item"]
C --> D["use 文<br>use App\Model\Item;<br>new Item()"]
D -. "クラスが未読み込みなら<br>オートローダーが探す" .-> A
App\Model\Item という名前から、ファイルの場所が決まる流れを表にします。
| 部分 | クラス名の中での位置 | ファイルの場所での位置 | 決めているもの |
|---|---|---|---|
| 接頭辞 | App\ |
src/ |
composer.json の psr-4 |
| 途中の名前空間 | Model\ |
Model/ |
ディレクトリ名(大文字小文字も一致させる) |
| クラス名 | Item |
Item.php |
ファイル名(大文字小文字も一致させる) |
接頭辞より後ろは、\ を / に置き換えて、最後に .php をつけるだけです。これが PSR-4 の対応の考え方です(PSR-4 の文書そのものは今回開いておらず、一般に知られた仕様と、次に示す実行結果にもとづく説明です)。
そのまま動く最小サンプル
5つのファイルを作ります。
composer.json:
{
"name": "example/shop",
"autoload": {
"psr-4": {
"App\\": "src/"
},
"files": ["src/Support/helpers.php"]
}
}
JSON の中では \ を2つ重ねて App\\ と書きます。末尾の \\ も必要です。files は、関数や定数のファイルを毎回読み込むための指定です(理由は後述します)。
src/Model/Item.php:
<?php
declare(strict_types=1);
namespace App\Model;
final class Item
{
public function __construct(
public readonly string $name,
public readonly int $price,
) {}
}
src/Support/helpers.php:
<?php
declare(strict_types=1);
namespace App\Support;
const TAX_RATE = 0.10;
function with_tax(int $price): int
{
return (int) floor($price * (1 + TAX_RATE));
}
src/Service/CartService.php:
<?php
declare(strict_types=1);
namespace App\Service;
use App\Model\Item;
use function App\Support\with_tax;
use const App\Support\TAX_RATE;
final class CartService
{
/** @var Item[] */
private array $items = [];
public function add(Item $item): void
{
$this->items[] = $item;
}
public function total(): int
{
$sum = array_sum(array_map(fn(Item $i) => $i->price, $this->items));
return with_tax($sum);
}
public function taxRate(): float
{
return TAX_RATE;
}
}
public/index.php:
<?php
declare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use App\Model\Item;
use App\Service\CartService;
$cart = new CartService();
$cart->add(new Item('ノート', 300));
$cart->add(new Item('ペン', 120));
echo "合計(税込): " . $cart->total() . " 円\n";
echo "税率: " . $cart->taxRate() . "\n";
echo "クラス名: " . CartService::class . "\n";
オートローダーを生成して実行します。
cd shop
composer dump-autoload
php public/index.php
実行結果(PHP 8.4.21、Composer 2.8.12):
Generating autoload files
Generated autoload files
合計(税込): 462 円
税率: 0.1
クラス名: App\Service\CartService
require で読み込んだのは vendor/autoload.php の1つだけですが、Item.php と CartService.php は必要になった時点で自動的に読み込まれています。composer dump-autoload が作った対応表(vendor/composer/autoload_psr4.php)の中身は次のとおりでした。
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'App\\' => array($baseDir . '/src'),
);
composer.json に書いた「App\ は src/」という対応が、そのまま記録されています。
書く位置の決まり
| 宣言 | 書く位置 |
|---|---|
declare(strict_types=1); |
ファイルの最初(namespace より前に書ける唯一の文) |
namespace ...; |
declare の次。ほかのコードや出力より前 |
use ...; |
namespace の次。クラス定義より前 |
| クラス・関数の定義 | そのあと |
namespace の前に出力などを書くと、次のメッセージで止まります(実行して確認)。
PHP Fatal error: Namespace declaration statement has to be the very first statement or after any declare call in the script
use・as・グループuse・use function・use constの使い方
サンプルの public/ に次のファイルを足して、use の書き方をひととおり実行します。
<?php
declare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use App\Model\Item as Product; // as で別名
use App\{Model\Item, Service\CartService}; // グループ use
use function App\Support\with_tax as tax; // 関数に別名
use const App\Support\TAX_RATE;
use App\Support; // 名前空間そのものを取り込む
echo Product::class . "\n";
echo Item::class . "\n";
echo CartService::class . "\n";
echo tax(1000) . "\n";
echo TAX_RATE . "\n";
echo Support\with_tax(200) . "\n"; // 修飾名(Support は use 済み)
echo \App\Support\with_tax(300) . "\n"; // 完全修飾名
echo \strlen('abc') . "\n";
実行結果:
App\Model\Item
App\Model\Item
App\Service\CartService
1100
0.1
220
330
3
1行目と2行目が同じになっています。as でつけた Product は、そのファイルの中だけで使える別名で、クラスの正式な名前は App\Model\Item のままです。
それぞれの使いどころです。
| 書き方 | 向いている場面 |
|---|---|
use A\B\C; |
基本の形。1クラスにつき1行 |
use A\B\C as D; |
同じ短い名前のクラスを2つ使う。名前が長い・意味が伝わりにくい |
use A\{B\C, D\E}; |
同じ接頭辞のクラスをたくさん取り込む |
use function A\f; |
名前空間つきの関数を短い名前で呼ぶ |
use const A\X; |
名前空間つきの定数を短い名前で使う |
use A\B;(名前空間) |
B\f()、B\C のように、出どころを見せながら呼ぶ |
同じ名前を2つ use するとどうなるか
短い名前が同じクラスを2つ取り込むと、次のメッセージで止まります(実行して確認)。
<?php
namespace App\Demo;
use App\Model\Item;
use Other\Item;
PHP Fatal error: Cannot use Other\Item as Item because the name is already in use
片方に as で別名をつければ解決します。
use App\Model\Item;
use Other\Item as OtherItem;
use した名前と同じ名前のクラスを、同じファイルで定義した場合も止まります。
PHP Fatal error: Cannot redeclare class App\Demo\Item (previously declared as local import)
use は「読み込み」ではなく「名前の登録」
use 文は、ファイルを読み込む命令ではありません。「このファイルで Item と書いたら App\Model\Item のこと」という名前の対応を登録するだけです。実際にファイルを読み込むのはオートローダーで、それも new Item() などでクラスが必要になった瞬間に動きます。
このため、存在しないクラスを use しても、その行ではエラーになりません。エラーが出るのは、そのクラスを使おうとした行です。
名前解決のルールを実行して確かめる
冒頭の早見表にある3種類の名前が、実際にどう解決されるかを ::class で表示して確かめます。::class はクラスを読み込まずに、解決後の名前だけを文字列で返します。
<?php
namespace App\Demo;
use App\Model\Item;
function strlen(string $s): string { return "App\\Demo\\strlen が呼ばれました"; }
const E_ALL = 'App\\Demo の E_ALL';
echo "1 " . Item::class . "\n"; // 非修飾名 + use あり
echo "2 " . Foo::class . "\n"; // 非修飾名 + use なし
echo "3 " . Model\Item::class . "\n"; // 修飾名 + use なし
echo "4 " . \App\Model\Item::class . "\n"; // 完全修飾名
echo "5 " . namespace\Foo::class . "\n"; // namespace 演算子(相対名)
echo "6 " . __NAMESPACE__ . "\n";
echo "7 " . strlen('abc') . "\n"; // 現在の名前空間の関数が優先
echo "8 " . \strlen('abc') . "\n"; // グローバルの組み込み関数
echo "9 " . strtoupper('abc') . "\n"; // 名前空間に無い関数はグローバルへフォールバック
echo "10 " . E_ALL . " / " . \E_ALL . "\n";
echo "11 " . PHP_VERSION . "\n"; // 定数もフォールバック
実行結果:
1 App\Model\Item
2 App\Demo\Foo
3 App\Demo\Model\Item
4 App\Model\Item
5 App\Demo\Foo
6 App\Demo
7 App\Demo\strlen が呼ばれました
8 3
9 ABC
10 App\Demo の E_ALL / 30719
11 8.4.21
結果をルールとして整理します。PHP マニュアルの「名前解決のルール」のページを今回開いて、内容が合っていることを確認しました。
| 番号 | 書いた名前 | 種類 | 解決された名前 | ルール |
|---|---|---|---|---|
| 1 | Item |
非修飾名(use あり) | App\Model\Item |
use の対応表が使われる |
| 2 | Foo |
非修飾名(use なし) | App\Demo\Foo |
今の名前空間が前につく |
| 3 | Model\Item |
修飾名(use なし) | App\Demo\Model\Item |
最初の部分が use になければ、今の名前空間が前につく |
| 4 | \App\Model\Item |
完全修飾名 | App\Model\Item |
先頭の \ を外しただけ |
| 5 | namespace\Foo |
相対名 | App\Demo\Foo |
namespace が今の名前空間に置き換わる |
3番は見落としやすいところです。Model\Item と書いても App\Model\Item にはなりません。 途中から書いた名前は「今いる場所からの相対パス」として扱われます。
関数と定数だけはグローバルへフォールバックする
7〜11番は、関数と定数の動きです。
| 番号 | 書いた名前 | 結果 | 説明 |
|---|---|---|---|
| 7 | strlen('abc') |
App\Demo\strlen が呼ばれた |
今の名前空間に同じ名前の関数があれば、そちらが優先 |
| 8 | \strlen('abc') |
3 | 先頭に \ をつけると必ず組み込みの関数 |
| 9 | strtoupper('abc') |
ABC | 今の名前空間になければ、グローバルの関数を探す |
| 10 | E_ALL / \E_ALL |
独自の値 / 30719 | 定数も同じ動き |
| 11 | PHP_VERSION |
8.4.21 | 名前空間になければグローバルの定数 |
非修飾名の関数と定数は、今の名前空間で見つからなければグローバルを探します。クラスにはこのフォールバックがありません。 この違いが、「名前空間の中で strlen() はそのまま呼べるのに、new DateTime() は Class not found になる」理由です。
| 種類 | 今の名前空間にないとき |
|---|---|
| クラス・インターフェース・トレイト・列挙型 | フォールバックしない(Class not found) |
| 関数 | グローバルの関数を探す |
| 定数 | グローバルの定数を探す |
なお、フォールバックするのはグローバルに対してだけです。別の名前空間にある関数は、use function しない限り見つかりません。App\Demo の中で with_tax(100) を use なしで呼んだ結果は次のとおりでした。
Call to undefined function App\Demo\with_tax()
Class not foundを原因別に再現して直す
ここからは、先ほどのサンプルに手を加えて「Class not found」を再現します。パスは環境に合わせて /home/taro/shop に置き換えています。先に、原因と直し方の一覧です。
| 原因 | エラーメッセージの特徴 | 直し方 |
|---|---|---|
組み込みクラスの先頭の \ 抜け |
Class "App\Service\DateTimeImmutable" not found と、今の名前空間がついた名前が出る |
\DateTimeImmutable と書くか use DateTimeImmutable; |
| ファイル名・ディレクトリ名の大文字小文字の不一致 | クラス名は正しいのに not found | ファイル名とクラス名、ディレクトリ名と名前空間をそろえる |
| namespace 宣言とパスのずれ | クラス名は正しいのに not found | namespace 宣言をディレクトリ構成に合わせる |
| dump-autoload 忘れ | composer.json に足した接頭辞のクラスだけ not found | composer dump-autoload を実行する |
| autoload.php を読み込んでいない | すべてのクラスが not found | 入口で require 'vendor/autoload.php'; |
| 文字列のクラス名に短い名前を使った | Class "Item" not found と、名前空間なしの名前が出る |
Item::class を使う |
エラーメッセージに出ているクラス名を見ると、原因の見当がつきます。 名前が思っているものと違えば「名前の解決」の問題、名前が正しければ「ファイルの場所」の問題です。
原因1:先頭の \ 抜け
名前空間の中で、組み込みのクラスをそのまま書いた例です。
<?php
declare(strict_types=1);
namespace App\Service;
final class Clock
{
public function today(): string
{
$d = new DateTimeImmutable('2026-10-03');
return $d->format('Y-m-d');
}
}
PHP Fatal error: Uncaught Error: Class "App\Service\DateTimeImmutable" not found in /home/taro/shop/src/Service/Clock.php:10
メッセージのクラス名が App\Service\DateTimeImmutable になっています。非修飾名のクラスには今の名前空間がつき、グローバルへのフォールバックもないためです。
直し方は2通りあります。
// 方法1:先頭に \ をつける
$d = new \DateTimeImmutable('2026-10-03');
// 方法2:ファイルの先頭で use する
use DateTimeImmutable;
直したあとの実行結果:
2026-10-03
同じことが Exception、PDO、Throwable、stdClass などすべての組み込みクラスで起こります。とくに catch (Exception $e) は、\ が抜けていてもエラーにならず、例外を受け取れないまま素通りするので気づきにくい箇所です(実行して確認。Uncaught RuntimeException になりました)。
原因2:大文字小文字の不一致
クラス名は Order なのに、ファイル名を小文字の order.php にした例です。
<?php
// src/Model/order.php
namespace App\Model;
final class Order {}
PHP Fatal error: Uncaught Error: Class "App\Model\Order" not found in /home/taro/shop/public/nf2.php:3
オートローダーは src/Model/Order.php を探しますが、Linux では大文字と小文字が区別されるため、order.php は見つかりません。ファイル名を Order.php に変えると動きました。
object(App\Model\Order)#2 (0) {
}
呼び出す側で名前空間の大文字小文字を変えた場合も同じです。new App\model\Item('a', 1) と書くと次のようになりました。
PHP Fatal error: Uncaught Error: Class "App\model\Item" not found in /home/taro/shop/public/nf2b.php:3
src/model/Item.php を探しに行くためです。
この原因は、開発用のパソコンでは動くのにサーバーでは動かない、という形で現れることがあります。 Windows や macOS の標準的な設定ではファイル名の大文字小文字が区別されないためです(この環境差は一般に知られた性質で、今回実行したのは Linux だけです。Windows・macOS での動作は未実行です)。
原因3:namespace宣言とパスのずれ
ディレクトリは src/Repository/ なのに、namespace を App\Repositories と複数形で書いた例です。
<?php
// src/Repository/ItemRepository.php
namespace App\Repositories;
final class ItemRepository {}
PHP Fatal error: Uncaught Error: Class "App\Repository\ItemRepository" not found in /home/taro/shop/public/nf3.php:3
ファイルは見つかって読み込まれますが、その中で定義されているのは App\Repositories\ItemRepository なので、求められた名前のクラスは存在しないままです。
この種のずれは、composer dump-autoload -o を実行すると見つけてもらえます。
Generating optimized autoload files
Class App\Repositories\ItemRepository located in ./src/Repository/ItemRepository.php does not comply with psr-4 autoloading standard (rule: App\ => ./src). Skipping.
Generated optimized autoload files containing 5 classes
「PSR-4 の決まりに合っていない」と、ファイル名つきで教えてくれます。namespace を App\Repository に直すと動きました。
原因4:dump-autoload忘れ
composer.json に新しい接頭辞を足したあと、オートローダーを作り直していない例です。
{
"name": "example/shop",
"autoload": {
"psr-4": {
"App\\": "src/",
"Tools\\": "lib/"
},
"files": [
"src/Support/helpers.php"
]
}
}
lib/Report/Csv.php に Tools\Report\Csv を作って呼ぶと、次のようになります。
PHP Fatal error: Uncaught Error: Class "Tools\Report\Csv" not found in /home/taro/shop/public/nf4.php:3
composer.json を書き換えただけでは、vendor/composer/ の中の対応表は変わりません。composer dump-autoload を実行すると読み込めるようになりました。
Generating autoload files
Generated autoload files
object(Tools\Report\Csv)#2 (0) {
}
dump-autoload が必要になる場面を整理します。
| 変更の内容 | dump-autoload |
|---|---|
| すでに登録済みの接頭辞の下に、クラスのファイルを足した | 不要(PSR-4 はその都度ファイルを探す) |
composer.json の psr-4 に接頭辞を足した・変えた |
必要 |
composer.json の files や classmap を変えた |
必要 |
--classmap-authoritative で生成したあとにクラスを足した |
必要 |
4行目も実行して確かめました。composer dump-autoload -o(最適化)のあとに足した App\Model\Tag は読み込めましたが、composer dump-autoload --classmap-authoritative のあとに足した App\Model\Memo は次のようになりました。
PHP Fatal error: Uncaught Error: Class "App\Model\Memo" not found in /home/taro/shop/public/nf4b.php:3
--classmap-authoritative は「一覧に載っているクラスだけを読み込み、載っていなければファイルを探しに行かない」という動きになるためです。公開用のビルドで使うことが多いオプションなので、公開の手順の中で、ファイルを配置したあとに dump-autoload を実行するようにしておくと安心です。
原因5:autoload.phpを読み込んでいない
<?php
use App\Model\Item;
var_dump(new Item('a', 1));
PHP Fatal error: Uncaught Error: Class "App\Model\Item" not found in /home/taro/shop/public/nf5.php:3
use 文は名前を登録するだけなので、オートローダーがなければファイルは読み込まれません。入口のファイルで一度だけ require __DIR__ . '/../vendor/autoload.php'; を書きます。
原因6:文字列のクラス名に短い名前を使った
クラス名を変数に入れて new する場合、use の対応表は使われません。
<?php
namespace App\Demo;
require __DIR__ . '/../vendor/autoload.php';
use App\Model\Item;
$class = 'Item';
try { new $class('a', 1); } catch (\Error $e) { echo $e->getMessage() . "\n"; }
$class = Item::class;
echo get_class(new $class('a', 1)) . "\n";
Class "Item" not found
App\Model\Item
文字列の中の名前は、常に完全な名前として扱われます。Item::class と書けば、use を反映した完全な名前の文字列になるので、文字列でクラス名を渡す場面ではこの書き方が確実です。
確認の手順
Class not found に出会ったときの、確認の順番です。
| 順 | 確認すること | 方法 |
|---|---|---|
| 1 | エラーメッセージのクラス名は思ったとおりか | 違えば \ 抜けか use の書きまちがい |
| 2 | vendor/autoload.php を読み込んでいるか |
入口のファイルを見る |
| 3 | 接頭辞が対応表にあるか | vendor/composer/autoload_psr4.php を開く |
| 4 | クラス名からファイルのパスを組み立てて、その場所にあるか | 大文字小文字まで比べる |
| 5 | ファイルの中の namespace 宣言がパスと合っているか | composer dump-autoload -o の警告を見る |
| 6 | 対応表を作り直したか | composer dump-autoload |
関数と定数はなぜfilesで読み込むのか
サンプルの composer.json では、helpers.php を files に書きました。これは、PHP のオートロードがクラス(とインターフェース・トレイト・列挙型)にしか働かないためです。関数や定数は、使われた瞬間に自動で読み込まれることがありません。
| 対象 | 読み込み方 |
|---|---|
| クラス・インターフェース・トレイト・列挙型 | psr-4 で必要になったときに自動で読み込む |
| 関数・定数 | files に書いて、autoload.php の読み込み時に毎回読み込む |
files に書いたファイルは毎回読み込まれるので、数が増えすぎないようにまとめておくとよいでしょう。関数を静的メソッドとしてクラスにまとめれば、psr-4 の自動読み込みに乗せることもできます。
Composerなしでオートロードの仕組みを確かめる
Composer が中でしていることは、spl_autoload_register() という標準の関数で再現できます。仕組みを理解するための最小の形です。
<?php
declare(strict_types=1);
spl_autoload_register(function (string $class): void {
$prefix = 'App\\';
$baseDir = __DIR__ . '/src/';
echo "[autoload] {$class} を探します\n";
if (!str_starts_with($class, $prefix)) {
return; // 担当外の名前空間は他のオートローダーに任せる
}
$relative = substr($class, strlen($prefix));
$file = $baseDir . str_replace('\\', '/', $relative) . '.php';
echo "[autoload] → " . str_replace(__DIR__, '.', $file) . "\n";
if (is_file($file)) {
require $file;
}
});
$item = new App\Model\Item('ノート', 300);
echo $item->name . "\n";
var_dump(class_exists('App\Model\Nothing'));
実行結果(src/Model/Item.php は先ほどと同じもの):
[autoload] App\Model\Item を探します
[autoload] → ./src/Model/Item.php
ノート
[autoload] App\Model\Nothing を探します
[autoload] → ./src/Model/Nothing.php
bool(false)
未定義のクラスが必要になると、登録した関数に完全なクラス名が渡されます。そこから接頭辞を外し、\ を / に置き換え、.php をつけてファイルを探す。PSR-4 のオートロードは、この文字列の置き換えにほかなりません。 学習用にはこの形で十分ですが、普段の開発では Composer に任せるのが手軽です。
composer dump-autoloadのオプション
| コマンド | 動き | 向いている場面 |
|---|---|---|
composer dump-autoload |
接頭辞とディレクトリの対応だけを記録。クラスはその都度探す | 開発中 |
composer dump-autoload -o |
全クラスの一覧を作る。一覧にないクラスは従来どおり探す。PSR-4 に合わないファイルを警告する | 公開前の確認、ずれの検出 |
composer dump-autoload --classmap-authoritative(-a) |
全クラスの一覧を作り、一覧にないクラスは探さない | 公開用。クラスを足したら作り直す |
3つとも今回実行し、表に書いた動きになることを確認しています。
よくある質問
Q. use を書けば require は不要になりますか?
A. use だけでは不要になりません。use は名前の対応を登録するだけで、ファイルは読み込みません。ファイルを読み込むのはオートローダーです。入口で vendor/autoload.php を一度 require しておけば、各クラスのファイルを個別に require する必要はなくなります。
Q. 名前空間の中で strlen() は動くのに new DateTime() が動かないのはなぜですか?
A. 関数と定数は、今の名前空間で見つからなければグローバルを探しますが、クラスにはこの動きがないためです。クラスは new \DateTime() と先頭に \ をつけるか、use DateTime; を書きます。
Q. 名前空間とディレクトリは必ず一致させる必要がありますか? A. PHP の文法としては一致させなくても動きます。ただし Composer の PSR-4 オートロードを使う場合は、接頭辞より後ろの名前空間とディレクトリ、クラス名とファイル名を、大文字小文字も含めて一致させる必要があります。ずれていると、今回再現したように Class not found になります。
Q. グループ use と1行ずつの use はどちらがよいですか? A. 動きは同じです。1行ずつ書くと、差分が見やすく、並べ替えや検索もしやすくなります。同じ接頭辞から多くのクラスを取り込むときはグループ use で行数を減らせます。チームのコーディング規約があればそれに合わせます。
まとめ
- 名前空間は名前に住所をつける仕組み、use は短い名前で呼ぶための登録、PSR-4 は住所とファイルの場所を対応させる決まりです。
- 接頭辞(
App\)を composer.json でsrc/に対応させ、その後ろは\を/に置き換えて.phpをつけると、ファイルの場所になります。 - use には as・グループ use・use function・use const があります。 as の別名はそのファイルの中だけで有効です。
- 先頭が
\の名前は書いたとおり、途中に\がある名前と\のない名前は今の名前空間が基準になります。 - 関数と定数だけがグローバルへフォールバックします。 クラスは
\か use が必要です。 - Class not found は、メッセージのクラス名を見て切り分けます。 名前が違えば
\抜けや use、名前が正しければ大文字小文字・パスのずれ・dump-autoload を確かめます。 composer dump-autoload -oは PSR-4 に合わないファイルを警告してくれるので、ずれの検出に使えます。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「PHP namespaceとuseの使い方|名前空間とPSR-4を図解」
株式会社RJCでは、PHPの名前空間やオートロードのような土台の仕組みを仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。