なにがしたい?
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 で別のネームスペースを割り当てて好き勝手するほうが良いかと思います。
...
"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ごと動かすか、単にコードベースのディレクトリが使えないなら標準エラーログを使うか、ハンドラを置き換えるならデータベースを使うなど根本から変えたほうが良いかと思います。
'channels' => [
'single' => [
'driver' => 'errorlog',
// ...
],
〇 なんとかなる
標準的ではないが、変更の手間や影響範囲が少ないところ。とはいえ、ほんとうにするんですか?
config
Applicationクラスを派生して、configPath()をオーバーライド。希望のディレクトリを返すようにしておきます。
resources/lang
public
Applicationクラスを派生して、それぞれ、langPath()と、publicPath()をオーバーライドするのが王道かと思いますが、それがめんどくさければ、AppServiceProviderで、サービスコンテナの 'path.lang'、'path.pulbic' を置き換えても動きます。ただし、これは、たまたまフレームワークでlangPathもpublicPathも、使っていないから。今後のバージョンアップで使うようになるかもしれません。
public を変更した場合は、 public/index.phpやDocument_rootを変更することも忘れずに。
.env
database
storage
それぞれ、Applicationクラスに、useEnvironmentPath()、useDatabasePath()、useStoragePath()というメソッドが用意されていて「どうぞ変更してください」という声が聞こえてきます。
ただ、注意したいのが、まずこれを使用するタイミング。
Applicationインスタンスが初期化された後、次にカーネルが初期化される中で、ServiceProvidersの初期化の前に使用されているので、AppServiceProviderでは遅いです。 bootstrap/app.php で $app を受け取った直後に行ってください(この 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要らないですね)。
◎ フリーダム
開発者が自由に変更することを前提に作られているところ。変更は簡単だし影響は少ない。
app/Providers
app/Http
app 以下のディレクトリはネームスペース管理なので自由に変更可能です。サービスプロバイダなどはデフォルトでいくつかファイルが入っていますが、そのファイル内のnamespaceと、参照元のクラス名を変更すれば問題ありません。
routes
app\Http\Controllers
どちらも、RouteServiceProvider で設定されています。$namespaceというプロパティは他からも参照されているようなので、撤去してしまうと影響が出るかもしれません。
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。
感想
できるかできないか、だけであって、やるかやらないか、ではありません!
よほどの事情がない限り、無理な変更はせずにフレームワークに合わせたほうが良いと思います。合わせてください。よろしくおねがいします。