Help us understand the problem. What is going on with this article?

Laravelの標準ディレクトリの変更方法 まとめ

More than 1 year has passed since last update.

なにがしたい?

Laravelは「ディレクトリ構成が自由」と言われますが、それはネームスペースで管理されるクラスとそのPHPファイルのお話なんだと思います。

そうではなくて、Laravelフレームワークのシステムファイルや重要なデータが入っていそうな「標準のディレクトリ」≒「小文字のディレクトリ」は変更できるのでしょうか?

変更できるでしょ?
やっといてね!
というご要望を、最近ちらほら頂いたので、ざっくりまとめてみました。

仕様

  • 変更できるかできないのか? にパッと答えられるようにするもの
  • 詳しい変更方法は別の記事か、Google先生におまかせします
  • 調査方法は主にLaravel5.5/5.6のソースコードをチェック
  • ざっくりしていますので、ヌケモレ間違いがあるかもしれません。気づかれましたら、ご指摘いただけるとありがたいです。

参考
ディレクトリ構造(Laravelドキュメント)
Laravelのディレクトリ構造について学ぶ

まとめ

DIR 難度 概要 詳細
/ 変更不可
app Applicationを派生 path()をオーバーライド
composer.jsonでAppの参照先を変更
 Providers ネームスペース PHPのネームスペースをディレクトリに合わせればOK
config/app.phpのクラス指定もそれに合わせる
 Http ネームスペース PHPのネームスペースをディレクトリに合わせればOK
config/app.phpのクラス指定もそれに合わせる
bootstrap Applicationを派生 bootstrapPath()をオーバーライド
bootstrap/index.phpを修正
config Applicationを派生 configPath()をオーバーライド
database bootstrap/app.php Application::useDatabasePath()
public Applicationを派生 publicPath()をオーバーライドするか
path.pulbicを置き換える
 storage シンボリックリンク storage/app/publicへのシンボリックリンク
php artisan storage:link
resources 変更困難 webpack,Vue などでハードコーディングされている。
Applicationを派生 resourcePath()をオーバーライド
Mail, Pagination などで使用
 assets 変更困難 webpack,Vue などでハードコーディングされている。
 lang Applicationを派生 langPath()をオーバーライドするか path.langを置き換える
 views config config/views.php を変更
routes RouteServiceProvider
storage bootstrap/app.php Application::useStoragePath()
 app/public config config/filesystems.php を変更
 framework 変更不可 ハードコーディングがちらほら
  cache config /cache.php を変更
  sessions config /session.php を変更
  testing 変更不可 Storage.php でハードコーディングされている。
  views config /views.php を変更
 logs LogHandlerを置き換え
tests composer.json
vendor 変更不可 PackageManifestなどでハードコーディング
.env bootstrap/app.php Application::useEnvironmentPath()

✕ 変更不可・困難

Laravelのソースコードの中でハードコーディングされていたり、影響範囲が大きく、実質的に変更できないディレクトリ。

/
vendor

「Laravelのルートディレクトリは、vendorが設置してあるディレクトリのことである」と思っていても間違いなさそうなくらい、動かさないほうが良いディレクトリ。
vendor ディレクトリは composer.json を修正すれば変更できるのですが、この vendor という名前が PackageManifestなどでハードコーディングされていて、むやみに変更したら100%動作する保証がありません。

参考
composer.jsonのvendorディレクトを変更するには(英語)
vendorを変更したら"php artisan optimize"でエラーが発生(英語)

resources

Application に resourcePath() というメソッドがあって変更できそうに見えますが、フロントエンド用の webpack,Vue などでハードコーディングされていたり、 resourcePath() も Mail, Pagination などの主力部隊が使っているので、事実上変更不可と思っていたほうが良さそうです。

resources/assets

その配下の assets も、webpack,Vue などでハードコーディングされていていて、事実上変更不可。フロント用の素材はここに置くと決めてかかりましょう。

storage/framework
storage/framework/testing

storageは変更できなくはないけど、その配下の framework と framework/testing が、Storage.php などでハードコーディングされていて変更が困難。

△ いばらの道

できなくはないが、標準的でない、上級テクニックを要する。

あなたは、なぜ、それでも前に進もうとするのか……。

app

この app の配下はネームスペースになっていて自由極まりないのですが、そのapp自体はどうなのか? 一見、composer.json の修正だけで行けそうな気がしますが、実際にはこの app ディレクトリは Application::path() の中でハードコーディングされていて、このpath()メソッドはいろんなところから呼ばれてます

この振る舞いを変更するには、Application::path() のオーバーライドが必須です。

他にも index.php から参照されていたり、ハードコーディングされていたり、単純な移動は困難です。それだったら、標準のappは触らずに置いといて、app_crawlers といった別ディレクトリを作って、composer.json で別のネームスペースを割り当てて好き勝手するほうが良いかと思います。

composer.json
    ...
    "autoload": {
        "classmap": [
            "database/seeds",
            "database/factories"
        ],
        "psr-4": {
            "App\\": "app/",
            "Crawlers\\": "app_crawlers/"  別ディレクトリを追加
        },
        ...

bootstrap

Application::bootstrapPath() のオーバーライドが必須です。public/index.php の修正も必要。複数のアプリケーションやカーネルを使い分ける、なんてことをする場合でも、bootstrapは触らず、bootstrap/app2.php と複数の起動スクリプトを作ったりしたほうが良さそうです。

storage/logs

要件としてはよくありがちなのに、意外と困難で、LogHandlerごと置き換える必要があります(LogServiceProviderにハードコーディングされています)。

storageディレクトリは比較的簡単に移動できるのでstorageごと動かすか、単にコードベースのディレクトリが使えないなら標準エラーログを使うか、ハンドラを置き換えるならデータベースを使うなど根本から変えたほうが良いかと思います。

config/logging.php
'channels' => [
    'single' => [
        'driver' => 'errorlog',
        // ...
    ],

参考
Laravel5.6でログをデータベースに記録する

〇 なんとかなる

標準的ではないが、変更の手間や影響範囲が少ないところ。とはいえ、ほんとうにするんですか?

config

Applicationクラスを派生して、configPath()をオーバーライド。希望のディレクトリを返すようにしておきます。

resources/lang
public

Applicationクラスを派生して、それぞれ、langPath()と、publicPath()をオーバーライドするのが王道かと思いますが、それがめんどくさければ、AppServiceProviderで、サービスコンテナの 'path.lang'、'path.pulbic' を置き換えても動きます。ただし、これは、たまたまフレームワークでlangPathもpublicPathも、使っていないから。今後のバージョンアップで使うようになるかもしれません。

public を変更した場合は、 public/index.phpやDocument_rootを変更することも忘れずに。

参考
Publicのディレクトリを移動する(ララジャパン)

.env
database
storage

それぞれ、Applicationクラスに、useEnvironmentPath()、useDatabasePath()、useStoragePath()というメソッドが用意されていて「どうぞ変更してください」という声が聞こえてきます。

ただ、注意したいのが、まずこれを使用するタイミング。

Applicationインスタンスが初期化された後、次にカーネルが初期化される中で、ServiceProvidersの初期化のに使用されているので、AppServiceProviderでは遅いです。 bootstrap/app.php で $app を受け取った直後に行ってください(この bootstrap/app.php を出た直後でも大丈夫です)。

bootstrap/app.php
/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
*/
$app = new Illuminate\Foundation\Application(
    realpath(__DIR__.'/../')
);

// ここで実行
$app->useStoragePath(__DIR__.'/../parent_temp/');

もう1つ注意は、.env の値が使えないこと。env()ヘルパー関数が使用不可。なので環境に依存するとしても、.envじゃない別の手段を考える必要があります(OSレベルでセットしておくとか、AWSやHerokuの管理画面で入れておくとか……。って、もう.env要らないですね)。

参考
Laravel5でstorageのパスを変更する

◎ フリーダム

開発者が自由に変更することを前提に作られているところ。変更は簡単だし影響は少ない。

app/Providers
app/Http

app 以下のディレクトリはネームスペース管理なので自由に変更可能です。サービスプロバイダなどはデフォルトでいくつかファイルが入っていますが、そのファイル内のnamespaceと、参照元のクラス名を変更すれば問題ありません。

routes
app\Http\Controllers

どちらも、RouteServiceProvider で設定されています。$namespaceというプロパティは他からも参照されているようなので、撤去してしまうと影響が出るかもしれません。

app/Providers/RouteServiceProvider.php
    protected $namespace = 'App\Http\Controllers';
    protected function mapWebRoutes()
    {
        Route::middleware('web')
            ->namespace($this->namespace)
            ->group(base_path('routes/web.php'));
    }

public/storage

標準では、storage/app/public へのシンボリックリンク。
php artisan storage:link で設定されます。なので、手動でリンクを貼ればOK。

resources/views
storage/framework/views

VIEWの元テンプレートと、PHP化されたキャッシュ置き場ですね。
どちらも、config/views.php を変更します。
ただ、ディレクトリを作ってはくれないので、あらかじめ作っておく必要があります。
もともとそうなっていますが、.envに書いてenv()で拾ってくるようにすると良い感じです。

storage/app/public
storage/framework/cache
storage/framework/sessions

それぞれ、configの、filesystems.php、cache.php、session.phpに書いてあるので変更すればOK。

tests

ネームスペースで参照可能なように composer.json に記述されています。あとは、phpunit.xmlを変更すればOK。

感想

できるかできないか、だけであって、やるかやらないか、ではありません!
よほどの事情がない限り、無理な変更はせずにフレームワークに合わせたほうが良いと思います。合わせてください。よろしくおねがいします。

kd9951
インフラからデザインまで。ワンストップでWEBアプリケーション開発しているエンジニア。メインはPHP/Laravelでの業務系システム開発。WordpressやAugnlarあたりも守備範囲。自称「穴埋め係」でGoogleやQiitaに無かった記事を書くことが多いので、誰得なマニアックな記事が多いです(*´ω`*)    園芸が好きで「多肉植物図鑑PUKUBOOK」を制作し編集長をしています。
https://pukubook.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away