TM4423 / Laravel_training

0 stars 0 forks source link

Laravel Training #1

Open TM4423 opened 2 years ago

TM4423 commented 2 years ago
sudo yum update -y
sudo yum -y remove php-*
sudo yum update -y amazon-linux-extras
amazon-linux-extras
sudo amazon-linux-extras disable lamp-mariadb10.2-php7.2
sudo amazon-linux-extras enable php8.0
sudo yum clean metadata && sudo yum install php-{pear,cgi,pdo,common,curl,mbstring,gd,mysqlnd,gettext,bcmath,json,xml,fpm,intl,zip,cli,devel}

sudo pecl uninstall xdebug & sudo pecl install xdebug
sudo systemctl restart httpd.service
sudo systemctl restart php-fpm.service

TM4423 commented 2 years ago

DBの準備(MariaDB)

sudo yum list installed | grep mariadb
sudo amazon-linux-extras install mariadb10.5 -y
sudo systemctl start mariadb
sudo mysql_secure_installation
sudo systemctl enable mariadb
sudo systemctl is-enabled mariadb
TM4423 commented 2 years ago

composerのインストール

curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/bin/composer
composer

※ composerが最新版でない場合は下記を実行(今回は不要)

sudo composer update
TM4423 commented 2 years ago

Laravelプロジェクトの作成

composer create-project laravel/laravel cms
cd cms
php artisan serve --port=8080

エラーが出た場合

sudo yum install php-cli php-common php-devel php-fpm php-gd php-mysqlnd php-mbstring php-pdo php-xml
sudo composer update
php artisan key:generate
TM4423 commented 2 years ago

phpMyAdminのインストール

新しいターミナル「New Terminal」を開く

cd cms/public
wget https://files.phpmyadmin.net/phpMyAdmin/5.1.2/phpMyAdmin-5.1.2-all-languages.zip
unzip phpMyAdmin-5.1.2-all-languages.zip
cd ..

phpMyAdminのフォルダ名を変更(長いので)

phpMyAdminにアクセス

/phpMyAdmin/index.php

ターミナルでDB作成する場合

mysql -u root -p
root [Enterキー]
create database c9;
show databases;
exit;

phpMyAdminで作成する場合

phpMyAdminの管理画面で c9 というDBを作成
※照合順はutf8mb4_general_ciを選択
(授業では、utf8mb4_unicode_ciだった)
TM4423 commented 2 years ago

DBの作成&Laravelと接続

隠しファイルを表示

デプロイするときは、ここを書き換える!!!

.envファイルを編集

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=c9
DB_USERNAME=root
DB_PASSWORD=root

Webサーバーを再起動

^9
php artisan serve --port
TM4423 commented 2 years ago

Laravelの初期設定(HTTPS設定)

/app/Providers/AppServiceProvider.php ファイルを修正

// 冒頭6行目あたり
use Illuminate\Support\Facades\URL;     //この行を追加

// boot(){}内に追加
public function boot() {
   URL::forceScheme('https');           //この行を追加
}
TM4423 commented 2 years ago

ログイン認証(復習)

php artisan migrate
composer require laravel/ui
php artisan ui vue --auth
npm install

2回

npm run dev
npm run dev
TM4423 commented 2 years ago

CRUD実装(復習) 場所

app/Http/Controllers/

app/Models/

database/migrations/

resources/views/

routes/web.php

TM4423 commented 2 years ago

モデル & コントローラ & マイグレーションファイルを作成

php artisan make:model Book -r -m

コントローラー Http/Controllers/BookController.php モデル app/Models/Book.php マイグレーション database/migrations/

TM4423 commented 2 years ago

マイグレーションファイルを編集 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->date('published');
        $table->timestamps();
    });
}

これで、bookテーブルの設計図ができた。

マイグレーションを実行(テーブル作成)

php artisan migrate

booksテーブルが作成されているか確認(重要) phpMyAdmin

TM4423 commented 2 years ago

ビューを作成

/resources/views/

books.blade.php

@extends('layouts.app')
@section('content')
    <!-- Bootstrapの定形コード… -->
    <div class="card-body">
        <div class="card-title">
            ブックマーク
        </div>

        <!-- ↓バリデーションエラーの表示に使用-->
        @include('common.errors')
        <!-- ↑バリデーションエラーの表示に使用-->

        <!-- 本登録フォーム -->
        <form action="{{ url('books') }}" method="POST" class="form-horizontal">
            @csrf
            <!-- 本のタイトル -->
            <div class="form-group col-md-6 p-2">
                <label for="item_name" class="col-sm-3 control-label">タイトル</label>
                <input type="text" name="item_name" class="form-control" id="item_name" value="{{ old('item_name') }}">
            </div>
            <!-- 冊数 -->
            <div class="form-group col-md-6 p-2">
                <label for="item_number" class="col-sm-3 control-label">冊数</label>
                <input type="text" name="item_number" class="form-control" id="item_number" value="{{ old('item_number') }}">
            </div>
            <!-- 金額 -->
            <div class="form-group col-md-6 p-2">
                <label for="item_amount" class="col-sm-3 control-label">金額</label>
                <input type="text" name="item_amount" class="form-control" id="item_amount" value="{{ old('item_amount') }}">
            </div>
            <!-- 公開日 -->
            <div class="form-group col-md-6 p-2">
                <label for="published" class="col-sm-3 control-label">公開日</label>
                <input type="date" name="published" class="form-control" id="published" value="{{ old('published') }}">
            </div>
            <!-- 本 登録ボタン -->
            <div class="form-group p-2">
                <div class="col-sm-offset-3 col-sm-6">
                    <button type="submit" class="btn btn-primary">
                        Save
                    </button>
                </div>
            </div>
        </form>
    </div>
    <!-- Book: 既に登録されてる本のリスト -->
    @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>
                                <form action="{{ url('book/'.$book->id) }}" method="POST">
                                    @csrf
                                    @method('delete')
                                    <button type="submit" class="btn btn-danger">
                                        削除
                                    </button>
                                </form>
                            </td>
                            <!-- 本: 更新ボタン -->
                            <td>
                                <a href="{{ url('booksedit/'.$book->id) }}">
                                    <button type="submit" class="btn btn-primary">更新</button>
                                </a>
                            </td>
                        </tr>
                    @endforeach
                </tbody>
            </table>
        </div>
    @endif
@endsection
TM4423 commented 2 years ago

booksedit.blade.php (更新画面)

@extends('layouts.app')
@section('content')
    <div class="row container">
        <div class="col-md-12">
            <!-- ↓バリデーションエラーの表示に使用-->
                        @include('common.errors')
            <!-- ↑バリデーションエラーの表示に使用-->
            <form action="{{ url('books/update') }}" method="POST">
                <!-- item_name -->
                <div class="form-group p-2">
                    <label for="item_name">タイトル</label>
                    <input type="text" name="item_name" class="form-control" id="item_name" value="{{$book->item_name}}">
                </div>
                <!--/ item_name -->

                <!-- item_number -->
                <div class="form-group p-2">
                    <label for="item_number">冊数</label>
                    <input type="text" name="item_number" class="form-control" id="item_number" value="{{$book->item_number}}">
                </div>
                <!--/ item_number -->

                <!-- item_amount -->
                <div class="form-group p-2">
                    <label for="item_amount">金額</label>
                    <input type="text" name="item_amount" class="form-control" id="item_amount" value="{{$book->item_amount}}">
                </div>
                <!--/ item_amount -->

                <!-- published -->
                <div class="form-group p-2">
                    <label for="published">公開日</label>
                    <input type="date" name="published" class="form-control" id="published" value="{{$book->published}}">
                </div>
                <!--/ published -->

                <!-- Save ボタン/Back ボタン -->
                <div class="form-group p-2">
                    <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>
                </div>
                <!--/ Save ボタン/Back ボタン -->

                <!-- id 値を送信 -->
                <input type="hidden" name="id" value="{{$book->id}}" />
                <!--/ id 値を送信 -->

                <!-- CSRF -->
                @csrf
                <!--/ CSRF -->
            </form>
        </div>
    </div>
@endsection
TM4423 commented 2 years ago

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
TM4423 commented 2 years ago

コントローラを編集

(🚨今回はコントローラ名をBooksControllerからBookControllerに変更しています)

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Book;
use Validator;

class BookController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $books = Book::orderBy('created_at', 'asc')->get();
        return view('books', ['books' => $books]);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    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);
        }

        // 登録処理
        $book = new Book;
        $book->item_name =    $request->item_name;
        $book->item_number =  $request->item_number;
        $book->item_amount =  $request->item_amount;
        $book->published =    $request->published;
        $book->save();
        return redirect('/');
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit(Book $book)
    {
        return view('booksedit', ['book' => $book]);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request)
    {
        // バリデーション
        $validator = Validator::make($request->all(), [
            'id' => 'required', // storeに対しての追加分
            '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);
        }

        $book = Book::find($request->id);
        $book->item_name =    $request->item_name;
        $book->item_number =  $request->item_number;
        $book->item_amount =  $request->item_amount;
        $book->published =    $request->published;
        $book->save(); 
        return redirect('/');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy(Book $book)
    {
        $book->delete();
        return redirect('/');
    }
}
TM4423 commented 2 years ago

ルート定義(web.php)

冒頭部分に追加

use App\Http\Controllers\BookController; 

ここは削除↓

Route::get('/', function () {
    return view('welcome');
});

以下も追加  (🚨 ’/' のルートは元のコードに存在します↑。そこだけ削除してから以下コピペ)

// 本のダッシュボード表示
Route::get('/', [BookController::class, 'index']);

// 新「本」を追加
Route::post('/books', [BookController::class, 'store']);

//「本」の更新画面表示
Route::get('/booksedit/{book}',[BookController::class, 'edit']);

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

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

動作確認

TM4423 commented 2 years ago

認証機能とルートの保護

ルートの保護

ルートグループ(Route::group)で認証後に実行するルート定義を囲う

web.php

Route::group(['middleware' => 'auth'], function () {
    //
    // この中に認証済み後のルート定義を入れる
    //
});

【回答例】

// 本のダッシュボード表示
Route::get('/', [BookController::class, 'index']);

Route::group(['middleware' => 'auth'], function(){
    // 新「本」を追加
    Route::post('/books', [BookController::class, 'store']);

    //「本」の更新画面表示
    Route::get('/booksedit/{book}',[BookController::class, 'edit']);

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

    // 本を削除
    Route::delete('/book/{book}', [BookController::class, 'destroy']);
});
TM4423 commented 2 years ago

動作確認

ユーザ登録して、本を登録してみる

【解説 / middlewareとは】

💡 ['middleware' => 'auth']ってなにしてる?

簡単に言えば、入国審査(や出国審査)のような、門番の役割

コントローラーの処理を実行する前(やした後)に何かをチェックしてくれる機能

例えば「ある特定のユーザーにしかできない機能(role)」「特定のIPアドレスからだけ許可」「スマホ専用ページへリダイレクト」など、リクエストを送ったユーザーの状況に応じて門番が振り分けてくれる役割などがある

https://readouble.com/laravel/9.x/ja/middleware.html

TM4423 commented 2 years ago

【解説 / Route::groupメソッド】

ルートグループは多くのルートで共通なもの(ミドルウェアや名前空間のようなルート属性)を一括して適用してくれる便利なルート定義の方法

例えば、管理者と利用者のサイトが分かれていて、ルート定義が多くなってきたときに

Route::prefix('admin')->group(function(){
  // admin用のルート定義がここに入る
}

と書くことで、https://xxxxx.com/admin/yyyyのように、admin/以下のルート定義をgroup内に書くことができるようになる

https://readouble.com/laravel/9.x/ja/routing.html#:~:text=return%20%24next(%24request)%3B%0A%7D-,%E3%83%AB%E3%83%BC%E3%83%88%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97,-%E3%83%AB%E3%83%BC%E3%83%88%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97%E3%82%92

TM4423 commented 2 years ago

Viewと認証

認証済みユーザ情報を使って、表示・登録などの処理をユーザごとに切り替えましょう

❓ 【お題(要件)】ダッシュボード(books.blade.php)

TM4423 commented 2 years ago

booksテーブルを編集

「ある一冊の本のデータ(1レコードと呼びます)を誰が登録したか」を判別するためには、「その本を登録したユーザのid」が必要になります。

ここではbooksテーブルに user_idのカラムを新たに追加しましょう。

マイグレーションを実行 (books_table)

マイグレーションファイルを編集し、user_idを追加する books_table

public function up()
{
    Schema::create('books', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->bigInteger('user_id');    //ここを追加
        $table->string('item_name');
        $table->integer('item_number');
        $table->integer('item_amount');
        $table->date('published');
        $table->timestamps();
    });
}
php artisan migrate:refresh

確認(重要!!)

booksテーブルが更新されているかphpMyAdminで確認

TM4423 commented 2 years ago

Controllerを編集(store)

登録処理(store)で、ログインユーザの user_id も保存するように変更

BookController.php

use Auth; // 冒頭付近に追加
// storeメソッドを編集
public function store(Request $request)
{
        // 前略
        $book = new Book;
        $book->user_id    =  Auth::id(); // ここを追加
        $book->item_name   = $request->item_name;
        // 後略

認証しているユーザの情報を入手するには、 Auth::user()だけで取得できてしまう Auth::id()で、ログインしているユーザのidを取得できる

TM4423 commented 2 years ago

Viewを編集

表示の出しわけをする

books.blade.php

登録フォーム

登録フォームを認証ありのときのみ表示 (L13~L46あたり) formタグを @if(Auth::check() ~ @enfifで囲う

<!-- 本登録フォーム -->
@if(Auth::check())
    <form action="{{ url('books') }}" method="POST" class="form-horizontal">
        <!-- 省略 -->
    </form>
@endif

削除・更新ボタン

削除・更新ボタンを登録したユーザのみ表示 formタグおよびaタグを @if($book->user_id === Auth::id()) ~ @endifで囲う

<!-- 本: 削除ボタン -->
<td>
    @if($book->user_id === Auth::id())
        <form action="{{ url('book/'.$book->id) }}" method="POST">
            @csrf
            @method('delete')
            <button type="submit" class="btn btn-danger">
                削除
            </button>
        </form>
    @endif
</td>

<!-- 本: 更新ボタン -->
<td>
    @if($book->user_id === Auth::id())
        <a href="{{ url('booksedit/'.$book->id) }}">
            <button type="submit" class="btn btn-primary">更新</button>
        </a>
    @endif
</td>

確認(重要!!)

TM4423 commented 2 years ago

Controllerを編集(edit / update)

BookController.php

public function edit(Book $book){
    if($book->user_id === Auth::id()){
        return view('booksedit', ['book' => $book]);
    } else {
        return "アクセス権がありません";
    }
}

public function update(Request $request)
{
    // 変更前
    $book = Book::find($request->id); // これを下のコードに変更
    // 変更後 
    $book = Book::where('user_id', Auth::id())->find($request->id);
TM4423 commented 2 years ago

👀 認証済みユーザの取得方法

BooksController.php

【+α / 認証済みか確認】

Auth::check() をすると、認証済みであればtrueが返ります https://readouble.com/laravel/9.x/ja/authentication.html#:~:text=request)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20//%20%24request%2D%3Euser()%0A%20%20%20%20%7D%0A%7D-,%E7%8F%BE%E5%9C%A8%E3%81%AE%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%8C%E8%AA%8D%E8%A8%BC%E6%B8%88%E3%81%BF%E3%81%8B%E5%88%A4%E5%AE%9A,-%E5%8F%97%E4%BF%A1HTTP%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88

【開発のポイント】

初めのうちは1つ1つのステップで細かく確認作業をすると、逆にスムーズに開発が進むようになることがわかるでしょう。Laravelではdd() という便利な確認ツールがあります。利用しない手はないですね! 使い方例: dd(Auth::id()) → ログインしているユーザのidが取得できます    ( ※この例の場合、use Auth; をファイルの冒頭付近に記載するのを忘れずに!)

TM4423 commented 2 years ago

証成功後のパスのカスタマイズ

app/Providers/RouteServicePrivicer.php

変更前

public const HOME = '/home';

変更後

public const HOME = '/';
TM4423 commented 2 years ago

リレーション(テーブルの関連付け)

TM4423 commented 2 years ago

User Modelの修正 (Book Modelと関連付け)

app\Models\User.php

// L45あたりに追加
public function books()
{
    return $this->hasMany(Book::class);
}

詰まりポイント(カッコの中に書くこと!!!)

TM4423 commented 2 years ago

Viewの修正(app.blade.php, home.blade.php)

resources\views\layouts\app.blade.php L60あたり

<div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
      <!-- ↓この1行を追加-->
      <a class="dropdown-item" href="{{ url('/home') }}">マイページ</a>
TM4423 commented 2 years ago

resources\views\home.blade.php L11あたり card-bodyの中身を削除し以下コードを追加

<div class="card-body">
    <!--↓ここから追加↓-->
    <div class="alert alert-primary">
        <div>マイページサンプル</div>
        <div>ログインユーザーの情報のみ表示</div>
    </div>
    <table class="table table-striped task-table">
        <!-- テーブルヘッダ -->
        <thead>
            <th>本一覧</th>
            <th>&nbsp;</th>
        </thead>
        <!-- テーブル本体 -->
        <tbody>
            @if(isset($books))
                @foreach ($books as $book)
                    <tr>
                        <!-- 本タイトル -->
                        <td class="table-text">
                            <div>{{ $book->item_name }}</div>
                        </td>
                        <td>
                            <form action="{{ url('book/'.$book->id.'/like') }}" method="POST">
                                @csrf
                                @method('delete')
                                <button type="submit" class="btn btn-danger">
                                    削除
                                </button>
                            </form>
                        </td>
                        <!-- 本: 更新ボタン -->
                        <td>
                            <a href="{{ url('booksedit/'.$book->id) }}">
                                <button type="submit" class="btn btn-primary">更新</button>
                            </a>
                        </td>
                    </tr>
                @endforeach
            @endif
        </tbody>
    </table>
    <!--↑ここまで↑-->
</div>
TM4423 commented 2 years ago

HomeControllerの修正

app\Http\Controllers\HomeController.php

冒頭付近に追加

use App\Models\User; // 追加
use Auth; // 追加

indexを修正

public function index()
{
    $books = User::find(Auth::id())->books;
    return view('home', ['books' => $books]);
}
TM4423 commented 2 years ago

ルート定義

routes\web.php

Route::group(['middleware' => 'auth'], function(){
    // 中略
    // ログインユーザの本を取得
    Route::get('/home', [App\Http\Controllers\HomeController::class, 'index']);
});

// 以下を削除
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');

詰まりポイント 

->name('home');を取り去って、保護の中へいれてしまうんだ。

TM4423 commented 2 years ago

表示できているか確認(重要)

TM4423 commented 2 years ago

「本」と「登録者の名前」を一覧表示(多対1)

TM4423 commented 2 years ago

Book Modelを修正(User Modelと関連付け)

BookモデルからUserモデルを呼び出してuserの情報を受け取れるようにします

app\Models\Book.php

public function user()
{
    return $this->belongsTo(User::class);
}
TM4423 commented 2 years ago

Viewの修正(books.blade.php)

resources\views\books.blade.php L66あたり

<!-- テーブル本体 -->
    <tbody>
        @foreach ($books as $book)
            <tr>
                <!-- 本タイトル -->
                <td class="table-text">
                    <div>{{ $book->item_name }}</div>
                </td>
                <!-- 登録者名 ↓ここを追加-->
                <td class="table-text">
                    <div>{{ $book->user->name }}</div>
                </td>
TM4423 commented 2 years ago

表示できているか確認(重要)

TM4423 commented 2 years ago

本のお気に入り機能(多対多)

TM4423 commented 2 years ago

中間テーブル作成(book_userテーブル)

マイグレーションファイル作成&編集

cms階層でコマンドを実行

php artisan make:migration create_book_user_table --create=book_user

database\migrations[日付]_create_book_user_table.phpの function upを編集

public function up()
{
    Schema::create('book_user', function (Blueprint $table) {
        $table->increments('id');
        $table->unsignedBigInteger('user_id');
        $table->unsignedBigInteger('book_id');
        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        $table->foreign('book_id')->references('id')->on('books')->onDelete('cascade');
        $table->unique(['user_id', 'book_id']);
    });
}
TM4423 commented 2 years ago

テーブル作成(Migrate実行)

php artisan migrate
TM4423 commented 2 years ago

テーブルが作成されたか確認(重要)

book_userテーブルができたか。

TM4423 commented 2 years ago

User Modelを修正

app\Models\User.php

public function favoriteBook()
{
    return $this->belongsToMany(Book::class);
}
TM4423 commented 2 years ago

Book Modelを修正

app\Models\Book.php

public function favoriteBook()
{
    return $this->belongsToMany(User::class);
}
TM4423 commented 2 years ago

BookControllerを修正

L139あたり(ファイル下部)に以下の関数を追加

// お気に入り(多対多)
public function likeBook(Book $book)
{
        $book->favoriteBook()->attach(Auth::id());
        return back();
}

public function unlikeBook(Book $book)
{
    $book->favoriteBook()->detach(Auth::id());
    return back();
}
TM4423 commented 2 years ago

ルート定義を修正

routes\web.php

Route::group(['middleware' => 'auth'], function(){
    // 中略
  // 以下追加
    // お気に入り機能
    Route::post('book/{book}/like', [BookController::class, 'likeBook']);
    Route::post('book/{book}/unlike', [BookController::class, 'unlikeBook']);
}
TM4423 commented 2 years ago

Viewを修正(books.blade.php)

books.blade.php L89あたり(更新ボタンの下)に以下を追加

<!-- Likeボタン -->
<td>
    @if($book->favoriteBook()->where('user_id',Auth::id())->exists() === false)
        <form action="{{ url('book/'.$book->id.'/like') }}" method="POST">
            {{ csrf_field() }}
            <button type="submit" class="btn btn-outline-warning">
                Like
            </button>
        </form>
    @endif
    @if($book->favoriteBook()->where('user_id',Auth::id())->exists() === true)
        <form action="{{ url('book/'.$book->id.'/unlike') }}" method="POST">
            {{ csrf_field() }}
            <button type="submit" class="btn btn-warning">
                Unlike
            </button>
        </form>
    @endif
</td>
TM4423 commented 2 years ago

テーブルが作成されたか確認(重要)

book_userテーブルの 3つのid が更新できたか。