【Laravel】課題：26章 演習課題 日記帳アプリの作成

## 手順

### プロジェクトの作成

以下のコマンドを打つ

```
cd ~/environment
composer create-project laravel/laravel laravel_diary --prefer-dist 6.*
```

###  .envの修正
```php
（省略）
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_diary_development
DB_USERNAME=root
DB_PASSWORD=secret
```

### タイムゾーンの修正
```php
'timezone' => 'UTC',
```

### ロケールの変更
```php
'locale' => 'en',
```

### TrustProxies ミドルウェアの修正
#### app/Http/MiddleWare/TrustProxies.php
```php
protected $proxies = '*'; // 全てのプロクシを信頼する。
```

### データベースの作成

phpMyAdminからlaravel_diary_developmentを作成。

照合順序はutf8mb4_unicode_ciを選択。


### データベースの動作確認

```php
php artisan migrate
```

「Migration table created successfully. 」から始まるメッセージが表示されればOK。


### コントローラーの作成
```php
cd laravel_diary

php artisan make:controller DiaryControlller

```

### モデルの作成＆マイグレーションの作成
```php

cd ~/environment/laravel_diary

php artisan make:model Diary --migration

```



# ルーティング

/laravel_diary/routes/**web.php**

```php
<?php
Route::get('/diaries', 'DiaryControlller@index');

Route::get('/diaries/create', 'DiaryControlller@create');

Route::post('/diaries', 'DiaryControlller@store');

Route::get('/diaries/{id}/edit', 'DiaryControlller@edit');

Route::patch('/diaries/{id}', 'DiaryControlller@update');

Route::delete('/diaries/{id}', 'DiaryControlller@destroy');
```

# コントローラー
/laravel_diary/app/Http/Controllers/**DiaryControlller.php**

```php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Diary;

use App\Http\Requests\DiaryRequest;

class DiaryControlller extends Controller
{
    public function index(){
        $diaries = Diary::all();
        return view('diary.index', [
        'title' => '日記一覧',
        'diaries' => $diaries,
      ]);
    }
    
    public function create(){
        return view('diary.create', [
        'title' => '日記一覧',
      ]);
    }
    
    public function store(DiaryRequest $request){
        Diary::create(
        $request->only([
                'title',
                'log'
            ])
        );
        session()->flash('success', '日記を追加しました！');
        return redirect('/diaries');
        
    }
    
    public function edit(int $id){
        $diary = Diary::find($id);
        
        return view('diary.edit', [
           'title' => '日記編集',
           'diary' => $diary,
        ]);
    }
    
    public function update(int $id, DiaryRequest $request){
        $diary = Diary::find($id);
        $diary->update($request->only(['title', 'log']));
        session()->flash('success', '日記を更新しました！');
        return redirect('/diaries');
        
    }
    
    public function destroy(int $id){
        $diary = Diary::find($id);
        $diary->delete();
        session()->flash('success', '日記を削除しました！');
        return redirect('/diaries');
    }
}

```

# モデル

/laravel_diary/app/**Diary.php**

```php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Diary extends Model
{
    public $fillable = ['title', 'log'];
}

```

# マイグレーションファイル

/laravel_diary/database/migrations/**2021_06_25_224044_create_diaries_table.php**

```php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateDiariesTable extends Migration
{
    public function up()
    {
        Schema::create('diaries', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('title', 100);
            $table->string('log', 2000);
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('diaries');
    }
}

```

# 一覧画面のビュー
/laravel_diary/resources/views/diary/**index.blade.php**

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

@section('title', $title)

@section('content')
<h1 class = "title" >日記一覧画面</h1>

<div class = "box">

    <a href="{{ url('/diaries/create') }}">新規投稿</a>

    <div>
        
    @forelse($diaries as $diary)
        <div class = "diary">
            <p>{{ $diary->title }} {{ $diary->created_at}}</p>
            <p>{{ $diary->log }}</p>
            <a href="{{ url('/diaries/' . $diary->id . '/edit') }}">編集</a>
            <form action="{{ url('/diaries/' . $diary->id) }}" method="post">
              @csrf
              @method('DELETE')  
                <input type="submit" value="削除">
            </form>
        </div>
    @empty
    
    <p>日記がありません。</p>
    
    @endforelse
    
    </div>
</div>

@endsection
```


# 新規投稿画面のビュー
/laravel_diary/resources/views/diary/**create.blade.php**

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

@section('title', $title)

@section('content')
<h1>日記追加画面</h1>
<a href="{{ url('/diaries') }}">一覧に戻る</a>

<form method="post" action="{{ url('/diaries') }}">
  @csrf
  
  <div>
    <label>
      タイトル：
      <input type="text" name="title" placeholder="日記のタイトルを入力">
    </label>
  </div>
  
  <div>
    <label>
      <textarea type="text" name="log" placeholder="内容を入力" rows="5" cols="80"></textarea>
    </label>
  </div>
  
  <input type="submit" value="保存">

</form>
@endsection

```

# 編集画面のビュー
/laravel_diary/resources/views/diary/**edit.blade.php**

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

@section('title', $title)

@section('content')
<h1>日記編集画面</h1>
<a>一覧に戻る</a>

<form action="{{ url('/diaries/' . $diary->id) }}" method="post">
  @csrf
  @method('PATCH')
  <div>
    <label>
      タイトル：
      <input type="text" name="title"  value = "{{$diary->title}}" placeholder="日記のタイトルを入力">
    </label>
  </div>
  <div>
    <label>
      <textarea type="text" name="log" placeholder="内容を入力">{{$diary->log}}</textarea>
    </label>
  </div>

  <input type="submit" value="保存">
</form>

@endsection
```

# デフォルトテンプレートのビュー
/laravel_diary/resources/views/diary/**create.blade.php**

```php
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="{{ secure_asset('css/styles.css') }}">
    <title>@yield('title')</title>
    <style>
        .header_nav {
            display: flex;
            list-style: none;
            padding-left: 0;
        }
        .header_nav li {
            margin-right: 30px;
        }
        /* エラーメッセージ用のスタイル */
        .error {
          color: red;
        }
        /* 成功メッセージ用のスタイル */
        .success {
          color: green;
        }
        
        .diary {
          border: 1px solid #000;
          padding :20px;
          margin :20px;
          width :600px;
        }
        
        .box {
            display:flex;
            justify-content:center;
        }
        
        .title {
            display:flex;
            justify-content:center;
        }
    </style>
</head>
<body>
    @yield('header')
 
    {{-- エラーメッセージを出力 --}}
    @foreach($errors->all() as $error)
      <p class="error">{{ $error }}</p>
    @endforeach
 
    {{-- 成功メッセージを出力 --}}
    @if (session()->has('success'))
        <div class="success">
            {{ session()->get('success') }}
        </div>
    @endif
 
    @yield('content')
</body>
</html>
```

# バリデーションファイル
/laravel_diary/app/Http/Requests/**DiaryRequest.php**

```php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class DiaryRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
      return [
          'title' => ['required', 'max:100'],
          'log' => ['required',  'max:2000'],
      ];
    }
}
```


# エラーメッセージの日本語化ファイル

/laravel_diary/resources/lang/ja/**validation.php**

```php
<?php

return [

    /*
    |--------------------------------------------------------------------------
    | バリデーション言語行
    |--------------------------------------------------------------------------
    |
    | 以下の言語行はバリデタークラスにより使用されるデフォルトのエラー
    | メッセージです。サイズルールのようにいくつかのバリデーションを
    | 持っているものもあります。メッセージはご自由に調整してください。
    |
    */

    'accepted'             => ':attributeを承認してください。',
    'active_url'           => ':attributeが有効なURLではありません。',
    'after'                => ':attributeには、:dateより後の日付を指定してください。',
    'after_or_equal'       => ':attributeには、:date以降の日付を指定してください。',
    'alpha'                => ':attributeはアルファベットのみがご利用できます。',
    'alpha_dash'           => ':attributeはアルファベットとダッシュ(-)及び下線(_)がご利用できます。',
    'alpha_num'            => ':attributeはアルファベット数字がご利用できます。',
    'array'                => ':attributeは配列でなくてはなりません。',
    'before'               => ':attributeには、:dateより前の日付をご利用ください。',
    'before_or_equal'      => ':attributeには、:date以前の日付をご利用ください。',
    'between'              => [
        'numeric' => ':attributeは、:minから:maxの間で指定してください。',
        'file'    => ':attributeは、:min kBから、:max kBの間で指定してください。',
        'string'  => ':attributeは、:min文字から、:max文字の間で指定してください。',
        'array'   => ':attributeは、:min個から:max個の間で指定してください。',
    ],
    'boolean'              => ':attributeは、trueかfalseを指定してください。',

// 前後省略

    'starts_with'          => ':attributeには、:valuesのどれかで始まる値を指定してください。',
    'string'               => ':attributeは文字列を指定してください。',
    'timezone'             => ':attributeには、有効なゾーンを指定してください。',
    'unique'               => ':attributeの値は既に存在しています。',
    'uploaded'             => ':attributeのアップロードに失敗しました。',
    'url'                  => ':attributeに正しい形式を指定してください。',
    'uuid'                 => ':attributeに有効なUUIDを指定してください。',

    /*
    |--------------------------------------------------------------------------
    | Custom バリデーション言語行
    |--------------------------------------------------------------------------
    |
    | "属性.ルール"の規約でキーを指定することでカスタムバリデーション
    | メッセージを定義できます。指定した属性ルールに対する特定の
    | カスタム言語行を手早く指定できます。
    |
    */

    'custom' => [
        '属性名' => [
            'ルール名' => 'カスタムメッセージ',
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | カスタムバリデーション属性名
    |--------------------------------------------------------------------------
    |
    | 以下の言語行は、例えば"email"の代わりに「メールアドレス」のように、
    | 読み手にフレンドリーな表現でプレースホルダーを置き換えるために指定する
    | 言語行です。これはメッセージをよりきれいに表示するために役に立ちます。
    |
    */

// ここを追記

    'attributes' => [
        'title' => 'タイトル',
        'log' => '内容',
        ],

];

```