LoginSignup
4
4

More than 3 years have passed since last update.

[Laravel]画像アップロード機能作ってみた

Posted at

簡単なフォトアルバムアプリを作成した際の画像アップロード機能に関する部分だけをまとめました。

フォームの作成

create.blade.php

@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が画像の名前を保存するカラム。

画像の保存

画像データはデータベースにそのまま保存するのではなく、基本的に画像本体は静的ファイル、画像の名前はデータベースに保存するようだ。

AlbumsController.php
    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という場所である。
スクリーンショット 2019-12-04 23.53.31.png
publicの下ではなく、album_coversというフォルダが/storage/appの下に作られ、保存した画像はその中にある。

そこでpublicディレクトリと/storage/appの間にリンクを持たせる必要がある。

>php artisan storage:link
The [public/storage] directory has been linked.

php artisan storage:linkを実行することによってシンボリックリンクを張り、その間にリンクを持たせることができる。

スクリーンショット 2019-12-05 00.05.57.png

publicの下にstorageというフォルダが作られ画像も保存されている。
これでブラウザ上から画像を見ることができる。

保存した画像を表示する

create.blade.php
@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となることに気を付けたい。

画像を削除する

PhotosController
    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テーブル上のデータだけでなく、アプリ内のストレージからも削除する。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4