laravel で画像を DB にアップロードしてみました。
laravel に画像のパスを保存するようのテーブルを作成する
まずマイグレーションファイルを作成します。マイグレーションファイルとは、テーブル定義に対する変更内容が書かれるファイルです。基本laravelでは、phpで書かれています。
$ php artisan make:migration create_image_table
Laravel におけるマイグレーションは以下のように実現されます。
1.一意な名前のマイグレーションファイル(テーブル定義に対する変更内容)を作成する。マイグレーションファイルは up と down という2つのメソッドを持つ PHP クラスとして記述される。
2.「どのような SQL をどの順番で実行したか」は migrations テーブルで管理される。migrations テーブルには実行済みのマイグレーションファイル名が格納されている。
3.マイグレーションコマンドを実行すると、まず migrations テーブルの検索結果とマイグレーションファイルが入っているディレクトリを比べて、実行されていないファイルが検索される。
4.実行されていないファイルがあった場合は、順番に up メソッドが実行される。
image file の中身は、以下の内容にします。
<?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 メソッドはロールバック(マイグレーションを元に戻す機能)の時に実行されます。
そして次に、テーブル更新します。ちなみに一度imageファイルを作ってから、imageファイルを編集した際は、以下のコマンドで更新されます。
% php artisan migrate
すると以下のようにテーブルが変更されます。
ちなみにcreated_at と updated_at は、timestamps() のにより作成しました。
/**
* 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攻撃は利用者のブラウザから罠サイトを閲覧しただけで、勝手にこのような重要な処理を実行させる攻撃です。以下がその流れです。
①利用者が攻撃対象のサービスにログインする
利用者がサービスにログイン状態でないとCSRF攻撃はできません。
②攻撃者が罠を用意する
攻撃者は罠のサイトやリンクを用意します。そこには攻撃用のスクリプトが仕込んであり、利用者のログイン情報(セッションIDなど)が入ればリクエストが送信できる状態になっています。
③利用者が罠サイトを閲覧する
利用者が罠サイトを閲覧したり罠URLをクリックすることで、攻撃用スクリプトにセッションIDなどが入ります。
④攻撃対象サーバーにリクエスト送信され,リクエストが実行される
セッションIDのクッキーなどがついた状態で攻撃対象サーバーにリクエストが送信されます。CSRF対策をしていないサーバーではどこのページからリクエストが送信されたかなどを区別していないので、リクエストは受け入れられます。
その後攻撃用スクリプトに仕込まれていたリクエスト通り、勝手にスパムのコメントを送信されていたり、パスワードが変更されていたり、知らない間に物が購入されていたりします。
そして、CSRF対策をしたフォームを作成していきます。場所はresources/viewsにedit.blade.phpを作成します。内容は、以下の通りです。(bladeは下記では省略しています。)
@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 に書き込みます。
Route::get('/users/edit', 'UserController@edit2');
Route::post('/users/edit', 'UserController@update');
最後にControllerの定義
<?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", "アップロードに成功しました。");
}
}
こうなると完成です!ちなみにpublic/storage/avatar に、保存した画像はあります。