laravel学んで2か月で自サービスを開発した話 Part11

皆さんこんにちは！techfeedのPHP項目の日間で、自分の記事が１位になっていたのにビビりまくってます。
長かったけれど今回が最終回と思います！

<a href="https://qiita.com/k-hayack884/items/e571138e8bf7f35f7502">胡蝶蘭を捨てるくらいならワイが欲しいので、サービス開発する編</a>
<a href="https://qiita.com/k-hayack884/items/720c7a6300139317deac">公式ドキュメントの言う通り、パッケージをインストールされたら、Inertia.jsが導入されて？？？になった編</a>
<a href="https://qiita.com/k-hayack884/items/dccb9d479bd162144559">マルチログインを作ってみた編</a>
<a href="https://qiita.com/k-hayack884/items/0354c0ddecee58272e46">デザインをtailwindcssに丸投げする編</a>
<a href="https://qiita.com/k-hayack884/items/e4c691041373a97afd97">デザイナーに怒られないために、画像をリサイズする編</a>
<a href="https://qiita.com/k-hayack884/items/ab8ddbb97b035c55fd1b">AWS×リボ払いで破産へGO編</a>
<a href="https://qiita.com/k-hayack884/items/cefae022df84a57df53f">Google MAPに無人島に飛ばされる編</a>
<a href="https://qiita.com/k-hayack884/items/ea97f393140c764e41d8">エンジニアはやせ型が好き編</a>
<a href="https://qiita.com/k-hayack884/items/2c5eeee93b8bfd7db7be">APIがよくわからなかった編</a>
<a href="https://qiita.com/k-hayack884/items/2c5eeee93b8bfd7db7be">自分のサイトのメールが迷惑メール扱いされてショックを受ける編</a>

# 今回やること
ユーザー機能は最低限そろえられたので、管理者機能を追加していきます
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f323238313934362f39303764326565662d393833362d636261632d376261662d6331383630366465636165642e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2281946/6a8c7876-94cf-46fc-6e56-0a1446c4fc41.png)

- 違反商品報告機能（ユーザー側）
- 違反商品管理機能（管理者側）

みなさん、ECサイトには様々な店が商品を登録していますが、なんでも登録していいわけではありませんね。
私の開発しているサイトは**花**を取り扱っていますが、悪ふざけで
![FireShot Capture 012 - flower-gift - flower-gift.herokuapp.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2281946/ffedee60-8520-0b81-dc30-034bad1cb163.png)
### ブリを出品してみました
当然ながら花を取り扱うサイトに魚を出品するのは言語道断なので違反報告をしていきたいと思います。

## ユーザー側で必要なもの
当然、理由なく違反報告するのは良くありませんし、誤送信の可能性もありますので、フォームを作っていきます。
badsフォルダにproduct.blade.phpを作成して
```product.blade.php
<x-app-layout>
    <section class="text-gray-600 body-font relative">
        <div class="container px-5 py-24 mx-auto">
            <div class="flex flex-col text-center w-full mb-12">
                <h1 class="sm:text-3xl text-2xl font-medium title-font mb-4 text-gray-900">違反商品報告</h1>
            </div>
            <div class="lg:w-1/2 md:w-2/3 mx-auto">
                <x-auth-validation-errors class="mb-4" :errors="$errors" />
                <div class="flex">
                    <div class="w-1/3">
                        <x-product-image :filename="$badProduct->user->img" />
                        <p>商品名:{{ $badProduct->name }}</p>
                        <p> 出品者:{{ $badProduct->user->name }}</p>
                    </div>
                    <div class="w-2/3">{{ $badProduct->comment }}
                        <p class="text-right">出品日時:{{ $badProduct->created_at->toDateString() }}</p>
                    </div>
                </div>
            </div>
            <form action="{{ route('user.bads.product.send', ['product' => $badProduct->id]) }}" method="post">
                @csrf
                <div class="lg:w-1/2 md:w-2/3 mx-auto">
                    <div class="flex flex-wrap -m-2">
                        <input type="hidden" name="product_id" value="{{ auth()->user()->id }}">
                        <div class="p-2 w-full">
                            <div class="relative">
                                <label for="reason" class="leading-7 text-sm text-gray-600">違反理由をお書きください</label>
                                <textarea id="reason" name="reason"
                                    class="w-full bg-gray-100 bg-opacity-50 rounded border border-gray-300 focus:border-indigo-500 focus:bg-white focus:ring-2 focus:ring-indigo-200 h-32 text-base outline-none text-gray-700 py-1 px-3 resize-none leading-6 transition-colors duration-200 ease-in-out"></textarea>
                            </div>
                        </div>
                        <div class="p-2 w-full">
                            <button
                                class="flex mx-auto text-white bg-indigo-500 border-0 py-2 px-8 focus:outline-none hover:bg-indigo-600 rounded text-lg">送信する</button>
                        </div>
                    </div>
                </div>
            </form>
        </div>
    </section>
</x-app-layout>
```
このフォームが送信されると、badcontroller.phpが作動し、違反商品テーブルに商品のidと報告者のidが登録されます
```badcontroller.php
 public function productSend(Request $request, $id)
    {
        $request->validate([
            'reason' => ['string', 'max:100'],
        ]);

        BadProduct::create([
            'user_id' => Auth::id(),
            'product_id' => $id,
            'reason' => $request->reason,
        ]);
        return redirect()
            ->route('user.dashboard')
            ->with([
                'message' => '違反商品を報告しました',
                'status' => 'bad'
            ]);
    }
```

これでユーザー側の処理は以上です
# 管理者側の処理
早速管理者画面ログインして、違反商品管理を開きます
![FireShot Capture 013 - flower-gift - flower-gift.herokuapp.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2281946/016d2e77-ac7c-20bc-795e-0c78f3dee718.png)
**なぜか、報告者の部分が出品者になっているので投稿後なおします(´・ω・｀)**
### ブリは冷蔵でも腐りやすいため、しっかりと凍結します。
![FireShot Capture 015 - flower-gift - flower-gift.herokuapp.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2281946/bd2daca6-8b9c-5d17-789e-a9e5d31f05e7.png)

複数のテーブルを動かすためしっかりとトランザクションを使っていきましょう。
```BadController.php
 public function badProductDelete(Request $request, $id)
    {
        try {
            DB::transaction(function () use ($request, $id) {
                $badproduct = BadProduct::findOrFail($id);
                $product = Product::findOrFail($badproduct->product_id);
                $product->status = 0;
                $product->save();
                BadProduct::select('id')
                    ->where('id', $id)->delete();

                ProcessedProduct::create([
                    'admin_id' => Auth::id(),
                    'result' => false,
                    'product_id' => $request->product_id

                ]);
            }, 2); //試行する回数
        } catch (Throwable $e) {
            Log::error($e);
            throw $e;
        }
        return redirect()->route('admin.bads.product-index')
            ->with([
                'message' => '違反商品をを凍結しました',
                'status' => 'delete'
            ]);
    }
```
## 再びユーザー側でログイン
![FireShot Capture 017 - flower-gift - flower-gift.herokuapp.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2281946/b5cccdc9-b95f-ed34-8de4-0a5aa9581062.png)
ちゃんと、ブリが凍結して非公開になりました。
![FireShot Capture 016 - フラワーギフト - flower-gift.herokuapp.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2281946/ccd74370-f627-a880-480c-4bc79a23a5d2.png)
非公開商品は、詳細画面のリンクが消え、直接URLでアクセスしても、自動的にリダイレクトされるようになります。

凍結処理をした商品には、商品、削除した管理者のId、処理内容を登録しており、
どの管理者がどの処理をしたのか一目でわかるようになっております！
![FireShot Capture 018 - 4915cddba6f64106825ded0b56bbc2c3.vfs.cloud9.ap-northeast-1.amazonaws._ - 4915cddba6f64106825ded0b56bbc2c3.vfs.cloud9.ap-northeast-1.amazonaws.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2281946/fe7696eb-d873-684a-08f2-f40be1c78120.png)

# 終わりに
大まかな機能は完成させました。
追加機能などはありますけれど、完成物を次の記事で紹介したいと思います。