Edited at

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


なにがしたい?

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。


感想

できるかできないか、だけであって、やるかやらないか、ではありません!

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