# Laravel 01 ## 今日のコンテンツ * 環境構築 * ターミナル操作 * MVCモデル * CRUD実装 * ログイン認証 ※授業では下記の順番で学習します 1. ターミナル操作 & 環境構築 2. ログイン認証 3. MVCモデル学習 4. CRUD実装 ## 今日の目標 * MVCモデルがどういうものか感覚をつかむ * Laravelの操作になれる * Laravel Loveになる --- ## 環境構築 この章ではPaiza Cloudでサーバーを立てて、Laravelプロジェクトを作成、DBの作成と接続、そのほかの初期設定を行います :::success ① Paiza Cloudでサーバー作成 ② Laravelプロジェクトの作成 ③ データベース作成&接続 ④ /app/Providers/AppServiceProvider.php ファイルを修正 ::: #### ① Paiza Cloudでサーバー作成 1. アカウント取得 https://paiza.cloud/ja/ ※ ライトプランのクーポンで作成済み Paiza Cloudでデプロイまで行いたい場合は別途ベーシックプランが必要 2. サーバーの作成 * 「新規サーバー作成」をクリック * 下記設定で、「新規サーバー作成」 :::info サーバ名:デフォルトでOK web開発:PHP,Laravel データベース:MySQL,phpMyAdmin その他は設定不要 ::: ![](https://i.imgur.com/FyERMXQ.png) #### ② Laravelプロジェクトの作成 1. ターミナル上でLaravelプロジェクト作成コマンドを入力 `composer create-project laravel/laravel cms 6.* --prefer-dist` :::info 【メモ / `cms`が今回作るプロジェクトのディレクトリ名】 >「CMS」とは、「Contents Management System:コンテンツ・マネジメント・システム」の略で、簡単にいうとWebサイトのコンテンツを構成するテキストや画像、デザイン・レイアウト情報(テンプレート)などを一元的に保存・管理するシステムのこと > https://www.hitachi-solutions.co.jp/digitalmarketing/sp/column/cms_vol01/ ::: :::info 【メモ / 授業で使うバージョン】 ``` PHP 7.4.1 Laravel 6 (LTS) ``` ググる時はそのサイトがどのバージョンについて書かれているかも気にしてみましょう ::: 2. プロジェクトディレクトリに移動 ``` cd cms ``` 3. Composerコマンドを実行 ``` sudo composer update ``` 4. BuiltInのLaravelサーバーを起動 ``` php artisan serve ``` 5. 動作確認 ターミナルで下記の実行結果が表示されていればOK。 ``` Starting Laravel development server: http://127.0.0.1:8000 ``` ブラウザ(8000番ポート)をクリックして、実際にプレビュー画面を表示してみましょう(Laravelのホーム画面が表示されていれば成功!) #### ③ データベース作成&接続 1. データベースを作成 方法はいくつかありますが、今回はターミナルで作成にチャレンジしてみましょう! * ターミナルでDB作成する場合 ターミナル上で下記の手順で実行 ``` mysql -u root -p root [Enterキー] create database c9; exit; ``` * phpMyAdminで作成する場合 ①左タブからphpMyAdminのタブ内「Open phpMyAdmin」をクリック ②phpMyAdminの管理画面で `c9` というDBを作成 ※照合順は`utf8mb4_general_ci`を選択 2. 隠しファイルを表示 エディタ左側のファイル階層で右クリック→「隠しファイルを表示」 3. .envファイルを編集 cms直下にあるenvファイル内の同じファイルを上書き ``` DB_CONNECTION=mysql DB_HOST=localhost DB_PORT=3306 DB_DATABASE=c9 DB_USERNAME=root DB_PASSWORD= ``` :::info 【メモ】envはenvironment(環境)の略 ::: 4. Webサーバーを再起動 :::danger 超重要!!!**`.env`を変更後はWebサーバーを再起動**する ::: i. 起動中のwebサーバーを停止 `Ctl + C` ii. cmsディレクトリにいることを確認後、サーバー起動 `php artisan serve` #### ④ Laravelの/app/Providers/AppServiceProvider.php ファイルを修正 ```php use Illuminate\Support\Facades\URL; //この行を追加 public function boot() { URL::forceScheme('https'); //この行を追加 } ``` :::info 【Paiza Cloudのポイント】 ファイルを開いた時は「自動保存」にチェック または 必ず `Ctl + S` (windows) / `Command + S` (mac)を! ::: --- ## ターミナル操作 ``` # LiSt ディレクトリ一覧を表示 ls ``` ``` # Change Directory ディレクトリを変更 cd + ディレクトリ名 # 一つ戻る場合は cd ../ ``` ``` # Print Working Directory 現ディレクトリを表示 pwd ``` ``` # ターミナルの画面をリセット clear ``` ``` # 実行中のコマンドを強制終了 Ctl + C ``` --- ## ログイン認証 この章ではログイン認証を実装して、Laravelの凄さを体験してみましょう! 1. マイグレーションを実行 ``` php artisan migrate ``` 2. laravel/ui パッケージをインストール ``` composer require laravel/ui:^1.0 --dev ``` ※Laravel UIは認証周りの機能の雛型を生成してくれるLaravel公式のライブラリ 3. artisan コマンドを実行 ``` php artisan ui vue --auth ``` 4. npmパッケージをインストール ``` npm install ``` 5. パッケージをビルド ``` npm run dev ``` --- ## MVCモデル この章では、Webフレームワークの設計モデル(アーキテクチャ)の一つであるMVCモデルを学びましょう Model,View,Controllerそれぞれの役割を理解することで、Laravelでのアプリ開発がよりスムーズになります :::info 【解説 / MVC】 MVCとは,役割分担の概念! これまでは適当な PHP ファイルに処理を全部書いていた! ファイル数が増える... あの処理,どのファイルに書いたっけ..?? バグあったけど次の処理が他の人の書いたファイルに...(チーム開発) => いずれ詰む未来が見える... => せや,処理毎に別々のところに書いて管理や分類をしやすくしたろ!MVC の 3 つくらいでええやろ! 引用元:taroosg先生 ::: | 役割 | 解説 | | -------- | -------- | | Model | データ処理全般を担当。データーベースアクセスに関する処理全般を行う| | View | 画面表示を担当。表示に使うテンプレート(blade)などがこれに相当 | | Controller| 全体の制御を担当。司令官。場合によってModelやViewに指示を出す| | Routing | 特定のアドレスにアクセスしたときに、どの処理を呼び出して実行するのか担当。URLとControllerのどの処理を行うのか紐付ける| 例として,DB から取り出したデータを一覧画面に表示する流れを考えてみる. リクエストからの処理の流れ リクエスト -> Route -> Controller の順で処理が実行される. ![](https://i.imgur.com/4XmQdQn.png) ©︎taroosg DB から取り出したデータの流れ Model -> Controller -> View の順で処理が実行される. ![](https://i.imgur.com/tIWOZwn.png) ©︎taroosg --- ## ブックマークアプリの実装 この章ではいよいよ本格的にブックマークアプリのCRUD処理を開発します どういう役割のコードを書いているのか、感覚をつかみながら開発しましょう :::success ① DBのテーブルを作成 (マイグレーションファイルの作成と実行) ② Modelを作成(テーブルを簡単に扱えるようにする機能) ③ Viewを作成(app.blade.php & books.blade.php) ④ ルート定義(ルーティング)を作成 ⑤ CRUD機能実装(登録) ⑥ CRUD機能実装(表示) ⑦ CRUD機能実装(削除) ⑧ CRUD機能実装(更新) ::: ## ① DBのテーブルを作成 (マイグレーションファイルの作成と実行) ここでは、本を登録するためのBDテーブルを作成します LaravelではMigrationというテーブル作成に便利な機能が備わっています ``` 【解説 / マイグレーション】 マイグレーションとは「マイグレーションファイル」を用いてテーブルを管理する仕組み 「マイグレーションファイル」にテーブル名やカラム名を記述し,指定されたコマンドを実行することで設定したテーブルが生成される ``` 1. booksテーブルの設計書(マイグレーションファイル)を作成 ``` php artisan make:migration create_books_table --create=books ``` ※成功すると、database/migrationsの直下にbooks_table.phpが作成されます 2. database/migrationsの直下のbooks_table.phpに以下追記 ```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->date('published'); //追加 $table->timestamps(); }); } ``` 3. マイグレーション(テーブル作成)を実行 ターミナル上でコマンド実行 ``` php artisan migrate ``` 4. booksテーブルが作成されているか確認 実行したら、phpMyAdminでbooksテーブルとカラムが作成されているか確認しましょう ![](https://i.imgur.com/ch1Slxh.png) ## ② Modelを作成(テーブルを簡単に扱えるようにする機能) Modelはデータベースをうまく処理してくれる役割を担います。 ①で作った`booksテーブル`に対応する`Bookモデル`をここでは作成しましょう。 ![](https://i.imgur.com/dxSRof8.png) ©︎山崎学校長 1. ターミナルでコマンドを実行 ``` php artisan make:model Book ``` 2. /app/Book.php に作成されたことを確認 :::info 【解説 / Eloquent Model】 Eloquent Model は Laravel 標準の ORM(object-relational mapper)である. ORM とは,DB のレコードをオブジェクトとして直感的に扱えるようにしたもので,SQL を意識せずにプログラムで処理を記述することができる. Eloquent Model は定義された「Model」を用いることで簡単に DB へのデータ保存・取得などを行える. 1 つのモデルが 1 つのテーブルに対応する.例えば,booksテーブルに対してBookのようにモデルを定義すると自動的に対応する.モデル内に明示的に対応を記述することもできる. テーブルに対してデータ操作を行う場合,対応するモデルに対して処理を実行することで DB 操作を行うことができる. 引用元:taroosg先生 ::: :::info 【+α】 ①のMigrationファイルと②のModelは同時に作成することができる -m のオプションを末尾につける 例)php artisan make:model Book -m 他にもControllerを同時に作れたりと、色々なオプションが用意されているので、慣れてきたら利用しましょう ::: > 参考:https://qiita.com/niisan-tokyo/items/9c799989cb535489f201 ## ③ Viewを作成(登録&表示のためのページ) ここでは実際に表示画面を作成していきましょう ![](https://i.imgur.com/kVDn3qc.png) ©︎山崎学校長 1. /resources/views/layouts/app.blade.php を作成 app.blade.phpを未作成の場合、以下コードを貼り付けます。 :::danger *※今回はログイン認証をlaravel/uiを利用して作成した際にapp.blade.phpを自動で作成済みなので、このステップは行いません* ::: ```htmlmixed <!DOCTYPE html> <html lang="ja"> <head> <title>Book List</title> <!-- CSS と JavaScript --> </head> <body> <div class="container"> <nav class="navbar navbar-default"> <!-- ナビバーの内容 --> </nav> </div> @yield('content') </body> </html> ``` 2. /resources/views/books.blade.php を作成 以下コードを貼り付けます ```htmlmixed @extends('layouts.app') @section('content') <!-- Bootstrapの定形コード… --> <div class="card-body"> <div class="card-title"> ブックマーク </div> <!-- ↓バリデーションエラーの表示に使用--> <!-- ↑バリデーションエラーの表示に使用--> <!-- 本登録フォーム --> <form action="{{ url('books') }}" method="POST" class="form-horizontal"> @csrf <!-- 本のタイトル --> <div class="form-group col-md-6"> <label for="item_name" class="col-sm-3 control-label">タイトル</label> <input type="text" name="item_name" class="form-control" id="item_name"> </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> <!-- Book: 既に登録されてる本のリスト --> @endsection ``` :::danger 【重要 / form actionは@csrfと一緒に使う】 クロス・サイト・リクエスト・フォージェリは悪意のあるエクスプロイトの一種 `@csrf`はその攻撃から守ってくれる ※ `{{ csrf_field()}}`も同じ意味 ::: :::info 【コード解説 / @yieldと@sectionの部分は何している?】 親のapp.blade.php `@yield('content')`のところに、 子のbooks.blade.php `@secion('conten')` ~ `@endsection`までの部分を挿入している ::: ## ④ ルーティング これまでにDB+Model(データの操作を担当)、View(表示を担当)を作成しました ここでは、Webアプリの玄関口(受付)となるRoutingを作成していきましょう ![](https://i.imgur.com/v58AZRA.png) ©︎山崎学校長 :::info 【解説 / ルーティング】 アクセスしたアドレスを元に処理を割り振るための機能 ::: 1. /routes/web.phpに以下の記述を追加 先頭部 ```php use App\Book; use Illuminate\Http\Request; ``` 中間 ```php // 本のダッシュボード表示(books.blade.php) Route::get('/', function () { return view('books'); //** ここを修正 ** }); // ** ここから追加 ** // 新「本」を追加 Route::post('/books', function (Request $request) { // }); // 本を削除 Route::delete('/book/{book}', function (Book $book) { // }); ``` 2. プレビュー画面で確認 無事に本のタイトルを入力するフォームが表示されていればOK ![](https://i.imgur.com/22UFzC5.png) ## ⑤ CRUD機能実装(登録) 1. /routes/web.phpを編集 ```php // 新「本」を追加 Route::post('/books', function (Request $request) { $books = new Book; $books->item_name = $request->item_name; $books->item_number = '1'; // 今は固定値で登録 $books->item_amount = '1000'; //今は固定値で登録 $books->published = '2017-03-07 00:00:00'; //今は固定値で登録 $books->save(); return redirect('/'); }); ``` 2. formを送信した後にDBに登録処理ができているか、phpMyAdminで確認 ![](https://i.imgur.com/pDEYukg.png) ## ⑥ CRUD機能実装(表示) ここでは、登録したデータの一覧を取得し表示する機能を実装していきましょう 1. /routes/web.phpを編集 ```php Route::get('/', function () { $books = Book::orderBy('created_at', 'asc')->get(); return view('books', [ 'books' => $books ]); //return view('books',compact('books')); //も同じ意味 }); ``` 2. /resources/views/books.blade.php < !-- Book: 既に登録されてる本のリスト -->の下に追加 ```htmlmixed <!-- 現在の本 --> @if (count($books) > 0) <div class="card-body"> <table class="table table-striped task-table"> <!-- テーブルヘッダ --> <thead> <th>本一覧</th> <th>&nbsp;</th> </thead> <!-- テーブル本体 --> <tbody> @foreach ($books as $book) <tr> <!-- 本タイトル --> <td class="table-text"> <div>{{ $book->item_name }}</div> </td> <!-- 本: 削除ボタン --> <td> </td> </tr> @endforeach </tbody> </table> </div> @endif ``` 3. プレビュー画面で、一覧表示できているか確認 ![](https://i.imgur.com/s23MHGV.png) :::info 【解説 / @foreach】 Bladeテンプレートエンジンに備わっている便利な繰り返し処理をしてくれる機能 PHPの `foreach` と同じ感じで書ける ::: :::info 【+α / `$books`に値が入っているかのデバッグ】 viewで`$books`に値が入っているか確かめたい時は `{{ddd($books)}}` を仕込んでみよう ※Controllerで `ddd($books);` をするのもGOOD ::: :::success Laravel01_授業はここまでです。おつかれ様でした! 【Special Thanks】 :clap: 山崎学校長 :clap: taroosg先生 :clap: 中野先生 ::: --- ※Laravel02授業はCRUDの続きから行います ## ⑦ CRUD機能実装(削除) 1. books.blade.phpに削除ボタンを追加 < !-- 本: 削除ボタン -->下の<td></td>要素内に追加 ```htmlmixed <form action="{{ url('book/'.$book->id) }}" method="POST"> @csrf @method('delete') <button type="submit" class="btn btn-danger"> 削除 </button> </form> ``` :::info 【解説】 削除ボタンクリック時には,コントローラのdestroy()関数にリクエストが送られる. 削除の処理を行うにはDELETEメソッドでリクエストを送る必要があるが,form からは GET または POST でしか送れない. `@method('delete')`を記述することで,DELETEメソッドで送信できる. ※`{{ method_field('delete') }}` も同じ意味 ::: 2. web.phpに「本を削除」のルート定義を追加編集 ```php Route::delete('/book/{book}', function (Book $book) { $book->delete(); //追加 return redirect('/'); //追加 }); ``` ## ⑧ CRUD機能実装(更新) 1. books.blade.phpに更新ボタンを追加 削除ボタンの<td></td>タグの下 ```htmlmixed <!-- 本: 更新ボタン --> <td> <a href="{{ url('booksedit/'.$book->id) }}"> <button type="submit" class="btn btn-primary">更新</button> </a> </td> ``` 2. booksedit.blade.phpをview配下に新規作成し、以下コードを貼り付け ```htmlmixed @extends('layouts.app') @section('content') <div class="row container"> <div class="col-md-12"> <!-- ↓バリデーションエラーの表示に使用--> <!-- ↑バリデーションエラーの表示に使用--> <form action="{{ url('books/update') }}" method="POST"> <!-- item_name --> <div class="form-group"> <label for="item_name">本のタイトル</label> <input type="text" name="item_name" class="form-control" id="item_name" value="{{$book->item_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="{{$book->id}}" /> <!--/ id 値を送信 --> <!-- CSRF --> @csrf <!--/ CSRF --> </form> </div> </div> @endsection ``` 3. [routing] web.phpに更新画面表示と更新処理を追加 ```php //「本」の更新画面表示 Route::get('/booksedit/{book}',function(Book $book){ return view('booksedit', ['book' => $book]); }); //「本」の更新処理 Route::post('books/update',function(Request $request){ // Eloquent モデル $books = Book::find($request->id); $books->item_name = $request->item_name; $books->item_number = '1'; // 固定値 $books->item_amount = '1000'; // 固定値 $books->published = '2017-03-07 00:00:00'; // 固定値 $books->save(); return redirect('/'); }); ```