# Laravel授業2回目(PaizaCloud版) ## 環境構築(先週の復習) ### 【サーバーの立ち上げ】 #### 1. ログインが完了したら新規サーバ作成をクリックするボタンが表示されます。以下の設定でサーバー作成 ``` サーバ名:デフォルトでOK web開発:PHP,Laravel データベース:MySQL,phpMyAdmin その他は設定不要 ``` 新規作成ボタンをクリック ### 【Laravelプロジェクトの立ち上げ】 #### 1. ターミナルを立ち上げてLaravelプロジェクト作成コマンドを入力 `composer create-project laravel/laravel cms 6.* --prefer-dist` #### 2. cms(プロジェクトディレクトリ)にターミナル上で移動 `cd cms` #### 3. ターミナル上CMS階層でComposerコマンド実行 `sudo composer update` #### 4. ターミナル上CMS階層でBuiltInサーバーを起動:動作確認 `php artisan serve` server startedと表示されてURLが生成されればOKです。 左側に地球で8000番ポートでプロジェクトが立ち上がっているはずです。 ブラウザで確認までいきましょう。 ## VSCodeからSSH接続で開発できる環境を作る ### 【PaizaCloud上での設定】 #### 1. PaizaCloud上でターミナルを新規で開いて公開鍵・秘密鍵を生成するコマンドを実行 `ssh-keygen -f ~/id_rsa` #### 2. 生成された「id_rsa」と「id_rsa.pub」の二つのファイルをダウンロード #### 3. 公開鍵を表示してコピー `$cat id_rsa.pub ` 実行結果 ``` $cat id_rsa.pub ↓ここから ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7Th1CAeSpQVsE9UheYi0Vpw+bcKxEqjooIHhaXLow2whnRRDnsSejaMVxH6OyTx81J5wlqTq/UXaViPMAeB5・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ ↑ここまでコピー .ssh ユーザー名$ ``` #### 4. PaizaCloudの左側メニューからSSH設定を開いてSSHkeyの部分に先程コピーした公開鍵を貼り付けてSAVE この作業でPaziaCloud上の作業は終了です。 ### 【ローカルPC(自分のパソコン)での設定】 #### 1. ローカル(自分のPC)で自分のOSにあった以下のフォルダの階層から「.ssh」フォルダを開く 表示されない場合は隠しファイル表示のショートカットキーは「command」+「shift」+「.」 です。 winはタスクバーからエクスプローラーを開いて[表示]>[表示]>[隠しファイル]を選択します。 ない場合は自分で作成してOKです。 ``` Windows C:\Users\ユーザ名\.ssh Mac /Users/ユーザ名/.ssh ``` #### 2. 「.ssh」フォルダの中にpaizaというフォルダを作成 ``` Windows C:\Users\ユーザ名\.ssh\paiza Mac /Users/ユーザ名/.ssh/paiza ``` #### 3. さっきダウンロードしてきた「id_rsa」と「id_rsa.pub」をpaizaの中に移動 ``` 【Windows】 C:\Users\ユーザ名\.ssh\paiza\id_rsa \id_rsa.pub 【Mac】 /Users/ユーザ名/.ssh/paiza/id_rsa /id_rsa.pub ``` #### 4. ターミナルで以下のコマンドを実行(権限を付与) `chmod 600 .ssh/paiza/id_rsa` #### 5. VSCodeで拡張機能の「Remote Development」を探して有効化 #### 6. VSCodeのSSH設定用のファイルを開く VSCodeの画面左下の歯車アイコンからコマンドパレットを起動 コマンドパレットから「>Remote-SSH: Open configuration File」を実行 下記のファイルを開く ``` Windows C:\Users\ユーザ名\.ssh\config Mac /Users/ユーザ名/.ssh/config ``` #### 7. SSH設定に書き変える paizacloudのSSH設定のSSH CommandのURLが個々人の接続コマンドです。 ここから情報をコピペで作業してください。 ``` # Read more about SSH config files: https://linux.die.net/man/5/ssh_config Host paiza-cloud HostName 自分で決めたサーバー名.paiza-user-lite.cloud User ubuntu Port -pの次の数字 59123など、環境によって変わります IdentityFile ~/.ssh/paiza/id_rsa ``` 変更できたら保存 #### 8. リモートアクセス 画面左下の歯車アイコンからコマンドパレットを起動 コマンドパレットから「>Remote-SSH: >Remote-SSH: Connect to Host」を選択するとさっき作ったpaiza-cloudが選択できるのでクリック 新しいタブが開けばOK。 #### 9. フォルダを開いてみる 左側のファイルツリーから「Open Folder」をクリックし、デフォルトでホームディレクトリ /home/ubuntu が選択されているので先ほど作ったcmsを選択してOKを押してみましょう。 ## 共通初期設定 ### 【Laravelプロジェクト初期設定】 #### 1. データベースを作成 エディタ左側の一番上に🔽ボタンをクリックすると下の方にMySQLがあるのでStart MySQLをクリックしてMySQlを起動 phpMyAdminのタブ内のOpen phpMyAdminをクリックして起動 phpMyAdminの管理画面からc9というデータベースを作成。 ``` DB名:c9 照合順:utf8mb4_general_ci ``` #### 2. env(ファイル内の同じ箇所を上書き) *隠しファイル表示はエディタ左側ファイル階層で右クリック ``` DB_CONNECTION=mysql DB_HOST=localhost DB_PORT=3306 DB_DATABASE=c9 DB_USERNAME=root DB_PASSWORD= ``` #### 3. /app/Providers/AppServiceProvider.php ファイルを修正 ``` use Illuminate\Support\Facades\URL; //この行を追加 public function boot() { URL::forceScheme('https'); //この行を追加 } ``` #### 4. サーバーの再起動 envファイルなどの設定を書き換えたときは必ず再起動!! サーバー起動後のターミナル上で `Ctrl + C` #### 5. 表示の仕組みをチェックしてみる! #4-1 /resouces/views/welcome.blade.php を編集して見よう! #4-2 ブラウザ・更新で確認 → 変更確認できれば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_posts_table --create=posts` #### 2. database/migrationsの直下のposts_table.phpに以下追記 ``` public function up() { Schema::create('posts', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('post_title'); $table->string('post_desc'); $table->integer('user_id'); $table->timestamps(); }); } ``` #### 3. マイグレーション実行(テーブルの作成) `php artisan migrate` ### 【モデルの作成】 #### 1. artisanコマンドでモデル作成 `php artisan make:model Post` ### 【モデルにリレーションの設定を記述】 #### 1. App/User.phpの中の39行目を改行して以下の内容をコピー ``` // Postsテーブルとのリレーション (主テーブル側) public function posts() { return $this->hasMany('App\Post'); } ``` #### 2. App/Post.phpの中の9行目を改行して以下の内容をコピー ``` // Userテーブルとのリレーション (従テーブル側) public function user() { return $this->belongsTo('App\User'); } ``` ### 【投稿画面の作成】 #### 1. viewsの直下にposts.blade.phpを作成して以下の内容をコピペ ``` <!-- resources/views/posts.blade.php --> @extends('layouts.app') @section('content') <!-- Bootstrapの定形コード… --> <div class="card-body"> <div class="card-title"> 投稿フォーム </div> <!-- バリデーションエラーの表示に使用--> @include('common.errors') <!-- バリデーションエラーの表示に使用--> <!-- 投稿フォーム --> <form action="{{ url('posts') }}" method="POST" class="form-horizontal"> {{ csrf_field() }} <!-- 投稿のタイトル --> <div class="form-group"> 投稿のタイトル <div class="col-sm-6"> <input type="text" name="post_title" class="form-control"> </div> </div> <!-- 投稿の本文 --> <div class="form-group"> 投稿の本文 <div class="col-sm-6"> <input type="text" name="post_desc" 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> </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. postsコントローラーを作成 ``` php artisan make:controller PostsController --resource ``` #### 2. postsコントローラー内にモデルの呼び出しをした上でindexメソッドに投稿表示処理を記述 ``` use App\Post; //この行を上に追加 use App\User;//この行を上に追加 use Auth;//この行を上に追加 use Validator;//この行を上に追加 public function index() { // return view('posts'); } ``` #### 3. web.phpにルーティングを追記 ``` Route::get('/', 'PostsController@index'); ``` #### 4. posts.blade.phpのフォームを以下のタグで囲んでログインユーザーしか投稿できないようにする ``` @if( Auth::check() ) <form action="{{ url('posts') }}" method="POST" class="form-horizontal"> === ここは省略してます。=== </form> @endif ``` ### 【投稿処理の実装】 #### 1. web.phpにルーティングを追記 `Route::post('posts', 'PostsController@store');` #### 2. postsコントローラー内のstoreメソッドに登録処理を記述 ``` public function store(Request $request) { //バリデーション $validator = Validator::make($request->all(), [ 'post_title' => 'required|max:255', 'post_desc' => 'required|max:255', ]); //バリデーション:エラー if ($validator->fails()) { return redirect('/') ->withInput() ->withErrors($validator); } //以下に登録処理を記述(Eloquentモデル) $posts = new Post; $posts->post_title = $request->post_title; $posts->post_desc = $request->post_desc; $posts->user_id = Auth::id();//ここでログインしているユーザidを登録しています $posts->save(); return redirect('/'); } ``` ### 【投稿の一覧表示処理を実装】 #### 1. posts.blade.php内42行目に以下を記述して表示エリア作成 ``` @if (count($posts) > 0) <div class="card-body"> <div class="card-body"> <table class="table table-striped task-table"> <!-- テーブルヘッダ --> <thead> <th>投稿一覧</th> <th>&nbsp;</th> </thead> <!-- テーブル本体 --> <tbody> @foreach ($posts as $post) <tr> <!-- 投稿タイトル --> <td class="table-text"> <div>{{ $post->post_title }}</div> </td> <!-- 投稿詳細 --> <td class="table-text"> <div>{{ $post->post_desc }}</div> </td> <!-- 投稿者名の表示 --> <td class="table-text"> <div></div> </td> <!-- お気に入りボタン --> <td class="table-text"> </td> </tr> @endforeach </tbody> </table> </div> </div> @endif ``` #### 2. postコントローラー内のindexメソッドを以下のように変更してログインユーザーと紐付く投稿を取得する ``` public function index() { // 全ての投稿を取得 $posts = Post::get(); return view('posts',[ 'posts'=> $posts ]); } ``` #### 3. posts.blade.php内63行目を以下のように変更して投稿したユーザー名を表示 ``` <!-- 投稿者名の表示 --> <td class="table-text"> <div>{{ $post->user->name }}</div> </td> ``` ## リレーション(多対多) 投稿をお気に入り機能 ### 【データベースに中間テーブルを作成する為にマイグレーションを作成】 #### 1. artisanコマンドでマイグレーション 作成 `php artisan make:migration create_post_user_table --create=post_user` #### 2. database/migrationsの直下のpost_user_table.phpに以下追記 ``` public function up() { Schema::create('post_user', function (Blueprint $table) { $table->increments('id'); $table->unsignedBigInteger('user_id'); $table->unsignedBigInteger('post_id'); $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); //外部キー参照 $table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade'); //外部キー参照 $table->unique(['user_id', 'post_id'],'uq_roles'); //Laravelは複合主キーが扱いにくいのでユニークで代用 }); } ``` #### 3. マイグレーション実行(テーブルの作成) `php artisan migrate` ### 【モデルにリレーション設定】 #### 1. App/User.phpに以下の内容を追記 ``` // Postsテーブルとの多対多リレーション public function favo_posts() { return $this->belongsToMany('App\Post'); } ``` #### 2. App/Post.phpに以下の内容を追記 ``` // Userテーブルとの多対多リレーション public function favo_user() { return $this->belongsToMany('App\User'); } ``` ### 【お気に入りボタン&お気に入り処理実装】 #### 1. posts.blade.phpの69行名お気に入りボタンのtdタグ内に以下をコピペ ``` <form action="{{ url('post/'.$post->id) }}" method="POST"> {{ csrf_field() }} <button type="submit" class="btn btn-danger"> お気に入り </button> </form> ``` #### 2.web.phpにルーティングを追加 `Route::post('post/{post_id}', 'PostsController@favo');` #### 3. postコントローラーに新規でメソッドを作成 ``` public function favo($post_id) { } ``` #### 4. favoメソッドに以下に処理を追記 ``` public function favo($post_id) { //ログイン中のユーザーを取得 $user = Auth::user(); //お気に入りする記事 $post = Post::find($post_id); //リレーションの登録 $post->favo_user()->attach($user); return redirect('/'); } ``` ### 【お気に入り表示リストを作成】 #### 1. post.blade.phpの@endsectionのすぐ上にログインユーザーのみの表示エリアを設定 ``` @if( Auth::check() ) === ここに表示処理を作成 === @endif ``` #### 2. 作成したエリアの間に以下をコピペ ``` @if (count($favo_posts) > 0) <div class="card-body"> <div class="card-body"> <table class="table table-striped task-table"> <!-- テーブルヘッダ --> <thead> <th>お気に入り一覧</th> <th>&nbsp;</th> </thead> <!-- テーブル本体 --> <tbody> @foreach ($favo_posts as $favo_post) <tr> <!-- 投稿タイトル --> <td class="table-text"> <div>{{ $favo_post->post_title }}</div> </td> <!-- 投稿詳細 --> <td class="table-text"> <div>{{ $favo_post->post_desc }}</div> </td> <!-- 投稿者名の表示 --> <td class="table-text"> <div>{{ $favo_post->user->name }}</div> </td> </tr> @endforeach </tbody> </table> </div> </div> @endif ``` #### 3. postコントローラーのindexメソッドを以下のように変更 ``` public function index() { // 全ての投稿を取得 $posts = Post::get(); if (Auth::check()) { //ログインユーザーのお気に入りを取得 $favo_posts = Auth::user()->favo_posts()->get(); return view('posts',[ 'posts'=> $posts, 'favo_posts'=>$favo_posts ]); }else{ return view('posts',[ 'posts'=> $posts ]); } } ``` #### 4. お気に入りボタンの表示を切り分けたいのでposts.blade.phpのボタンエリアを以下のように変更 ``` @if(Auth::check()) @if(Auth::id() != $post->user_id && $post->favo_user()->where('user_id',Auth::id())->exists() !== true) <form action="{{ url('post/'.$post->id) }}" method="POST"> {{ csrf_field() }} <button type="submit" class="btn btn-danger"> お気に入り </button> </form> @endif @endif ``` ## テストデータ自動生成 seederの使い方 ### 【ユーザーのテストデータを自動生成】 #### 1. seederファイルをartisanコマンドで生成 `php artisan make:seeder UserTableSeeder` #### 2. database/seeds/UserTableSeederのrunメソッドの中を以下のように追記 ``` public function run() { \DB::table('users')->insert([ [ 'name' => 'テスト1', 'email' => 'test1@test.jp', 'password' => Hash::make('testtest') ], [ 'name' => 'テスト2', 'email' => 'test2@test.jp', 'password' => Hash::make('testtest') ], [ 'name' => 'テスト3', 'email' => 'test3@test.jp', 'password' => Hash::make('testtest') ], ]); } ``` #### 3. database/seeds/DatabaseSeeder.phpのrunメソッドに以下を追記 `$this->call(UserTableSeeder::class);` #### 4. cms階層でartisanコマンドを以下の順番で実行 `php artisan migrate:refresh` `php artisan db:seed` ### 【投稿(post)のテストデータを自動生成】 #### 1. spostテーブル用のeederファイルをartisanコマンドで生成 `php artisan make:seeder PostTableSeeder` #### 2. artisanコマンドでファクトリーを生成 `php artisan make:factory PostFactory` #### 3. databases/factories/Postfactory.phpの中身を以下に変更 ``` <?php /** @var \Illuminate\Database\Eloquent\Factory $factory */ use App\Model; use Faker\Generator as Faker; use App\User; //追記 $factory->define(App\Post::class, function (Faker $faker) { return [ 'post_title' => $faker->realText(100), 'post_desc' => $faker->realText(100), 'user_id' => function() { return User::all()->random(); } ]; }); ``` #### 4. database/seeds/PostTableSeederのrunメソッドの中を以下のように追記 ` $posts = factory(App\Post::class, 15)->create();` #### 5. database/seeds/DatabaseSeeder.phpのrunメソッドに以下を追記 `$this->call(PostTableSeeder::class);` #### 6. artisanコマンドを以下の順番で実行 `php artisan migrate:refresh` `php artisan db:seed` ##### *自動生成されるテキストを日本語にしたい場合は以下を変更 config/app.phpの109行名を以下に変更 ``` 'faker_locale' => 'ja_JP', ``` ##### *ログイン後のリダイレクト先を変更したい場合はapp/Providers/RouteServiceProvider.phpの24行目を以下のように変更 ``` public const HOME = '/home'; //変更前(home.blade.php) public const HOME = '/'; //変更後(トップページに遷移) ```