---
# System prepended metadata

title: Laravel_01

---

### 授業資料ダウンロードリンク
[Googleドライブ](https://drive.google.com/drive/folders/1PVyoulX1_TY-mPQaN4SEnNGUpzpRvagu?usp=sharing)

## 環境構築
### 【AWSコンソールにログイン】
#### 1. まずはAWSAcademyにログイン
#### 2. 左側のリストからコースを選択
#### 3. モジュールをクリックして画面中央の「Learner Lab」を開く
#### 4. 「Start Lab」ボタンをクリック
#### 5. 「AWS」の横のランプがグリーンになったら「AWS」のリンクをクリック
#### 6. AWSマネジメントコンソールへログインできます。
#### 7. 上部検索窓からAWSCloud9と検索してクリック
#### 8. AWSCloud9の管理画面に入れます。

### 【AWSCloud9でプロジェクト作成】
#### 1. Create environmentをクリック
環境設定情報
```
Name： 自由
Description： 自由
Environment type：New EC2 instance
Instance type： Additional instance types t2.micro
Connection: Secure Shell (SSH)
その他は変更なし
```
#### 2. 入力できたらCreateをクリック
#### 3. 管理画面のプロジェクト一覧からopenをクリック
＊Cloud9のエディターか立ち上がります。

### 【Laravelを動かす為に必要なものを導入していく】
基本的にLaravelを動かす為にはPHPとComposerが必要です。
AWSCloud9はクラウド上に空っぽのサーバーを借りてくるので必要なものは自分でインストールする必要があります。
今回は中身の詳細は軽く説明だけにして簡単にインストールできるようにパッケージにしたシェルスクリプトを実行することで準備します。

#### 1.Fileタブから今日の授業資料からsetup.shをアップロードします。

#### 2. セットアップのシェルスクリプトを実行
`sh setup.sh`

## Laravelのプロジェクト立ち上げ
### 【Laravelの起動】

#### 1. サーバーの起動とLaravelプロジェクトの起動チェック
#ディレクトリ移動
`cd cms`

#BuiltInサーバーを起動：動作確認
`php artisan serve --port=8080`

＊Cloud9の画面上部の緑の起動ボタンの左側Previewボタン＞Preview Running Applicationをクリック
右下に画面が起動してLaravelの文字が確認できたらOK

#### 3.コンポーザーをアップデートしておく
`sudo composer update`

### 【データベースの作成】
ターミナルの上に緑プラスボタンからNewterminalを起動
`mysql -u root -p`
`root [Enterキー]`
`create database c9;`
`show databases; `
`exit;`

### 【Laravelプロジェクト初期設定】
#### 1. env（ファイル内の同じ箇所を上書き）
```
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=c9
DB_USERNAME=root
DB_PASSWORD=root
```

#### 2. サーバーの再起動
サーバー起動後のターミナル上で
`Ctrl + C`

#### 3. /app/Providers/ AppServiceProvider.php ファイルを修正
```
 use Illuminate\Support\Facades\URL;    //この行を追加

//bootメソッドを以下に変更
 public function boot()
{
    URL::forceScheme('https');          //この行を追加
}
```

#### 4. 表示の仕組みをチェックしてみる！
#4-1  /resouces/views/welcome.blade.php を編集して見よう！
#4-2 ブラウザ・更新で確認 →　変更確認できればOK

## ログイン認証
### 【ログイン認証実装】
#### 0.cms階層に移動
`cd cms`

#### 1. Laravel 9.x の場合
`sudo composer require laravel/breeze --dev`
質問が来たらyesでOK

#### 2. artisan コマンドを実行
`php artisan breeze:install`
インストールするバージョンはblade(0)を選択
他の質問はyesでOK

#### 3. npmパッケージをインストール
`npm install`

#### 4. パッケージをビルド
`npm run build`

#### 5．テーブル作成
`php artisan migrate`

#### 6. ログイン画面へのリンクを追加する以下２ページ
/resources/views/auth/register.blade.php
/resources/views/auth/login.blade.php
```
#<x-guest-layout>
省略

#</x-guest-layout>...以下...

<!-- 以下を追加 -->
@if (Route::has('login'))
    <div class="hidden fixed top-0 right-0 px-6 py-4 sm:block">
        @auth
            <a href="{{ url('/dashboard') }}" class="text-sm text-gray-700 dark:text-gray-500 underline">Dashboard</a>
        @else
            <a href="{{ route('login') }}" class="text-sm text-gray-700 dark:text-gray-500 underline">Log in</a>

            @if (Route::has('register'))
                <a href="{{ route('register') }}" class="ml-4 text-sm text-gray-700 dark:text-gray-500 underline">Register</a>
            @endif
        @endauth
    </div>
@endif
```

## 本管理アプリ実装（簡単なCRUDの実装）
### 【データベースにbooksテーブルを作成する為にマイグレーションを作成】
#### 1. artisanコマンドでモデル作成する（モデル＆コントローラー&マイグレーションファイルも一緒に作成）
`php artisan make:model Book -mcr`

#### 2. database/migrationsの直下のbooks_table.phpに以下追記
```
 public function up()
     {
         Schema::create('books', function (Blueprint $table) {
             $table->bigIncrements('id');
             $table->string('item_name');
             $table->integer('item_number');
             $table->integer('item_amount');
             $table->datetime('published');
             $table->timestamps();
         });
 }
```
#### 3. マイグレーション実行（テーブルの作成）
`php artisan migrate`

#### 2./routes/web.phpに以下二行を追記してモデルを呼び出す
```
use App\Http\Controllers\BookController; //追加
use App\Models\Book; //追加
```

### 【ルーティングとviewの準備】
#### 1. /routes/web.phpに以下の記述を追加
```
 <?php
use App\Http\Controllers\ProfileController;//9.43.x~
use Illuminate\Support\Facades\Route;
use Illuminate\Http\Request;
use App\Http\Controllers\BookController; //追加
use App\Models\Book; //追加

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

//本：ダッシュボード表示(books.blade.php)
Route::get('/', [BookController::class,'index'])->middleware(['auth']);

//本：追加 
Route::post('/books',[BookController::class,"store"]);

//本：削除 
Route::delete('/book/{book}', [BookController::class,"destroy"]);

//本：更新画面表示
Route::post('/booksedit/{book}',[BookController::class,"edit"]); //通常

//本：更新処理
Route::post('/books/update',[BookController::class,"update"]);

//*****ここから下はデフォルトで入ってます*****
Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
```
#### 2. /resources/views/components/collection.blade.php を作成し以下の内容をコピー
collection.blade.php
```
<div class="flex justify-between p-4 items-center bg-blue-500 text-white rounded-lg border-2 border-white">
  <div>{{ $slot }}</div>
  <button>×</button>
</div>
```
#### 3. /resources/views/components/errors.blade.php を作成し以下の内容コピー
```
 <!-- resources/views/components/errors.blade.php -->
@if (count($errors) > 0)
    <!-- Form Error List -->
    <div class="flex justify-between p-4 items-center bg-red-500 text-white rounded-lg border-2 border-white">
        <div><strong>入力した文字を修正してくた?さい。</strong></div> 
        <div>
            <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
            </ul>
        </div>
    </div>
@endif
```

#### 4. resources/views/components/button.blade.phpを作成し以下の内容をコピー
```
<button {{ $attributes->merge(['type' => 'submit', 'class' => 'inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 active:bg-gray-900 focus:outline-none focus:border-gray-900 focus:ring ring-gray-300 disabled:opacity-25 transition ease-in-out duration-150']) }}>
    {{ $slot }}
</button>
```

#### 5. resources/views/books.blade.php を作成し以下の内容コピー
```
<!-- resources/views/books.blade.php -->
<x-app-layout>

    <!--ヘッダー[START]-->
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
            
        </h2>
    </x-slot>
    <!--ヘッダー[END]-->
            
        <!-- バリデーションエラーの表示に使用-->
       <x-errors id="errors" class="bg-blue-500 rounded-lg">{{$errors}}</x-errors>
        <!-- バリデーションエラーの表示に使用-->
    
    <!--全エリア[START]-->
    <div class="flex bg-gray-100">

        <!--左エリア[START]--> 
        <div class="text-gray-700 text-left px-4 py-4 m-2">
            
            <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                <div class="p-6 bg-white border-b border-gray-500 font-bold">
                    本を管理する
                </div>
            </div>


            <!-- 本のタイトル -->
            <form action="{{ url('books') }}" method="POST" class="w-full max-w-lg">
                @csrf
                  <div class="flex flex-col px-2 py-2">
                   <!-- カラム１ -->
                    <div class="w-full md:w-1/1 px-3 mb-2 md:mb-0">
                      <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
                       Book Name
                      </label>
                      <input name="item_name" class="appearance-none block w-full text-gray-700 border border-red-500 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white" type="text" placeholder="">
                    </div>
                    <!-- カラム２ -->
                    <div class="w-full md:w-1/1 px-3">
                      <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
                        金額
                      </label>
                      <input name="item_amount" class="appearance-none block w-full text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" type="text" placeholder="">
                    </div>
                    <!-- カラム３ -->
                    <div class="w-full md:w-1/1 px-3 mb-2 md:mb-0">
                      <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
                        数
                      </label>
                      <input name="item_number" class="appearance-none block w-full text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" type="text" placeholder="">
                    </div>
                    <!-- カラム４ -->
                    <div class="w-full md:w-1/1 px-3 mb-6 md:mb-0">
                      <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
                        発売日
                      </label>
                      <input name="published" type="date" class="appearance-none block w-full text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" type="text" placeholder="">
                    </div>
                  </div>
                  <!-- カラム５ -->
                  <div class="flex flex-col">
                      <div class="text-gray-700 text-center px-4 py-2 m-2">
                             <x-button class="bg-blue-500 rounded-lg">送信</x-button>
                      </div>
                   </div>
            </form>
        </div>
        <!--左エリア[END]--> 
    
    
    <!--右側エリア[START]-->
    <div class="flex-1 text-gray-700 text-left bg-blue-100 px-4 py-2 m-2">
        <x-collection>テスト１</x-collection>
        <x-collection>テスト２</x-collection>
        <x-collection>テスト３</x-collection>
    </div>
    <!--右側エリア[[END]-->       

</div>
 <!--全エリア[END]-->

</x-app-layout>
```

#### 6. コンポートネントをビルド
`npm run build`

### 【登録処理実装】
#### 1. /app/Http/Controllers/BookController.phpを開いて以下1行追加！！
```
BookController.phpの上部
# use App\Models\Book; 
# use Illuminate\Http\Request;

use Validator;  //この1行だけ追加！
```

#### 2. BookController.phpのstoreメソッドに以下を以下に変更
```
public function store(Request $request) {
   //** ↓ 下をコピー ↓ **
   
      
    //バリデーション
    $validator = Validator::make($request->all(), [
         'item_name' => 'required|min:3|max:255',
         'item_number' => 'required | min:1 | max:3',
         'item_amount' => 'required | max:6',
         'published'   => 'required',
    ]);

    //バリデーション:エラー 
    if ($validator->fails()) {
        return redirect('/')
            ->withInput()
            ->withErrors($validator);
    }
    //以下に登録処理を記述（Eloquentモデル）

  // Eloquentモデル
  $books = new Book;
  $books->item_name   = $request->item_name;
  $books->item_number = $request->item_number;
  $books->item_amount = $request->item_amount;
  $books->published   = $request->published;
  $books->save(); 
  return redirect('/');
  
  
   //** ↑ 上をコピー ↑ **
}
```

### 【一覧表示処理実装】
#### 1. BookController.phpのindexメソッドを以下に変更
```
public function index() {
   //** ↓ 下をコピー ↓ **    
    
    $books = Book::orderBy('created_at', 'asc')->get();
    return view('books', [
        'books' => $books
    ]);
    
    //** ↑ 上をコピー ↑ **
}
```

#### 2. resources/views/books.blade.phpに表示領域を作成
books.blade.phpの 右側エリアを全て上書き！！
```
<!--右側エリア[START]-->
    <div class="flex-1 text-gray-700 text-left bg-blue-100 px-4 py-2 m-2">
         <!-- 現在の本 -->
        @if (count($books) > 0)
            @foreach ($books as $book)
                <x-collection id="{{ $book->id }}">{{ $book->item_name }}</x-collection>
            @endforeach
        @endif
    </div>
<!--右側エリア[[END]-->  
```

#### 3. /resources/views/components/collection.blade.php を更新！！
```
<!-- 本: 削除ボタン -->
<div class="flex justify-between p-4 items-center bg-blue-500 text-white rounded-lg border-2 border-white">
  <div>{{ $slot }}</div>
  
    <div>
    <form action="{{ url('booksedit/'.$id) }}" method="POST">
         @csrf
         
        <button type="submit"  class="btn bg-blue-500 rounded-lg">
            更新
        </button>
        
     </form>
  </div>
  
  <div>
    <form action="{{ url('book/'.$id) }}" method="POST">
         @csrf
         @method('DELETE')
        
        <button type="submit"  class="btn bg-blue-500 rounded-lg">
            削除
        </button>
        
     </form>
  </div>

</div>
```

### 【削除処理の実装】
#### 1. BookController.phpのdestroyメソッドを以下に変更
```
public function destroy(Book $book) {
   //** ↓ 下をコピー ↓ **    
    
    $book->delete();       //追加
    return redirect('/');  //追加
    
     //** ↑ 上をコピー ↑ **
});
```

### 【更新画面表示の処理を作成】
#### 1．更新画面を作成 /resources/views/booksedit.blade.php を作成
```
<!-- resources/views/booksedit.blade.php -->
<x-app-layout>

            
        <!-- バリデーションエラーの表示に使用-->
        <x-errors id="errors" class="bg-blue-500 rounded-lg">{{$errors}}</x-errors>
        <!-- バリデーションエラーの表示に使用-->
    
    <!--全エリア[START]-->
    <div class="flex bg-gray-100">

        <!--左エリア[START]--> 
        <div class="text-gray-700 text-left px-4 py-4 m-2">
            
            <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                <div class="p-6 bg-white border-b border-gray-500 font-bold">
                    本を管理する
                </div>
            </div>


            <!-- 本のタイトル -->
            <form action="{{ url('books/update') }}" method="POST" class="w-full max-w-lg">
                @csrf
                
                  <div class="flex flex-col px-2 py-2">
                   <!-- カラム１ -->
                    <div class="w-full md:w-1/1 px-3 mb-2 md:mb-0">
                      <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
                       Book Name
                      </label>
                      <input name="item_name" value="{{$book->item_name}}" class="appearance-none block w-full text-gray-700 border border-red-500 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white" type="text" placeholder="">
                    </div>
                    <!-- カラム２ -->
                    <div class="w-full md:w-1/1 px-3">
                      <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
                        金額
                      </label>
                      <input name="item_amount" value="{{$book->item_amount}}" class="appearance-none block w-full text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" type="text" placeholder="">
                    </div>
                    <!-- カラム３ -->
                    <div class="w-full md:w-1/1 px-3 mb-2 md:mb-0">
                      <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
                        数
                      </label>
                      <input name="item_number" value="{{$book->item_number}}" class="appearance-none block w-full text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" type="text" placeholder="">
                    </div>
                    <!-- カラム４ -->
                    <div class="w-full md:w-1/1 px-3 mb-6 md:mb-0">
                      <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2">
                        発売日
                      </label>
                      <input name="published" type="datetime-local" value="{{$book->published}}" class="appearance-none block w-full text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"  placeholder="">
                    </div>
                  </div>
                  <!-- カラム５ -->
                  <div class="flex flex-col">
                      <div class="text-gray-700 text-center px-4 py-2 m-2">
                             <x-button class="bg-blue-500 rounded-lg">更新</x-button>
                      </div>
                   </div>
                <!-- id値を送信 -->
                <input type="hidden" name="id" value="{{$book->id}}">
                <!--/ id値を送信 -->
            </form>
        </div>
        <!--左エリア[END]--> 
    
    
    <!--右側エリア[START]-->
    <div class="flex-1 text-gray-700 text-left bg-blue-100 px-4 py-2 m-2">
      
    </div>
    <!--右側エリア[[END]-->       

</div>
 <!--全エリア[END]-->

</x-app-layout>
```
#### 2. BookController.phpのeditメソッドを以下に変更
```
public function edit(Book $book)
    {
        //** ↓ 下をコピー ↓ **
        
        //{books}id 値を取得 => Book $books id 値の1レコード取得
        return view('booksedit', ['book' => $book]);
        
        //** ↑ 上をコピー ↑ **!
    }
```

### 【更新処理の実装】
#### 1. BookController.phpのupdateメソッドを以下に変更
```
public function update(Request $request, Book $book)
    {
      //** ↓ 下をコピー ↓ **


        //バリデーション
         $validator = Validator::make($request->all(), [
             'id' => 'required',
             'item_name' => 'required|min:3|max:255',
             'item_number' => 'required|min:1|max:3',
             'item_amount' => 'required|max:6',
             'published' => 'required',
        ]);
        //バリデーション:エラー
         if ($validator->fails()) {
             return redirect('/booksedit/'.$request->id)
                 ->withInput()
                 ->withErrors($validator);
        }
        
        //データ更新
        $books = Book::find($request->id);
        $books->item_name   = $request->item_name;
        $books->item_number = $request->item_number;
        $books->item_amount = $request->item_amount;
        $books->published   = $request->published;
        $books->save();
        return redirect('/');
        
        
        //** ↑ 上をコピー ↑ **!
    }
```



### 【ページネーション実装】
#### 1. BooksControllerのindexの処理を以下に変更
```
public function index()
    {
        $books = Book::orderBy('created_at', 'asc')->paginate(3);
        return view('books', [
            'books' => $books
        ]);
    }
```

#### 2.  books.blade.phpの右側エリアの下に追加
```
<div>
    {{ $books->links()}}
</div>
```
