# Laravel授業4回目 ## 環境構築(先週の復習) ### 【環境構築(bashコマンド)】 #### 1. PHPセットアップ `sudo amazon-linux-extras install php7.2=stable` `sudo yum install php-mbstring php-pecl-memcached php-gd php-apcu php-xml` #### 2. データベースの準備 #### MaryaDB 構築 `sudo amazon-linux-extras install -y lamp-mariadb10.2-php7.2` #### MariaDBのインストール `sudo yum install -y mariadb-server` #### 3. MariaDBの起動&初期設定 `sudo systemctl start mariadb` `sudo mysql_secure_installation` ``` 初回設定の入力項目 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 ``` #### MaridaDBの自動起動を有効化 `sudo systemctl enable mariadb` `sudo systemctl is-enabled mariadb` #### 4. Composerインストール `curl -sS https://getcomposer.org/installer | php -- --version=2.1.6` `sudo mv composer.phar /usr/bin/composer` `composer` #### 5. Laravelインストール `composer create-project laravel/laravel cms 6.* --prefer-dist` #### 6. サーバーの起動と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\Support\Facades\Schema; //この行を追加 use Illuminate\Support\Facades\URL; //この行を追加 public function boot() { Schema::defaultStringLength(191); //この行を追加 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/4.8.3/phpMyAdmin-4.8.3-all-languages.zip` #### 3. zipファイルを解凍 `unzip phpMyAdmin-4.8.3-all-languages.zip` #### 4. cms階層に戻る `cd ..` ``` <手順解説> 1 publicフォルダ内に「phpMyAdmin-4.8.3-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 パッケージをインストール `composer require laravel/ui:^1.0 --dev` #### 3. artisan コマンドを実行 `php artisan ui vue --auth` #### 4. npmパッケージをインストール `npm install` #### 5. パッケージをビルド `npm run dev` ## リレーション(1対多) ### 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@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> ```