---
# System prepended metadata

title: Laravel EXP講座（講義１）

---

# Laravel EXP講座（講義１）
## 環境構築(先週の復習)
## 環境構築
### 【PHPセットアップ】
#### 1.パッケージのアップデート
`sudo yum update -y`

#### 2.PHPのパッケージをすべてアンインストール
`sudo yum -y remove php-*`

#### 3.amazon-linux-extrasをアップデート
`sudo yum update -y amazon-linux-extras`

#### 4.amazon-linux-extrasで使用中のパッケージと使えるパッケージを確認
`amazon-linux-extras`

#### 5.lamp-mariadb10.2-php7.2を使用停止
`sudo amazon-linux-extras disable lamp-mariadb10.2-php7.2`

#### 6.PHP8.0を有効化
`sudo amazon-linux-extras enable php8.0`

#### 7-1.インストールするパッケージの案内があったので、表示されたコマンドを実行
`sudo yum clean metadata && sudo yum install php-cli php-pdo php-fpm php-mysqlnd`

#### 7-2.インストールするパッケージの案内があったので、表示されたコマンドを実行
`sudo yum install php-cli php-common php-devel php-fpm php-gd php-mysqlnd php-mbstring php-pdo php-xml`

#### 8-1.apacheなどを再起動
`sudo systemctl restart httpd.service`
#### 8-2.apacheなどを再起動
`sudo systemctl restart php-fpm.service`

###  【データベースの準備】
#### 1.MariaDBデフォルト確認
`sudo yum list installed | grep mariadb`

#### 2.MariaDBのインストール
`sudo amazon-linux-extras install mariadb10.5 -y`

#### 3-1.Apache, MariaDBの起動
`sudo systemctl start mariadb`
#### 3-2.Apache, MariaDB初期設定
`sudo mysql_secure_installation`
```
初回設定の入力項目
Enter current password for root (enter for none):  [Enterキー]
Switch to unix_socket authentication [Y/n] y
Set root password? [Y/n] y
New password: root
Re-enter new password: root
Remove anonymous users? [Y/n] y 
Disallow root login remotely? [Y/n] y
Remove test database and access to it? [Y/n] y
Reload privilege tables now? [Y/n] y
```

#### 4-1.MaridaDBの自動起動を有効化
`sudo systemctl enable mariadb`
#### 4-2.MaridaDBの自動起動確認
`sudo systemctl is-enabled mariadb`

#### 5-1. Composerインストール
`curl -sS https://getcomposer.org/installer | php -- --version=2.3.5`
#### 5-2. Composerパスを通す
`sudo mv composer.phar /usr/bin/composer`
#### 5-3. Composer確認
`composer`


#### 6. Laravelインストール(最新バージョン)
`composer create-project "laravel/laravel=9.1.8" cms`

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

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

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

### 【データベースの作成】
`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\Routing\UrlGenerator;//この行を追加

//bootメソッドを以下に変更
 public function boot(UrlGenerator $url)
{
    $url->forceScheme('https');
}
```

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

### 【phpMyAdmin設定】
#### 1. cms階層からpublicフォルダに移動
`cd public`
#### 2. phpMyAdminのzipをダウンロード
`wget https://files.phpmyadmin.net/phpMyAdmin/5.1.2/phpMyAdmin-5.1.2-all-languages.zip`
#### 3. zipファイルを解凍
`unzip phpMyAdmin-5.1.2-all-languages.zip`
#### 4. cms階層に戻る
`cd ..`
> ＜手順解説＞
> 1 publicフォルダ内に「phpMyAdmin-5.1.2-all-languages」フォルダが作成される 
> 2 フォルダ名が長いので「phpMyAdmin」に変更
> 3「Preview」でサイトを開き、URLの最後に「phpMyAdmin/index.php」をつけてEnterキーを押す
> 4 URL例： https://＊＊＊＊＊＊.cloud9.us-east-1.amazonaws.com/phpMyAdmin/index.php
> 5 phpMyAdmin画面が表示されたら： ユーザー名・パスワードともに「root」を入力してログイン
> 6 ログインできればOK

## ログイン認証
### 【ログイン認証実装】
#### 1. マイグレーションを実行
`php artisan migrate`
#### 2. laravel/ui パッケージをインストール（Laravel 9.x の場合）
`composer require laravel/ui`
#### 3.  artisan コマンドを実行
`php artisan ui vue --auth`
#### 4. npmパッケージをインストール
`npm install`
#### 5.  パッケージをビルド(１回目)
`npm run dev`
#### 6.  パッケージをビルド(２回目)
`npm run dev`
＊なぜかビルド２回必要です！

## リレーション(1対多)
### １人のログインユーザーは複数のチームを作成してオーナーになることができる機能

#### 1 artisanコマンドでマイグレーション 作成
`php artisan make:migration create_teams_table --create=teams`


#### 2 database/migrationsの直下のteams_table.phpに以下追記
```
public function up()
    {
        Schema::create('teams', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('team_name');
	    $table->integer('user_id');
            $table->timestamps();
        });
}
```

#### 3 マイグレーション実行（テーブルの作成）
`php artisan migrate`


### モデルの作成(リレーションの設定)
#### 1： artisanコマンドでモデル作成
`php artisan make:model Team`

#### 1 App/User.phpの中の39行目を改行して以下の内容をコピー
 ```
// Teamsテーブルとのリレーション （主テーブル側）
     public function o_teams() {
        return $this->hasMany('App\Models\Team');
    }
```
#### 2　App/Team.phpの中の9行目を改行して以下の内容をコピー
```
 // Userテーブルとのリレーション （従テーブル側）
     public function user() {
        return $this->belongsTo('App\Models\User');
    }
```
### チーム作成画面の作成
#### 1 viewsの直下にteams.blade.phpを作成して以下の内容をコピペ
```

<!-- resources/views/teams.blade.php -->
@extends('layouts.app')
@section('content')
    <!-- Bootstrapの定形コード… -->
    <div class="card-body">
        <div class="card-title">
            投稿フォーム
        </div>
        <!-- バリデーションエラーの表示に使用-->
    	@include('common.errors')
        <!-- バリデーションエラーの表示に使用-->
        <!-- 投稿フォーム -->
        @if( Auth::check() )
        <form action="{{ url('teams') }}" method="POST" class="form-horizontal">
            {{ csrf_field() }}
            <!-- チーム名 -->
            <div class="form-group">
                チーム名
                <div class="col-sm-6">
                    <input type="text" name="team_name" class="form-control">
                </div>
            </div>
            <!--　登録ボタン -->
            <div class="form-group">
                <div class="col-sm-offset-3 col-sm-6">
                    <button type="submit" class="btn btn-primary">
                        Save
                    </button>
                </div>
            </div>
        </form>
        @endif
    </div>
    <!-- 全てのチームリスト -->
    
@endsection

```
#### 2 /resources/views/common/errors.blade.php を作成 し以下を追記
```

<!-- resources/views/common/errors.blade.php -->
@if (count($errors) > 0)
    <!-- Form Error List -->
    <div class="alert alert-danger">
        <div><strong>入力した文字を修正してください。</strong></div> 
        <div>
            <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
            </ul>
        </div>
    </div>
@endif

```

### 投稿画面表示処理の実装
#### 1 teamsコントローラーを作成
`php artisan make:controller TeamsController`

#### 2  teamsコントローラー内にモデルの呼び出しをした上でindexメソッドに投稿表示処理を記述

```
use App\Models\Team; //この行を上に追加
use App\Models\User;//この行を上に追加
use Auth;//この行を上に追加
use Validator;//この行を上に追加

public function index()
    {
        //
        return view('teams');
    }
```



#### 3 web.phpにルーティングを追記

```
use App\Http\Controllers\TeamsController;//追記

Route::get('/', [TeamsController::class, 'index']);
```


### チーム登録処理の実装
#### 1 web.phpにルーティングを追記
`Route::post('teams', [TeamsController::class, 'store']);`


#### 2 teamsコントローラー内のstoreメソッドに登録処理を記述
```

 public function store(Request $request)
    {
        //バリデーション 
        $validator = Validator::make($request->all(), [
            'team_name' => 'required|max:255'
        ]);
        
        //バリデーション:エラー
        if ($validator->fails()) {
            return redirect('/')
                ->withInput()
                ->withErrors($validator);
        }
        
        //以下に登録処理を記述（Eloquentモデル）
        $teams = new Team;
        $teams->team_name = $request->team_name;
        $teams->user_id = Auth::id();//ここでログインしているユーザidを登録しています
        $teams->save();
        
        return redirect('/');
        
    }
```
### チームの一覧表示処理を実装
#### 1 teams.blade.php内42行目に以下を記述して表示エリア作成
 ```
@if (count($teams) > 0)
        <div class="card-body">
            <div class="card-body">
                <table class="table table-striped task-table">
                    <!-- テーブルヘッダ -->
                    <thead>
                        <th>チーム一覧</th>
                        <th>オーナー</th>
                        <th>参加人数</th>
                        <th>詳細</th>
                        <th>参加</th>
                        <th>編集</th>
                    </thead>
                    <!-- テーブル本体 -->
                    <tbody>
                        @foreach ($teams as $team)
                            <tr>
                                <!-- チーム名 -->
                                <td class="table-text">
                                    <div>{{ $team->team_name }}</div>
                                </td>
                                 <!-- チームオーナー -->
                                <td class="table-text">
                                    <div>{{ $team->user->name }}</div>
                                </td>
                                <!-- 所属人数 -->
                                <td class="table-text">
                                    <div></div>
                                </td>
                                <!-- 詳細ボタン -->
                                <td class="table-text">
                                    
                                </td>
 				                <!-- チーム参加ボタン -->
                                <td class="table-text">
                                    
                                </td>
                                <!-- チーム編集ボタン-->
                                <td class="table-text">
                                    
                                </td>
                            </tr>
                        @endforeach
                    </tbody>
                </table>
            </div>
        </div>		
    @endif
```


#### 2 teamsコントローラー内のindexメソッドを以下のように変更してログインユーザーと紐付く投稿を取得する
```

 public function index()
    {
        //チーム 全件取得
        $teams = Team::get();
    
        
        return view('teams',[
            'teams'=> $teams
            ]);
    }
```

#### 3 temas.blade.php内63行目を以下のように変更して投稿したユーザー名を表示
 ```
<!-- チームオーナー -->
    <td class="table-text">
       <div>{{ $team->user->name }}</div>
    </td>
```

## リレーション(多対多）チーム参加機能
### データベースに中間テーブルを作成する為にマイグレーションを作成
#### 1 artisanコマンドでマイグレーション 作成
`php artisan make:migration create_team_user_table --create=team_user`


#### 2 database/migrationsの直下のpost_user_table.phpに以下追記
```
public function up()
    {
        Schema::create('team_user', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('user_id');
            $table->unsignedBigInteger('team_id');
            
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); //外部キー参照
            $table->foreign('team_id')->references('id')->on('teams')->onDelete('cascade'); //外部キー参照
            $table->unique(['user_id', 'team_id'],'uq_roles'); //Laravelは複合主キーが扱いにくいのでユニークで代用
            $table->timestamps();
        });
    }
```

#### 3 マイグレーション実行（テーブルの作成）
`php artisan migrate`


### モデルにリレーション設定
#### 1 App/User.phpに以下の内容を追記
```
 // Teamsテーブルとの多対多リレーション
     public function my_teams() {
        return $this->belongsToMany('App\Models\Team');
    }
```

#### 2　App/Team.phpに以下の内容を追記
```
 // Userテーブルとの多対多リレーション
     public function members() {
        return $this->belongsToMany('App\Models\User');
    }
```

### チーム参加ボタン&参加処理実装 
#### 1 teams.blade.phpの69行名チーム参加ボタンのtdタグ内に以下をコピペ
```
<form action="{{ url('team/'.$team->id) }}" method="GET">
	{{ csrf_field() }}
	<button type="submit" class="btn btn-danger">
	参加
	</button>
</form>
```
#### 2 web.phpにルーティングを追加
`Route::get('team/{team_id}', [TeamsController::class, 'join']);`

#### 3 teamsコントローラーに新規でメソッドを作成
```
public function join($team_id)
    {

    }
```
#### 4 joinメソッドに以下に処理を追記
```

 public function join($team_id)
    {
        //ログイン中のユーザーを取得
        $user = Auth::user();
        
        //お気に入りする記事
        $team = Team::find($team_id);
        
        //リレーションの登録
        $team->members()->attach($user);
        
        return redirect('/');
        
    }
```
#### 5 teams.blade.phpの所属人数の部分に以下のように記述
```
<!-- 所属人数 -->
<td class="table-text">
     <div>{{ $team->members()->count() }}人参加中</div>
</td>
```

#### 6 参加ボタンの表示を切り分けたいのでteams.blade.phpのボタンエリアを以下のように変更
```
@if(Auth::check())
　@if(Auth::id() != $team->user_id && $team->members()->where('user_id',Auth::id())->exists() !== true)
 　<form action="{{ url('team/'.$team->id) }}" method="GET">
	{{ csrf_field() }}
	<button type="submit" class="btn btn-danger">
	参加
	</button>
　　</form>
　@endif
@endif
```

#### 7 teamsコントローラーのstoreメソッドのリダイレクト処理の直前に以下の処理を追記
```
//多対多のリレーションもここで登録
$teams->members()->attach( Auth::user() );
```

## チーム編集機能
#### 1 teams.blade.phpのチーム編集ボタンのtd内に以下を記述
```
@if(Auth::check()&& Auth::id() == $team->user_id )
　　<form action="{{ url('teamedit/'.$team->id) }}" method="GET">
	{{ csrf_field() }}
	<button type="submit" class="btn btn-danger">
	編集
	</button>
　　</form>	
@endif
```
#### 2 web.phpにルーティングを作成
`Route::get('teamedit/{team}',  [TeamsController::class, 'edit']);
`

#### 3 teamsコントローラーにeditメソッドを作成して以下の処理を作成
```
//チーム編集画面表示
public function edit (Team $team) {
        
   return view('teamsedit', ['team' => $team]);
        
}
```
#### 4 teamsedit.blade.phpを作成して編集画面を作成
```
@extends('layouts.app')
@section('content')
<div class="row">
    <div class="col-md-12">
    @include('common.errors')
        <form action="{{ url('teams/update') }}" method="POST">
            <!-- item_name -->
            <div class="form-group">
                <label for="item_name">チーム名</label>
                <input type="text" name="team_name" class="form-control" value="{{$team->team_name}}">
            </div>
            <!--/ item_name -->
            <!-- Save ボタン/Back ボタン -->
            <div class="well well-sm">
                <button type="submit" class="btn btn-primary">Save</button>
                <a class="btn btn-link pull-right" href="{{ url('/') }}"> Back</a>
            </div>
            <!--/ Save ボタン/Back ボタン -->
            <!-- id 値を送信 -->
            <input type="hidden" name="id" value="{{$team->id}}" /> <!--/ id 値を送信 -->
            <!-- CSRF -->
            {{ csrf_field() }}
            <!--/ CSRF -->
        </form>
    </div>
</div>
@endsection
```
#### 5 ルーティングをweb.phpに記述
```
//チーム更新処理
Route::post('teams/update',  [TeamsController::class, 'update']);
```

#### 6 更新処理をteamsコントローラーに作成
```
//更新処理
public function update (Request $request) {
        
         //バリデーション 
        $validator = Validator::make($request->all(), [
            'team_name' => 'required|max:255',
        ]);
        
        //バリデーション:エラー
        if ($validator->fails()) {
            return redirect('/')
                ->withInput()
                ->withErrors($validator);
        }
        
        //対象のチームを取得
        $team = Team::find($request->id);
        $team->team_name = $request->team_name;
        $team->save();
        
        return redirect('/');
        
}
```

### チーム詳細機能
#### 1 web.phpにルーティングを作成
```
// チーム詳細表示
Route::get('teams/{team}', [TeamsController::class, 'show']);
```

#### 2 コントローラーに処理を追記
```
//詳細表示
public function show(Team $team)
{
    return view('teamsdetail',[
        'team'=> $team
        ]);
}
```

#### 3 teamsdetail.blade.phpを作成して以下をコピペ
```
@extends('layouts.app')
@section('content')
<div class="row">
    <div class="col-md-12">
        <h1>チーム名： {{ $team->team_name}}</h1>
        <h2>オーナー： {{ $team->user->name}}</h2>
        <h3>メンバー</h3>
        @foreach($team->members as $member)
        <p>{{ $member->name}}</p>
        @endforeach
    </div>
</div>
@endsection
```

#### 4　詳細ボタンをteams.blade.phpのtdタグないに追加
```
<a href="{{ url('teams/'.$team->id) }}" class="btn btn-danger">詳細</a>
```

## 複数オーナー対応（中間テーブルにデータを持たせるWithPivot）
#### 1 カラム追加用のマイグレーションを作成
`php artisan make:migration add_role_to_team_user_table --table=team_user`
#### 1 中間テーブルにカラムを追加
```
public function up()
    {
        Schema::table('team_user', function (Blueprint $table) {
            
            $table->string('role')->default('member');//<-これを追加しています！！！
            
        });
    }
```

#### 2 migration refresh（テーブル再構築：データ全部一回消えます）
`php artisan migrate`

#### 3 TeamsControllerのstoreメソッドの部分のアタッチを変更
```
   上は省略
   //以下に登録処理を記述（Eloquentモデル）
        $teams = new Team;
        $teams->team_name = $request->team_name;
        $teams->user_id = Auth::id();//ここでログインしているユーザidを登録しています
        $teams->save();
        
        //多対多のリレーションもここで登録
        $teams->members()->attach( Auth::user(),['role'=>'owner'] );//<-ここが変わってるよ！！
        
        return redirect('/');
```

#### 4 モデルの中でwithPivotの設定をする
##### App/Models/User.phpの多対多リレーションを変更
`->withPivot('カラム名');`をつけてあげる
```
 // Teamsテーブルとの多対多リレーション
     public function my_teams() {
        return $this->belongsToMany('App\Models\Team')->withPivot('role');
    }
```

##### 　App/Models/Team.phpの多対多リレーションを変更
```
 // Userテーブルとの多対多リレーション
     public function members() {
        return $this->belongsToMany('App\Models\User')->withPivot('role');
    }
```

#### 5 teamsdetail.blade.phpの表示部分を変更！
```
@extends('layouts.app')
@section('content')
<div class="row">
    <div class="col-md-12">
        <h1>チーム名： {{ $team->team_name}}</h1>
        <h2>オーナー： {{ $team->user->name}}</h2>
        <h3>メンバー</h3>
        @foreach($team->members as $member)
        <p>{{ $member->pivot->role}}：{{ $member->name}}</p>//<-ここが変わってるよ！
        @endforeach
    </div>
</div>
@endsection
```