Laravelでプロジェクトを作成したらまずやることメモ

どんなプロジェクトでもLaravel使う場合はこんな感じにしてるってのが見えてきたのでまとめてみた。

| Laravel | URL     |
| :-----: | :-----: |
| 5.1 LTS | https://github.com/ponko2/laravel-starter-kit/tree/5.1 |
| 5.2 | https://github.com/ponko2/laravel-starter-kit/tree/master |

# Node.jsのインストール

[Laravel Elixir](http://laravel.com/docs/5.1/elixir)や[ESLint](http://eslint.org/)を実行するためには[Node.js](https://nodejs.org/)が必要なので、インストールしておく。

# Gitの設定を調整

キャッシュや[Laravel Elixir](http://laravel.com/docs/5.1/elixir)が生成するファイルの設定

```text:.gitignore
### Composer ###
composer.phar
/vendor

### PHP Coding Standards Fixer ###
.php_cs.cache

### Node ###
/node_modules

## Laravel ##
.env

## Laravel Homestead ##
/.vagrant
Homestead.yaml
Homestead.json
```

```text:public/build/.gitignore
*
!.gitignore
```

```text:public/css/.gitignore
*
!.gitignore
```

```text:public/js/.gitignore
*
!.gitignore
```

```text:public/vendor/.gitignore
*
!.gitignore
```

```text:.gitattributes
* text=auto
*.min.js binary
*.min.css binary
*.css linguist-vendored
*.scss linguist-vendored
/public/js/**/* binary
/public/css/**/* binary
/public/build/**/* binary
/public/vendor/**/* binary
```

# Coding Style関連の設定

## [EditorConfig](http://editorconfig.org/)

インデントや文字コードをそろえたいので、[EditorConfig](http://editorconfig.org/)を使用する。

### エディタ
[Atom Editor](https://atom.io/)を使う場合は、下記のコマンドで[EditorConfig](https://atom.io/packages/editorconfig)パッケージを導入しておく。

```console
$ apm install editorconfig
```

### 設定

プロジェクトルートに下記のファイルを設置する。

```text:.editorconfig
# editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.php]
indent_size = 4

[composer.json]
indent_size = 4

[*.md]
trim_trailing_whitespace = false
```

## [PHP Coding Standards Fixer](http://cs.sensiolabs.org/)
PHPのコーディングスタイルをそろえたいので[PHP Coding Standards Fixer](http://cs.sensiolabs.org/)を使用する。

### インストール

```console
$ composer require --dev friendsofphp/php-cs-fixer
```

### 設定

プロジェクトルートに下記のファイルを設置する。

```php:.php_cs
<?php

$finder = Symfony\CS\Finder\DefaultFinder::create()
    ->exclude('bootstrap/cache')
    ->exclude('resources/assets')
    ->exclude('resources/views')
    ->exclude('storage')
    ->exclude('node_modules')
    ->in(__DIR__);

$fixers = [
  '-psr0',
  '-phpdoc_no_empty_return',
  '-phpdoc_no_package',
  '-phpdoc_params',
  '-phpdoc_short_description',
  '-unalign_double_arrow',
  '-unalign_equals',
  'ereg_to_preg',
  'ordered_use',
  'php_unit_construct',
  'php_unit_strict',
  'phpdoc_order',
  'short_array_syntax',
  'strict',
  'strict_param',
];

return Symfony\CS\Config\Config::create()
    ->fixers($fixers)
    ->finder($finder)
    ->setUsingCache(true);
```

### 使い方

プロジェクトルートで下記のコマンドを実行するとPHPコードをコーディング規約に沿うよう修正してくれる。

```console
$ vendor/bin/php-cs-fixer fix -v
```

## [PHP_CodeSniffer](https://pear.php.net/manual/ja/package.php.php-codesniffer.php)
PHPのコーディングスタイルをそろえたいので[PHP_CodeSniffer](https://pear.php.net/manual/ja/package.php.php-codesniffer.php)も使用する。

### インストール

```console
$ composer require --dev squizlabs/php_codesniffer
```

### エディタ
[Atom Editor](https://atom.io/)を使う場合は、下記のコマンドで[linter-phpcs](https://atom.io/packages/linter-phpcs)パッケージを導入しておくと、リアルタイム構文チェックができて便利。

```console
$ apm install linter-phpcs
```

このパッケージを使うためにはパッケージの設定にて`phpcs`のPATHを指定しておく必要があるため、下記のコマンドで`$HOME/.composer/vendor/bin`（Windowsの場合は`%APPDATA%\Composer\vendor\bin`？）にインストールしておくと良い。

```console
$ composer global require squizlabs/php_codesniffer
```

### 設定

プロジェクトルートに下記のファイルを設置する。

* 基本のルールは`PSR-2`
* [PHP_CodeSniffer](https://pear.php.net/manual/ja/package.php.php-codesniffer.php)で行の文字数をチェックすると、コメントに日本語を使っていた時などに正しくチェックできないため除外。
* `PSR1.Classes.ClassDeclaration`はマイグレーションやテスト等の`namespace`指定をしていないところで引っかかるため除外。

```xml:phpcs.xml
<?xml version="1.0"?>
<ruleset name="Custom Standard">
  <rule ref="PSR2">
    <exclude name="Generic.Files.LineLength"/>
    <exclude name="PSR1.Classes.ClassDeclaration"/>
  </rule>

  <exclude-pattern>*.blade.php</exclude-pattern>
  <exclude-pattern>*.twig.php</exclude-pattern>
  <exclude-pattern>bootstrap/</exclude-pattern>
  <exclude-pattern>node_modules/</exclude-pattern>
  <exclude-pattern>public/build/</exclude-pattern>
  <exclude-pattern>public/css/</exclude-pattern>
  <exclude-pattern>public/js/</exclude-pattern>
  <exclude-pattern>public/vendor/</exclude-pattern>
  <exclude-pattern>resources/assets/</exclude-pattern>
  <exclude-pattern>resources/views/</exclude-pattern>
  <exclude-pattern>storage/</exclude-pattern>
  <exclude-pattern>vendor/</exclude-pattern>
</ruleset>
```

### 使い方

プロジェクトルートで下記のコマンドを実行するとPHPコードがコーディング規約に沿っているかを確認できる。

```console
$ vendor/bin/phpcs --standard=phpcs.xml --extensions=php .
```

## [PHP Mess Detector](http://phpmd.org/)
PHPのコードに潜在的なバグになりそうな箇所や実装上の問題がないかチェックするため[PHP Mess Detector](http://phpmd.org/)を使用する。

### インストール

```console
$ composer require --dev phpmd/phpmd:"@stable"
```

### エディタ
[Atom Editor](https://atom.io/)を使う場合は、下記のコマンドで[linter-phpmd](https://atom.io/packages/linter-phpmd)パッケージを導入しておくと、リアルタイムチェックができて便利。

```console
$ apm install linter-phpmd
```

パッケージの設定画面で`Automatically use ruleset.xml`にチェックを入れていない場合、下記の`ruleset.xml`が読み込まれないので注意。

このパッケージを使うためにはパッケージの設定にて`phpmd`のPATHを指定しておく必要があるため、下記のコマンドで`$HOME/.composer/vendor/bin`（Windowsの場合は`%APPDATA%\Composer\vendor\bin`？）にインストールしておくと良い。

```console
$ composer global require phpmd/phpmd:"@stable"
```

### 設定

プロジェクトルートに下記のファイルを設置する。

* [Clean Code Rules](http://phpmd.org/rules/cleancode.html)を有効化しておくと、[Laravel](http://laravel.com/)のコードを書く時に不便なので除外する。
* [Naming Rules](http://phpmd.org/rules/naming.html)の[ShortVariable](http://phpmd.org/rules/naming.html#shortvariable)はデフォルト設定の3文字だと`php artisan make:controller`をした時のコード等に2文字の変数があり引っかかるので、2文字に変更。

```xml:ruleset.xml
<?xml version="1.0"?>
<ruleset
  name="Custom PHPMD rule set"
  xmlns="http://pmd.sf.net/ruleset/1.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
  xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"
>
  <rule ref="rulesets/codesize.xml" />
  <rule ref="rulesets/controversial.xml" />
  <rule ref="rulesets/design.xml" />
  <rule ref="rulesets/naming.xml">
    <exclude name="ShortVariable" />
    <exclude name="ShortMethodName" />
  </rule>
  <rule ref="rulesets/naming.xml/ShortVariable">
    <priority>1</priority>
    <properties>
      <property name="minimum" value="2" />
    </properties>
  </rule>
  <rule ref="rulesets/naming.xml/ShortMethodName">
    <priority>1</priority>
    <properties>
      <property name="minimum" value="2" />
    </properties>
  </rule>
  <rule ref="rulesets/unusedcode.xml" />
</ruleset>
```

### 使い方

プロジェクトルートで下記のコマンドを実行するとPHPコードに潜在的なバグになりそうな箇所や実装上の問題がないかを確認できる。

```console
$ vendor/bin/phpmd . text ruleset.xml --suffixes php --exclude node_modules,resources,storage,vendor
```

## [ESLint](http://eslint.org/)

JavaScriptのコーディングスタイルをそろえたいので[ESLint](http://eslint.org/)を使用する。

### インストール

```console
$ npm install --save-dev eslint
$ npm install --save-dev eslint-plugin-html
$ npm install --save-dev eslint-config-ponko2
```

設定ファイルを毎回コピーするのが面倒なので、[ESLint Shareable Configs](http://eslint.org/docs/developer-guide/shareable-configs)で作成した設定を読み込んで使う。

### エディタ
[Atom Editor](https://atom.io/)を使う場合は、下記のコマンドで[linter-eslint](https://atom.io/packages/linter-eslint)パッケージを導入しておくと、リアルタイム構文チェックができて便利。

```console
$ apm install linter-eslint
```

### 設定

プロジェクトルートに下記のファイルを設置する。

```json:.eslintrc.json
{
  "plugins": [
    "html"
  ],
  "extends": "ponko2"
}
```

```text:.eslintignore
*.min.js
public/js/
public/build/
public/vendor/
```

### 使い方

プロジェクトルートで下記のコマンドを実行するとJavaScriptコードがコーディング規約に沿っているかを確認できる。

```console
$ eslint resources/assets/js/**
```

## [CSScomb](http://csscomb.com/)

Scssのコーディングスタイルをそろえたいので[CSScomb](http://csscomb.com/)を使用する。

### インストール

```console
$ npm install --save-dev csscomb
```

### 設定

プロジェクトルートに下記のファイルを設置する。

```json:.csscomb.json
{
  "exclude": [
    ".git/**",
    "node_modules/**",
    "resources/assets/sass/bootstrap/_variables.scss"
  ],
  "always-semicolon": true,
  "block-indent": "  ",
  "color-case": "lower",
  "color-shorthand": true,
  "element-case": "lower",
  "eof-newline": true,
  "leading-zero": false,
  "quotes": "double",
  "remove-empty-rulesets": true,
  "space-after-colon": " ",
  "space-after-combinator": " ",
  "space-after-opening-brace": "\n",
  "space-after-selector-delimiter": "\n",
  "space-before-closing-brace": "\n",
  "space-before-colon": "",
  "space-before-combinator": " ",
  "space-before-opening-brace": " ",
  "space-before-selector-delimiter": "",
  "space-between-declarations": "\n",
  "strip-spaces": true,
  "tab-size": true,
  "unitless-zero": true,
  "vendor-prefix-align": false
}
```

### 使い方

プロジェクトルートで下記のコマンドを実行するとSCSSコードをコーディング規約に沿ったものに修正できる。

```console
$ csscomb resources/assets/sass
```

## [stylelint](http://stylelint.io/)

[CSScomb](http://csscomb.com/)ではそろえられない細かいコーディングスタイルは[stylelint](http://stylelint.io/)を使用してチェックする。

### インストール

```console
$ npm install --save-dev stylelint
$ npm install --save-dev stylelint-config-ponko2
```

設定ファイルを毎回コピーするのが面倒なので、[stylelint shareable config](http://stylelint.io/?/docs/user-guide/configuration.md)で作成した設定を読み込んで使う。

### エディタ
[Atom Editor](https://atom.io/)を使う場合は、下記のコマンドで[linter-stylelint](https://github.com/AtomLinter/linter-stylelint)パッケージを導入しておくと、リアルタイム構文チェックができて便利。

```console
$ apm install linter-stylelint
```

### 設定

プロジェクトルートに下記のファイルを設置する。

```json:.stylelintrc.json
{
  "extends": "stylelint-config-ponko2"
}
```

### 使い方

プロジェクトルートで下記のコマンドを実行するとSCSSコードがコーディング規約に沿っているかを確認できる。

```console
$ stylelint -s scss resources/assets/sass/**/*.scss
```

# [Laravel Homestead](http://laravel.com/docs/5.1/homestead)の設定

[Laravel Homestead](http://laravel.com/docs/5.1/homestead)を使って、ローカル開発環境を作成する。

## インストール

[Laravel Homestead](http://laravel.com/docs/5.1/homestead)を実行するためには[Virtual Box](https://www.virtualbox.org/)と[Vagrant](https://www.vagrantup.com/)が必要なのでインストールしておき、プロジェクトルートで下記のコマンドを実行する。

```console
$ vagrant box add laravel/homestead
$ composer require --dev laravel/homestead
$ php vendor/bin/homestead make
```

初期設定では [http://homestead.app/](http://homestead.app/) でローカル開発環境が立ち上がる。
変更が必要な場合は、プロジェクトルートに生成された`Homestead.yaml`を編集する。

### 設定
Vagrant v1.8 以上を使っている場合はLinked clone、VirtualBox v5.0以上を使っている場合は準仮想化の設定もしておくと良いかもしれない。

```diff
diff --git Vagrantfile Vagrantfile
index 812b2b2..b218a23 100644
--- Vagrantfile
+++ Vagrantfile
@@ -12,6 +12,11 @@ aliasesPath = 'aliases'
 require File.expand_path(confDir + '/scripts/homestead.rb')
 
 Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
+  config.vm.provider 'virtualbox' do |vb|
+    vb.linked_clone = true
+    vb.customize ['modifyvm', :id, '--paravirtprovider', 'kvm']
+  end
+
   if File.exist? aliasesPath
     config.vm.provision 'file', source: aliasesPath, destination: '~/.bash_aliases'
   end
```

## 使い方

### ローカル開発環境の起動

```console
$ vagrant up
```

### ローカル開発環境の終了

```console
$ vagrant halt
```

# [Laravel Elixir](http://laravel.com/docs/5.1/elixir)の設定

## 設定内容

* ライブラリ追加
 * [jQuery](https://jquery.com/)
 * [Font Awesome](https://fortawesome.github.io/Font-Awesome/)
* CSSプリプロセッサ
 * [Sass](http://sass-lang.com/)
* ES6からES5への変換
 * [Browserify](http://browserify.org/)
* キャッシュ対策
 * [Versioning / Cache Busting](http://laravel.com/docs/5.1/elixir#versioning-and-cache-busting)
* Linter
 * [PHP_CodeSniffer](https://pear.php.net/manual/ja/package.php.php-codesniffer.php)
 * [ESLint](http://eslint.org/)
 * [stylelint](http://stylelint.io/)
* ファイル変更時のブラウザリロード
 * [Browsersync](http://www.browsersync.io/)

## 設定

```json:package.json
{
  "devDependencies": {
    "babel-preset-es2015": "^6.16.0",
    "babel-preset-react": "^6.16.0",
    "babel-register": "^6.16.3",
    "bootstrap-sass": "^3.3.7",
    "csscomb": "^3.1.8",
    "eslint": "^3.8.1",
    "eslint-config-ponko2": "^7.0.0",
    "eslint-plugin-html": "^1.5.3",
    "font-awesome": "^4.6.3",
    "gulp": "^3.9.1",
    "jquery": "^1.12.4",
    "laravel-elixir": "^6.0.0-11",
    "laravel-elixir-browserify-official": "^0.1.3",
    "laravel-elixir-browsersync-official": "^1.0.0",
    "laravel-elixir-eslint": "^4.0.0-4",
    "laravel-elixir-licensify": "^1.0.0-2",
    "laravel-elixir-phpcs": "^1.0.0-4",
    "laravel-elixir-stylelint": "^5.0.0-5",
    "stylelint": "^7.5.0",
    "stylelint-config-ponko2": "^7.0.0"
  },
  "engines": {
    "node": ">=4",
    "npm": ">=3"
  },
  "private": true,
  "scripts": {
    "csscomb": "csscomb resources/assets/sass",
    "dev": "gulp watch",
    "eslint": "eslint resources/assets/js/**",
    "eslint-fix": "eslint --fix resources/assets/js/**",
    "php-cs-fixer": "vendor/bin/php-cs-fixer fix -v",
    "phpcs": "vendor/bin/phpcs --standard=phpcs.xml --extensions=php .",
    "phpmd": "vendor/bin/phpmd . text ruleset.xml --suffixes php --exclude node_modules,resources,storage,vendor",
    "prod": "gulp --production",
    "stylelint": "stylelint -s scss resources/assets/sass/**/*.scss"
  }
}
```

```javascript:gulpfile.babel.js
const elixir = require('laravel-elixir');
const config = elixir.config;

config.browserSync.proxy = 'homestead.app';

require('laravel-elixir-phpcs');
require('laravel-elixir-eslint');
require('laravel-elixir-stylelint');
require('laravel-elixir-licensify');

elixir((mix) => {
  mix.sass('app.scss')
    .browserify('main.js')
    .copy(
      'node_modules/bootstrap-sass/assets/fonts/bootstrap',
      'public/vendor/bootstrap/fonts'
    )
    .copy(
      'node_modules/font-awesome/fonts',
      'public/vendor/font-awesome/fonts'
    )
    .version([
      'js/main.js',
      'css/app.css'
    ])
    .phpcs(null, {
      bin: 'vendor/bin/phpcs',
      standard: 'phpcs.xml'
    })
    .eslint([
      `${config.get('assets.js.folder')}/**/*.js`,
      `!${config.get('public.js.outputFolder')}/main.js`,
    ])
    .stylelint([
      `${config.get('assets.css.sass.folder')}/**/*.scss`,
      `!${config.get('public.css.outputFolder')}/app.css`,
    ])
    .browserSync();
});
```

```json:.babelrc
{
  "presets": ["es2015"]
}
```

```scss:resources/assets/sass/app.scss
@charset "UTF-8";

// Bootstrap
@import "bootstrap/variables";
@import "node_modules/bootstrap-sass/assets/stylesheets/bootstrap";

// Font Awesome
@import "font-awesome/variables";
@import "node_modules/font-awesome/scss/font-awesome";
```

```scss:resources/assets/sass/bootstrap/_variables.scss
@charset "UTF-8";


//== Iconography
//
//##

//** Load fonts from this directory.
$icon-font-path: "/vendor/bootstrap/fonts/";
```

```scss:resources/assets/sass/font-awesome/_variables.scss
@charset "UTF-8";


//== Iconography
//
//##

//** Load fonts from this directory.
$fa-font-path: "/vendor/font-awesome/fonts";
```

```javascript:resources/assets/js/main.js
import $ from 'jquery';

window.jQuery = $;
window.$      = $;

require('bootstrap-sass');


/**
 * formのinputにてEnterを押した時の送信を無効化する
 * `allow-submit`がclass指定されたものについては無効化を行わない
 *
 * @returns {boolean} Enterが押された場合はfalse
 */
function disableFormSubmitOnEnter() {
  const KEY_CODE_ENTER = 13;

  $('input:not(.allow-submit)').on('keyup keypress', (event) => {
    const keyCode = event.keyCode || event.which;

    if (keyCode === KEY_CODE_ENTER) {
      event.preventDefault();
      return false;
    }

    return true;
  });
}

/**
 * 二重登録を防止
 *
 * @returns {void}
 */
function preventDuplicateFormSubmissions() {
  $('form :submit').click((event) => {
    const TIMEOUT = 10000;
    const target  = event.target;
    const $form   = $(target).closest('form');
    const $submit = $form.find(':submit');

    // clickしたsubmitの値をhiddenに保存
    const $hidden = $('<input/>', {
      type: 'hidden',
      name: target.name,
      value: target.value
    }).appendTo($form);

    event.preventDefault();
    event.stopPropagation();

    // 全てのsubmitを無効化
    $submit.prop('disabled', true);

    // 時間経過でsubmitの無効化を解除
    setTimeout(() => {
      $hidden.remove();
      $submit.prop('disabled', false);
    }, TIMEOUT);

    $form.submit();
  });
}


$(function () {
  disableFormSubmitOnEnter();
  preventDuplicateFormSubmissions();
}());
```

## インストール

```console
$ npm install --global gulp
$ npm install
```

## 使い方

プロジェクトルートで下記のコマンドを実行する。

```console
$ gulp watch
```

localの環境を [http://homestead.app/](http://homestead.app/) でないもので立ち上げている場合は、`BrowserSync`の設定にある`proxy`の部分を変更する。

# ファイル配置場所の調整

下記のコマンドを実行後、`User`クラスの`namespace`を修正する。

```console
$ mkdir app/Entities
$ mv app/User.php app/Entities/User.php
```

```diff
diff --git app/Entities/User.php app/Entities/User.php
index ef6fe91..164a092 100644
--- app/Entities/User.php
+++ app/Entities/User.php
@@ -1,6 +1,6 @@
 <?php
 
-namespace App;
+namespace App\Entities;
 
 use Illuminate\Foundation\Auth\User as Authenticatable;
 
diff --git app/Http/Controllers/Auth/AuthController.php app/Http/Controllers/Auth/AuthController.php
index d96635b..773d65c 100644
--- app/Http/Controllers/Auth/AuthController.php
+++ app/Http/Controllers/Auth/AuthController.php
@@ -2,7 +2,7 @@
 
 namespace App\Http\Controllers\Auth;
 
-use App\User;
+use App\Entities\User;
 use Validator;
 use App\Http\Controllers\Controller;
 use Illuminate\Foundation\Auth\ThrottlesLogins;
diff --git config/auth.php config/auth.php
index 3fa7f49..4bb1fe5 100644
--- config/auth.php
+++ config/auth.php
@@ -67,7 +67,7 @@ return [
     'providers' => [
         'users' => [
             'driver' => 'eloquent',
-            'model' => App\User::class,
+            'model' => App\Entities\User::class,
         ],
 
         // 'users' => [
diff --git config/services.php config/services.php
index 93eec86..9ebf2c6 100644
--- config/services.php
+++ config/services.php
@@ -30,7 +30,7 @@ return [
     ],
 
     'stripe' => [
-        'model'  => App\User::class,
+        'model'  => App\Entities\User::class,
         'key'    => env('STRIPE_KEY'),
         'secret' => env('STRIPE_SECRET'),
     ],
diff --git database/factories/ModelFactory.php database/factories/ModelFactory.php
index 0876c70..62c7397 100644
--- database/factories/ModelFactory.php
+++ database/factories/ModelFactory.php
@@ -11,7 +11,7 @@
 |
 */
 
-$factory->define(App\User::class, function (Faker\Generator $faker) {
+$factory->define(App\Entities\User::class, function (Faker\Generator $faker) {
     return [
         'name' => $faker->name,
         'email' => $faker->email,
```

# 日本語化

## 日本語の言語ファイルを追加

https://github.com/caouecs/Laravel-lang/tree/master/src/ja のファイルを `resources/lang` の下に追加する。

```console
$ tree resources/lang 
resources/lang
├── en
│   ├── auth.php
│   ├── pagination.php
│   ├── passwords.php
│   └── validation.php
└── ja
    ├── auth.php
    ├── pagination.php
    ├── passwords.php
    └── validation.php

2 directories, 8 files
```

## localeを変更

`locale`を`ja`に変更する。

```diff:config/app.php
diff --git config/app.php config/app.php
index 04ae95e..5f87b29 100644
--- config/app.php
+++ config/app.php
@@ -65,7 +65,7 @@ return [
     |
     */
 
-    'locale' => 'en',
+    'locale' => 'ja',
 
     /*
     |--------------------------------------------------------------------------
```

## timezoneを変更

`timezone`を`Asia/Tokyo`に変更する。

```diff:config/app.php
diff --git config/app.php config/app.php
index 5f87b29..3cd8aab 100644
--- config/app.php
+++ config/app.php
@@ -52,7 +52,7 @@ return [
     |
     */
 
-    'timezone' => 'UTC',
+    'timezone' => 'Asia/Tokyo',
 
     /*
     |--------------------------------------------------------------------------
```

# マスターレイアウトファイルを作成

ビューの共通部分を切り出して使い回しできるようにしておく。

```php:resources/views/layouts/master.blade.php
<!DOCTYPE html>
<html lang="{{ App::getLocale() }}">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>@yield('title') - App Name</title>
        @section('styles')
            <link rel="stylesheet" href="{{ elixir('css/app.css') }}">
        @show
        <!--[if lt IE 9]>
            <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
            <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
        <![endif]-->
    </head>
    <body class="@yield('body-class')">
        <div class="container">
            @yield('content')
        </div>
        @section('scripts')
            <script src="{{ elixir('js/main.js') }}"></script>
        @show
    </body>
</html>
```

こんな感じに使える。

```php
@extends('layouts.master')

@section('title', 'It Works!')

@section('content')
    <h1 class="page-header">It Works!</h1>
    <p>This is the default web page for this server.</p>
    <p>The web server software is running but no content has been added, yet.</p>
@endsection
```

# カスタムバリデータを登録

```php:app/Services/Validation/Validator.php
<?php

namespace App\Services\Validation;

class Validator extends \Illuminate\Validation\Validator
{
    /**
     * Validate that an attribute contains only alphabetic characters.
     *
     * @param  string  $attribute
     * @param  mixed   $value
     *
     * @return bool
     *
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    protected function validateAlpha($attribute, $value)
    {
        // オリジナルのバリデーションから多バイト文字を除外
        return is_string($value) && preg_match('/^[\pL\pM]+$/', $value);
    }

    /**
     * Validate that an attribute contains only alpha-numeric characters.
     *
     * @param  string  $attribute
     * @param  mixed   $value
     *
     * @return bool
     *
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    protected function validateAlphaNum($attribute, $value)
    {
        if (!is_string($value) && !is_numeric($value)) {
            return false;
        }

        // オリジナルのバリデーションから多バイト文字を除外
        return preg_match('/^[\pL\pM\pN]+$/', $value);
    }

    /**
     * Validate that an attribute contains only alpha-numeric characters, dashes, and underscores.
     *
     * @param  string  $attribute
     * @param  mixed   $value
     *
     * @return bool
     *
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    protected function validateAlphaDash($attribute, $value)
    {
        if (!is_string($value) && !is_numeric($value)) {
            return false;
        }

        // オリジナルのバリデーションから多バイト文字を除外
        return preg_match('/^[\pL\pM\pN_-]+$/', $value);
    }
}
```

```php:app/Services/Validation/ServiceProvider.php
<?php

namespace App\Services\Validation;

class ServiceProvider extends \Illuminate\Support\ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        $this->app->validator->resolver(function ($translator, $data, $rules, $messages, $customAttributes) {
            return new Validator($translator, $data, $rules, $messages, $customAttributes);
        });
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}
```

```diff:config/app.php
diff --git config/app.php config/app.php
index 3cd8aab..edcb366 100644
--- config/app.php
+++ config/app.php
@@ -155,6 +155,7 @@ return [
         App\Providers\AuthServiceProvider::class,
         App\Providers\EventServiceProvider::class,
         App\Providers\RouteServiceProvider::class,
+        App\Services\Validation\ServiceProvider::class,
 
     ],
```

# [Laravel Debugbar](https://github.com/barryvdh/laravel-debugbar)の設定

## インストール

```console
$ composer require --dev barryvdh/laravel-debugbar
```

## 設定
`APP_ENV`が`local`の時だけ`Debugbar`が表示されるように設定。

```diff:config/app.php
diff --git config/app.php config/app.php
index edcb366..c38f3d0 100644
--- config/app.php
+++ config/app.php
@@ -155,6 +155,7 @@ return [
         App\Providers\AuthServiceProvider::class,
         App\Providers\EventServiceProvider::class,
         App\Providers\RouteServiceProvider::class,
+        App\Providers\LocalServiceProvider::class,
         App\Services\Validation\ServiceProvider::class,
 
     ],
```

```php:app/Providers/LocalServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Foundation\AliasLoader;
use Illuminate\Support\ServiceProvider;

class LocalServiceProvider extends ServiceProvider
{
    /**
     * localでのみ設定したいサービスプロバイダー
     *
     * @var array
     */
    protected $providers = [
        \Barryvdh\Debugbar\ServiceProvider::class,
    ];

    /**
     * localでのみ設定したいクラスエイリアス
     *
     * @var array
     */
    protected $aliases = [
        'Debugbar' => \Barryvdh\Debugbar\Facade::class,
    ];

    /**
     * アプリケーションサービスの初期化処理
     *
     * @return void
     */
    public function boot()
    {
        //
    }

    /**
     * アプリケーションサービスの登録
     *
     * @return void
     */
    public function register()
    {
        if ($this->app->isLocal()) {
            $this->registerProviders();
            $this->registerAliases();
        }
    }

    /**
     * サービスプロバイダーの登録
     *
     * @return void
     */
    protected function registerProviders()
    {
        if (!empty($this->providers)) {
            foreach ($this->providers as $provider) {
                $this->app->register($provider);
            }
        }
    }

    /**
     * クラスエイリアスの登録
     *
     * @return void
     */
    protected function registerAliases()
    {
        if (!empty($this->aliases)) {
            $loader = AliasLoader::getInstance();

            foreach ($this->aliases as $alias => $facade) {
                $loader->alias($alias, $facade);
            }
        }
    }
}
```

```console
$ php artisan vendor:publish
```

# [Laravel Collective](http://laravelcollective.com/docs/5.2/html)の設定

## インストール

```console
$ composer require laravelcollective/html:'5.2.*'
```

## 設定

メソッドはやしたり動作を変えたい箇所があるため上書きしている。

```php:app/Services/Html/HtmlBuilder.php
<?php

namespace App\Services\Html;

class HtmlBuilder extends \Collective\Html\HtmlBuilder
{
    //
}
```

```php:app/Services/Html/FormBuilder.php
<?php

namespace App\Services\Html;

class FormBuilder extends \Collective\Html\FormBuilder
{
    /**
     * Get the action for a "route" option.
     *
     * @param  array|string $options
     *
     * @return string
     */
    protected function getRouteAction($options)
    {
        if (is_array($options)) {
            return call_user_func_array([$this->url, 'route'], $options);
        }

        return $this->url->route($options);
    }
}
```

```php:app/Services/Html/ServiceProvider.php
<?php

namespace App\Services\Html;

use Collective\Html\HtmlServiceProvider;

class ServiceProvider extends HtmlServiceProvider
{
    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->registerHtmlBuilder();
        $this->registerFormBuilder();

        $this->app->alias('html', HtmlBuilder::class);
        $this->app->alias('form', FormBuilder::class);
    }

    /**
     * Register the HTML builder instance.
     *
     * @return void
     */
    protected function registerHtmlBuilder()
    {
        $this->app->singleton('html', function ($app) {
            return new HtmlBuilder($app['url'], $app['view']);
        });
    }

    /**
     * Register the form builder instance.
     *
     * @return void
     */
    protected function registerFormBuilder()
    {
        $this->app->singleton('form', function ($app) {
            $form = new FormBuilder($app['html'], $app['url'], $app['view'], $app['session.store']->getToken());

            return $form->setSessionStore($app['session.store']);
        });
    }

    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return [
            'html',
            'form',
            HtmlBuilder::class,
            FormBuilder::class,
        ];
    }
}
```

```diff:config/app.php
diff --git c38f3d0..2774253 2774253
index c38f3d0..2774253 100644
--- config/app.php
+++ config/app.php
@@ -156,6 +156,7 @@ return [
         App\Providers\EventServiceProvider::class,
         App\Providers\RouteServiceProvider::class,
         App\Providers\LocalServiceProvider::class,
+        App\Services\Html\ServiceProvider::class,
         App\Services\Validation\ServiceProvider::class,
 
     ],
@@ -203,6 +204,8 @@ return [
         'URL'       => Illuminate\Support\Facades\URL::class,
         'Validator' => Illuminate\Support\Facades\Validator::class,
         'View'      => Illuminate\Support\Facades\View::class,
+        'Form'      => Collective\Html\FormFacade::class,
+        'Html'      => Collective\Html\HtmlFacade::class,
 
     ],
```

# [Laravel 5 Repositories](https://github.com/andersao/l5-repository)の設定

リポジトリパターンで書きたいので入れておく。使い方は[README.md](https://github.com/andersao/l5-repository/blob/master/README.md)を見る。

## インストール

```console
$ composer require prettus/l5-repository
$ composer require prettus/laravel-validation
$ composer require league/fractal
```

## 設定

```diff:config/app.php
diff --git 2774253..bd1429e bd1429e
index 2774253..bd1429e 100644
--- config/app.php
+++ config/app.php
@@ -154,11 +154,14 @@ return [
         App\Providers\AppServiceProvider::class,
         App\Providers\AuthServiceProvider::class,
         App\Providers\EventServiceProvider::class,
+        App\Providers\RepositoryServiceProvider::class,
         App\Providers\RouteServiceProvider::class,
         App\Providers\LocalServiceProvider::class,
         App\Services\Html\ServiceProvider::class,
         App\Services\Validation\ServiceProvider::class,
 
+        Prettus\Repository\Providers\RepositoryServiceProvider::class,
+
     ],
 
     /*
```

`Prettus\Repository\Providers\RepositoryServiceProvider::class`は`providers`の最後に追加しないとおかしな動作をするので注意する。


```php:app/Providers/RepositoryServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

/**
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class RepositoryServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        $repositories = [
            // \App\Repositories\UserRepository::class,
        ];

        foreach ($repositories as $repository) {
            $this->app->bind($repository, $repository.'Eloquent');
        }
    }
}
```

```console
$ php artisan vendor:publish
```


# [laracasts/flash](https://github.com/laracasts/flash)の設定

## インストール

```console
$ composer require laracasts/flash
```

## 設定

```diff:config/app.php
diff --git bd1429e..fc0ff5c fc0ff5c
index bd1429e..fc0ff5c 100644
--- config/app.php
+++ config/app.php
@@ -147,6 +147,7 @@ return [
         Illuminate\Translation\TranslationServiceProvider::class,
         Illuminate\Validation\ValidationServiceProvider::class,
         Illuminate\View\ViewServiceProvider::class,
+        Laracasts\Flash\FlashServiceProvider::class,
 
         /*
          * Application Service Providers...
@@ -209,6 +210,7 @@ return [
         'View'      => Illuminate\Support\Facades\View::class,
         'Form'      => Collective\Html\FormFacade::class,
         'Html'      => Collective\Html\HtmlFacade::class,
+        'Flash'     => Laracasts\Flash\Flash::class,
 
     ],
```

```console
$ php artisan vendor:publish
```

# [whoops](https://github.com/filp/whoops)の設定

## インストール

```console
$ composer require filp/whoops --dev
```

## 設定

```diff:app/Exceptions/Handler.php
diff --git app/Exceptions/Handler.php app/Exceptions/Handler.php
index aa13677..2d8e5e9 100644
--- app/Exceptions/Handler.php
+++ app/Exceptions/Handler.php
@@ -49,4 +49,39 @@ class Handler extends ExceptionHandler
     {
         return parent::render($request, $e);
     }
+
+    /**
+     * Create a Symfony response for the given exception.
+     *
+     * @param  \Exception  $e
+     *
+     * @return \Symfony\Component\HttpFoundation\Response
+     */
+    protected function convertExceptionToResponse(Exception $e)
+    {
+        if (config('app.debug')) {
+            return $this->renderExceptionWithWhoops($e);
+        }
+
+        return parent::convertExceptionToResponse($e);
+    }
+
+    /**
+     * Render an exception using Whoops.
+     *
+     * @param  \Exception $e
+     *
+     * @return \Illuminate\Http\Response
+     */
+    protected function renderExceptionWithWhoops(Exception $e)
+    {
+        $whoops = new \Whoops\Run();
+        $whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler());
+
+        return response()->make(
+            $whoops->handleException($e),
+            method_exists($e, 'getStatusCode') ? $e->getStatusCode() : 500,
+            method_exists($e, 'getHeaders') ? $e->getHeaders() : []
+        );
+    }
 }
```