laravel８に画像をアップロードするやり方➀

laravel で画像を DB にアップロードしてみました。

#laravel に画像のパスを保存するようのテーブルを作成する

まずマイグレーションファイルを作成します。マイグレーションファイルとは、<font color="LimeGreen">テーブル定義に対する変更内容が書かれるファイルです。</font>基本laravelでは、phpで書かれています。

```
$ php artisan make:migration create_image_table
```

Laravel におけるマイグレーションは以下のように実現されます。

>1.一意な名前のマイグレーションファイル（テーブル定義に対する変更内容）を作成する。マイグレーションファイルは up と down という2つのメソッドを持つ PHP クラスとして記述される。<br>
2.「どのような SQL をどの順番で実行したか」は migrations テーブルで管理される。migrations テーブルには実行済みのマイグレーションファイル名が格納されている。<br>
3.マイグレーションコマンドを実行すると、まず migrations テーブルの検索結果とマイグレーションファイルが入っているディレクトリを比べて、実行されていないファイルが検索される。<br>
4.実行されていないファイルがあった場合は、順番に up メソッドが実行される。

image file の中身は、以下の内容にします。

```php:create_images_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateImagesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('images', function (Blueprint $table) {
            $table->increments('id');
            $table->unsignedInteger('user_id');
            $table->text('image_name');
            $table->text('image_path');
            $table->foreign('user_id')->references('id')->on('users');
            $table->timestamps();
            $table->softDeletes();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('images');
    }
}

}

```
ちなみに初期に作られるDBのidとimageテーブルのuser_idは紐付けています。Schema::create() でテーブルを作成します。第一引数がテーブル名、第二引数の無名関数がカラム定義です。以下が公式でのカラムタイプの種類です。 down メソッドはロールバック（マイグレーションを元に戻す機能）の時に実行されます。
![スクリーンショット 2021-05-13 18.22.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299864/2ffd3354-17de-cb86-4bd7-c487fc845482.png)
そして次に、テーブル更新します。ちなみに一度imageファイルを作ってから、imageファイルを編集した際は、以下のコマンドで更新されます。

```
% php artisan migrate
```
すると以下のようにテーブルが変更されます。
![053371F2-056F-447F-8CD4-518B4D8E1FD1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299864/f8aa831f-065d-29d2-ba70-3599daa81c8f.jpeg)
ちなみにcreated_at と updated_at は、timestamps() のにより作成しました。

```vendor/laravel/framework/src/Illuminate/Database/Schema/Blueprint.php
    
/**
     * Add nullable creation and update timestamps to the table.
     *
     * @param  int  $precision
     * @return void
     */
    public function timestamps($precision = 0)
    {
        $this->timestamp('created_at', $precision)->nullable();

        $this->timestamp('updated_at', $precision)->nullable();
    }
```
#画像をアップロードするフォームを作成する
フォーム画面などを作成する際、CSRF対策をすることが必須になります。
###そもそもCSRF（クロスサイト・リクエストフォージェリ)とは
Webアプリケーションにはログインした利用者のアカウントにより、取り消せない重要な処理(利用者のクレジットカードでの決済や、利用者の口座からの送金、メール送信、パスワードやメールアドレスの変更など)が実行できるものなどがあります。『安全なWebアプリケーションの作り方（第2版）』によると、CSRF攻撃は利用者のブラウザから罠サイトを閲覧しただけで、勝手にこのような重要な処理を実行させる攻撃です。以下がその流れです。

![名称未設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299864/3f8cc90f-b1a9-e25a-d82c-e3101bbb31ab.png)
>①利用者が攻撃対象のサービスにログインする
利用者がサービスにログイン状態でないとCSRF攻撃はできません。
②攻撃者が罠を用意する
攻撃者は罠のサイトやリンクを用意します。そこには攻撃用のスクリプトが仕込んであり、利用者のログイン情報(セッションIDなど)が入ればリクエストが送信できる状態になっています。
③利用者が罠サイトを閲覧する
利用者が罠サイトを閲覧したり罠URLをクリックすることで、攻撃用スクリプトにセッションIDなどが入ります。
④攻撃対象サーバーにリクエスト送信され,リクエストが実行される
セッションIDのクッキーなどがついた状態で攻撃対象サーバーにリクエストが送信されます。CSRF対策をしていないサーバーではどこのページからリクエストが送信されたかなどを区別していないので、リクエストは受け入れられます。
その後攻撃用スクリプトに仕込まれていたリクエスト通り、勝手にスパムのコメントを送信されていたり、パスワードが変更されていたり、知らない間に物が購入されていたりします。

そして、CSRF対策をしたフォームを作成していきます。場所はresources/viewsにedit.blade.phpを作成します。内容は、以下の通りです。(bladeは下記では省略しています。)

```edit.php
@if (Session::has('message'))
    <p>{{ session('message') }}</p>
@endif

<form action="/users/edit" method="post" enctype='multipart/form-data'> 
        {{ csrf_field() }}
        <div>
            <input type="hidden" name="id" value="">
        </div>
        <div>
            <input type="file" name="image">
        </div>
        <input type="submit" value="画像を送信する">
</form>
```
#Routeを書き込む
web.php に書き込みます。

```web.php
Route::get('/users/edit', 'UserController@edit2');
Route::post('/users/edit', 'UserController@update');
```
#最後にControllerの定義
```UserController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    
    public function edit2(Request $request)
    {
        return view('edit');
    }
    
    public function update(Request $request)
    {
        $path = $request->file('image')->store('public/avatar');
        $image_path = basename($path);

        return redirect("/users/edit")->with("message", "アップロードに成功しました。");
    }
}
```
上手くいくと以下のような形になると思います。
![3B94F0AE-FAB9-4E0B-9189-71D38FD4C084_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299864/e6f84221-9cd1-f8d2-ca3b-22d23ecbd8ac.jpeg)

![59B56F73-FE57-45A8-BF38-5A16D4119836_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299864/a53b9ff8-a8e1-dc44-7525-17d02c31ce8e.jpeg)
こうなると完成です！ちなみにpublic/storage/avatar に、保存した画像はあります。
#今回のまとめ
![Untitled Diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299864/fce53e86-779a-8874-eb53-1efcae0ea017.png)
次回の記事は、今回作成したdatabaseに画像のパスを入れていきます。お楽しみに！w