簡単なフォトアルバムアプリを作成した際の画像アップロード機能に関する部分だけをまとめました。
フォームの作成
@extends("layouts.app")
@section("content")
<h3>Create Album</h3>
{!!Form::open(["action" => "AlbumsController@store" , "method" => "POST", "enctype" => "multipart/form-data"])!!}
{{ csrf_field() }}
{{Form::text("name","",["placeholder" => "Album Name"])}}
{{Form::textarea("description","",["placeholder" => "Album Description"])}}
{{Form::file("cover_image")}}
{{Form::submit("submit")}}
{!!Form::close()!!}
@endsection
Formファサードで作成。
"enctype" => "multipart/form-data"は二つ以上のファイルを同時にリクエストに格納するための方式。画像アップロードのフォームには必須。
cover_imageが画像の名前を保存するカラム。
画像の保存
画像データはデータベースにそのまま保存するのではなく、基本的に画像本体は静的ファイル、画像の名前はデータベースに保存するようだ。
public function store(Request $request)
{
//拡張子付きでファイル名を取得
$filenameWithExt = $request->file("cover_image")->getClientOriginalName();
//ファイル名のみを取得
$filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
//拡張子を取得
$extension = $request->file("cover_image")->getClientOriginalExtension();
//保存のファイル名を構築
$filenameToStore = $filename."_".time().".".$extension;
$path = $request->file("cover_image")->storeAs("public/album_covers", $filenameToStore);
$album = new Album;
$album->name = $request->input("name");
$album->description = $request->input("description");
$album->cover_image = $filenameToStore;
$album->save();
return redirect("/albums")->with("success", "Album Created");
}
名前の保存
そのままのファイル名で保存してもよいが、時間を入れることで同じ名前の画像を区別できる。
アップロードされたものからファイル名と拡張子を取得する。間にアップロードされた時間を挟み込み保存する新たに名前を構築。
画像本体の保存
$path = $request->file("cover_image")->storeAs("public/album_covers", $filenameToStore);
ブラウザからサーバ上のファイルにアクセスするためには、Laravelインストールディレクトリの下にあるpublicディレクトリの下に保存する必要がある。なのでpublicディレクトリに保存するが、実際に保存されるのは/storage/appという場所である。
publicの下ではなく、album_coversというフォルダが/storage/appの下に作られ、保存した画像はその中にある。
そこでpublicディレクトリと/storage/appの間にリンクを持たせる必要がある。
>php artisan storage:link
The [public/storage] directory has been linked.
php artisan storage:linkを実行することによってシンボリックリンクを張り、その間にリンクを持たせることができる。

publicの下にstorageというフォルダが作られ画像も保存されている。
これでブラウザ上から画像を見ることができる。
保存した画像を表示する
@extends("layouts.app")
@section("content")
@if(count($albums) > 0)
<?php
$colcount = count($albums);
$i = 1;
?>
<div id="albums">
<div class="row text-center">
@foreach($albums as $album)
@if($i == $colcount)
<div class="medium-4 columns end">
<a href="/albums/{{$album->id}}">
<img class="thumbnail" src="storage/album_covers/{{$album->cover_image}}" alt="{{$album->name}}">
</a>
<br>
<h4>{{$album->name}}</h4>
@else
<div class="medium-4 columns">
<a href="/albums/{{$album->id}}">
<img class="thumbnail" src="storage/album_covers/{{$album->cover_image}}" alt="{{$album->name}}">
</a>
<br>
<h4>{{$album->name}}</h4>
@endif
@if($i % 3 == 0)
</div>
</div>
<div class="row text-center">
@else
</div>
@endif
<?php $i++;?>
@endforeach
</div>
</div>
@else
<p>No Albums To Display</p>
@endif
@endsection
保存の時は画像をpublic/album_coversの下に保存したが、読み込む場合のパスはstorage/album_coversとなることに気を付けたい。
画像を削除する
public function destroy($id)
{
$photo = Photo::find($id);
if(Storage::delete("public/photos/".$photo->album_id."/".$photo->photo))
{
$photo->delete();
return redirect("/")->with("success","Photo Deleted");
}
}
画像の削除はDBテーブル上のデータだけでなく、アプリ内のストレージからも削除する。