実際に運用しているサービスのLaravelのファイル構成を共有してみる。

Laravelを始めるにあたって、どんなファイル構成が正しいのかわからない
実際私たちも全然わからなかったので、今の運用形式を共有してみる。

だれかの助けになったり、指摘をいただけたらとても嬉しいと思います:sushi:

階層毎に h タグの階層をつけてます


# app
アプリケーションファイル、基本的なアプリケーションコードはここに入れている
ほかにはKernel.phpという、最初に実行されうファイルがおいてある。

## console
コンソールから利用するアプリケーションコードはここに入れている

### Command
コンソールから利用するコマンドを入れている
日別実行、バッチファイルなどが入っている

うちのチームではECSのタスクのスケジューリングから
dockerコンテナ内でcronを設定するようにして、これらのファイルを実行している。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69647/751af65a-7e36-743e-a24b-64132c99665b.png)

## Exceptions
例外処理を入れるためのフォルダだと思われる。
しかし使っていない。
例外のハンドリングができていないのでいずれやりたい。

## Helpers
グローバルなメソッドを定義している
どこでも `関数名()` でその処理を呼び出せるので便利だが、グローバル変数環境がすごく汚染される
極力使わないようにしている

```php
if (! function_exists('hoge')) {
  /**
    * hogeする
    *
    * @param Eroquent\Collection Hoge
    * @param Integer 取得したい hoge_id
    * @return String 内容
  */
  function hoge($hoge, $piyo_id) {
    return $hoge->hogeSections()->where('piyo_id', $piyo_id)->first();
  }
}
```

## Http
ControllerやMiddlewware、Requests、ViewComposersが入っている。

### Controller
いろんなControllerが入ってる

管理画面は /admin 以下にControllerをまとめている
そのほかにも /markdown や /auth などがある。

自由に使い分けて良いと思う。

## Middleware
Controllerの前に実行するミドルウェアをたくさん入れているフォルダ

EncryptCookiesでCookieの暗号化
Authenticate、認証ミドルウェア
CheckForMaintenanceModeといったメンテナンス用ページ作成するときに使う
TrimStrings、getパラメータから特定のkeyを削除してくれる（password）など


そのほかに、サイト計測の値を操作したり、CSRFトークンチェックなどを実装して入れている



## Requests
postされた値のバリデーションルールを定義しているファイルが配置されている


## ViewComposers
viewで利用する共有処理をまとめておける。
グローバルなメソッドは定義せず、極力ここにまとめておきたい。

## Jobs
非同期処理を行うことを前提としたコードを入れておく。
railsでいう sidekiq 的なものが内装されている。

## Logging
ログフォーマットを独自のものに書き換えたりするときの処理を入れておく。
例えばjson形式で吐き出して、ログをS3に保存して、CloudWatchに送り、Athenaとかで解析するなどの使い道がある。


## Mail
メールを送信するときの処理を書いておく

私たちはメール内容をDBに文字列で保存（ビジネスチームが編集するため）
送信処理はこのディレクトリのファイルに記述
送信先や送信タイミングは各Controllerに任せている。

## Models
> Laravelを学習し始めるとき、多くの開発者はmodelsディレクトリが存在しないことに戸惑います。しかし、意図的にこのディレクトリを用意していません。多くの別々の人達にとって、その意味合いは様々なため、"models"という言葉の定義は曖昧であることに私達は気づきました。

https://readouble.com/laravel/5.5/ja/structure.html


Laravel公式でも議題にしているが、どこに配置するのが良いのか議論した結果、私たちは`app`配下に置いている
Rails を使ったサービスが多いので、 Rails と同じ配置ならわかりやすいだろうという判断だ。

私たちはRailsに慣れ親しんでいるので私たちの定義ではここに配置するのが良いだろうという判断なので、正解はないような気がしている。

Controllerと階層を合わせて`http`以下に入れるというのもありだが。
Modelはデータを管理する場所であって、あまり`http`とは関係ないなと思い外に出している。


## Providers

正直全然使ったことないので、Laravel公式の文章を持ってくる
https://readouble.com/laravel/5.3/ja/providers.html

> Laravelアプリケーション全体の起動処理における、初めの心臓部です。皆さんのアプリケーションと同じく、Laravelのコアサービス全部もサービスプロバイダを利用し、初期起動処理を行っています

色々なプロバイダがデフォルトで配置されているが

私たちのアプリケーションでは、`routes`ファイルたちの読み込み順を`RouteServiceProvider`で変更している
通常のroutesファイルの処理を行う前に、redirect処理をしたかったからだ。

`redirect.php`というファイルを `routes`ディレクトリ以下に新規追加し、そちらを優先的に処理するよう記述している。

また、先ほどの`viewComposer`で作成したファイルをどのviewファイルで利用できるようにするかを定義し、読み込んでいる`ComposerServiceProvider`というファイルもある。


## Services
システム全体で利用する、他システムとの連携部の共通処理をまとめている。

私たちのアプリケーションではAWSへの画像アップロード処理、CSV作成処理、マークダウンをHTMLに変換するときの処理などを共通にしている。



詳しくはこの記事を読むとわかりやすい、おすすめ。
https://qiita.com/nunulk/items/6b7a7bbda17192f6b2f5


# Bootstrap
あのデザインフレームワーク！と思う人も多いと思いますが違います。
アプリケーションを実行するときに最初に読み込まれるファイルです。

この子たちを呼び出したりしております。

* httpのkernel
* consoleのkernel
* exceptionsのkernel

この記事がわかりやすいのでおすすめ。

Laravelのリクエスト開始からコントローラにたどり着くまで
https://qiita.com/takyam/items/c2d397dd486c047dcbb1#step-3-bootstrap

# Config
基本的にLaravelに初めから入っている、認証機能、メール機能、非同期処理機能などの設定はここで設定が可能です。

便利ですね。

# database
DB周りのファイルが入っている

## factories
テストコードを実行するときに必要なサンプルデータを作る処理を入れておく


## migrations
DB構造の変更を履歴を残して管理してくれているおなじみのディレクトリ。
DB変更のたびにファイルが増える。

## seeds
アプリケーションを実行する上で必要となるマスターデータを入れるための処理を記述するファイルを配置する。
全部を記述する必要はないと考え

都道府県データ
性別データ

このようなマスターデータのみseedsでgit管理している。

# public
静的なファイルを配置したいときに利用する
faviconを配置したり、robots.txtなどを配置している。

また、Laravelのアプリケーション動作時はこのディレクトリにコンパイルされたファイルたちが配置される。

## CSS、JS
SCSSのコンパイル結果がここに保存されていく。
基本的には`gitignore`するべき。

## fonts
こちらも同じくコンパイルされたものが入る
管理画面で`font-awesome`を利用しているのでそれはここに入っている。


## images
基本的な画像はここに配置している。
フォルダ構成は極力viewファイルと合わせている


# resorces
コンパイル前のjs、scss、viewファイルなどフロント周りのファイルが入っている

## js
私たちのチームでは生jsを利用。
アプリケーションの形式上、jsを使う部分がほぼないため、フレームワークは導入せず。

フォルダとファイルの規則はシンプルで、viewファイルの構成に合わせることにしている。

生のjsで書いている、無論 jquery も使っていない。
必要十分で非常にやりやすい、チャンスがあればフレームワーク良い感じにしたい。

## lang
多言語対応用のファイル、入社直後の中国人エンジニアが英語を日本語に翻訳してくれた。
それ以降特に問題なく使えている、すごい、ありがとう。

### 下層ディレクトリ
* en
* ja

```php5:バリデーション周りの和訳設定
    'accepted' => ':attributeを承認してください。',
    'active_url' => ':attributeが有効なURLではありません。',
    'after' => ':attributeには、:dateより後の日付を指定してください。',
    'after_or_equal' => ':attributeには、:date以前の日付を指定してください。',
    'alpha' => ':attributeはアルファベットのみがご利用できます。',
```

## sass
cssはsass形式で書いている。
ディレクトリ構成はviewファイルと1：1対応するようにしている。

それ以外のファイルとしてはこれらを用意している

* layouts
* mixins
* module
* elements
* variables


## views
viewファイルです、デフォルトのこの配置のまま利用しています。

admin
front
lp

このようなディレクティブだけ切っております。


# routes
ルーティング系ファイルですね

* admin.php
* web.php
* redirect.php

おもに、この３つを使ってます。
adminとredirectは独自のファイルですね。

リダイレクトはもちろんngixでやったほうが早いのですが、メンテナンスコストなどを鑑みてこうしております。

# storage
今日までこのファイルを認識しておりませんでした。

私たちは独自でS3との連携を行う処理を、Serviceディレクトリ以下に作りましたがこちらに作るのが本来正しいのかもしれません。

https://readouble.com/laravel/5.5/ja/filesystem.html
> LaravelはFrank de Jongeさんが作成したありがたいほど素晴らしい、抽象ファイルシステムであるFlysystem PHPパッケージを提供しています
> LaravelとFlysystemの統合によりローカルのファイルシステム、Amazon S3、Rackspaceクラウドストレージを操作できる、シンプルなドライバが提供できました。更に素晴らしいことにそれぞれのシステムに対し同じAPIを使用しているため、ストレージをとても簡単に変更できるのです。


# tests
テストコードを配置してます。
FeatureテストとUnitテストの2種類ですね。

Featureテストではリクエストテストを最低限カバーし、Unitテストで重要な部分のみテストを書いております。
カバー率を上げていきたいところです。