質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.50%

Laravel5.4で画像をアップロードし、public/imagesに保存したい

解決済

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 8,307
退会済みユーザー

退会済みユーザー

現在Laravel5.4でグルメサイトの作成をしています。

formでレストラン名や住所などと一緒に、画像を登録した際に、画像がpublic/imagesフォルダに保存されるように実装したいのですが、できません。

いかに、create.blade.php, form.blade.php, ShopsController.phpのコードを掲載しております。どこが間違っているのかわかる方がおりましたら教えていただきたいですm(_ _)m
また根本的にLaravel5.4での画像アップロードの手法と間違っている場合は、その点も指摘していただけましたら幸いです。

create.blade.php

@extends('layout')

@section('content')

<div class="page-size center-block">
    <h3>レストラン新規登録</h3>
        <hr/>
        @include('errors.form_errors')

        {{Form::open(array('url' => 'shops', 'files' => true))}}
            @include('shops.form')
        {{Form::close()}}
</div>
@stop


form.blade.php

            <div class="form-group">
            {{Form::label('fname', 'レストランの写真')}}
            {{ Form::file('fname') }}
            </div>
            <div class="form-group">
                {{Form::label('name', '店名')}}
                {{Form::text('name', null, ['class' => 'form-control'])}}
            </div>
            <div class="form-group">
                {{Form::label('category', 'カテゴリー')}}<br>
                {{Form::select('category', [
                'フィリピン料理' => 'フィリピン料理',
                '和食' => '和食',
                '魚介・海鮮料理' => '魚介・海鮮料理',
                'そば・うどん' => 'そば・うどん',
                '焼き鳥' => '焼き鳥',
                'お好み焼き' => 'お好み焼き',
                'しゃぶしゃぶ' => 'しゃぶしゃぶ',
                '洋食' => '洋食',
                'フレンチ' => 'フレンチ',
                'イタリアン' => 'イタリアン',
                'スペイン料理' => 'スペイン料理',
                'ステーキ' => 'ステーキ',
                'ハンバーガー' => 'ハンバーガー',
                '中華料理' => '中華料理',
                '餃子' => '餃子',
                '韓国料理' => '韓国料理',
                'タイ料理' => 'タイ料理',
                'ラーメン' => 'ラーメン',
                'カレー' => 'カレー',
                '焼肉' => '焼肉',
                '鍋' => '鍋',
                '居酒屋' => '居酒屋',
                'バイキング' => 'バイキング',
                'カフェ' => 'カフェ',
                'パン' => 'パン',
                'スイーツ' => 'スイーツ',
                'バー・お酒' => 'バー・お酒']
                )}}
            </div>
            <div class="form-group">
                {{Form::label('description', 'レストランの紹介')}}
                {{Form::textarea('description', null, ['class' => 'form-control'])}}
            </div>
            <div class="form-group">
                {{Form::label('address', '住所')}}
                {{Form::text('address', null, ['class' => 'form-control'])}}
            </div>
            <div class="form-group">
                {{Form::label('runningtime', '営業時間')}}
                {{Form::text('runningtime', null, ['class' => 'form-control'])}}
            </div>
            <div class="form-group">
                <!-- {{Form::label('published_at', 'Publish On:')}} -->
                {{Form::hidden('published_at', date('Y-m-d'))}}
            </div>
            <div class="form-group form-button center-block">
                {{Form::submit('登録', ['class' => 'btn btn-success form-control'])}}
            </div>


ShopsController.php

<?php

namespace App\Http\Controllers;

use App\Shop;
use Illuminate\Http\Request;

class ShopsController extends Controller {

    public function index() {
        $shops = Shop::latest('published_at')->get();
        return view('shops.index', compact('shops'));
    }

    public function show($id) {
        $shop = Shop::findOrFail($id);
        return view('shops.show', compact('shop'));
    }

    public function create() {
        return view('shops.create');
    }

    public function store(Request $request) {
        $path = $request->file('fname')->store('images');

        // ①フォームの入力値を取得
        $inputs = \Request::all();

        // ②マスアサインメントを使って、記事をDBに作成
        Shop::create($inputs);

        // ③レストラン一覧へリダイレクト
        return redirect('shops');
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • CHERRY

    2017/08/27 16:38

    どのような問題が生じているのか具体的に書いてください。ログにメッセージが出ているようであれば、メッセージも記載してください。

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2017/08/27 16:41

    失礼しました。直ちに修正いたしますので、今しばらくお待ちいただけますと幸いです。

    キャンセル

回答 2

checkベストアンサー

+2

あくまでもpublic/images配下にファイルを保存するようにしたいのであれば、
config/filesystems.phpのdisks設定にpublicディレクトリ、もしくはpublic/imagesに向く設定を追加し、その名前をstoreメソッドの第二引数に指定する必要があります。
(もしくはシステム全体のデフォルトをその設定にしてもよい、filesystems.phpの冒頭参照)

デフォルトの設定ではlocalが使われることになりますが、
このlocalでのパスはstorage/app配下が指定されているため
->store('public/images');と書いても、storage/app/public/imagesの下にファイルが出来るだけです。

// filesystems.php
// disks設定に追加(publicはデフォルトで存在するので、本当なら別名推奨)
'public' => [
    'driver' => 'local',
    'root' => public_path();
]

// ShopsControllerのstoreメソッド
// storeの第二引数に、上の設定名を指定
$uploadName = $request->file('fname')->store('images', 'public');
// ファイル名を指定したければ、storeAsの第三引数に設定名を指定
$uploadName = $request->file('fname')->storeAs('images', 'somethingName.jpg', 'public');

// 共に$uploadNameにはアップしたパスとファイル名情報が含まれています

ここまで書きましたが、Laravelの推奨はpublic/images直下には直接ファイルを置くのではなく、
一度アップロードファイルは'storage/app/public'以下に置き、
public/storageからstorage/app/publicにシンボリックリンクを張り
アクセスすることを推奨しています。
これでよいのであれば、以下のページの「パブリックディスク」の項目が参考になります。

https://readouble.com/laravel/5.4/ja/filesystem.html

あわせて以下のページ最後の「アップロードファイルの保存」の項目も見ると使い方がわかります。
https://readouble.com/laravel/5.4/ja/requests.html

もともと最初から存在するpublic設定を使ってstoreメソッドを使い、
php aritsan storage:linkでシンボリックリンクを張るだけです。


最後になりますが、HTMLのformにenctype="multipart/form-data"を忘れないようにしてください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/29 18:51

    非常にご丁寧な回答をいただき感謝いたします。おかげさまで保存のフローを理解することができました。ありがとうございます。

    キャンセル

0

できないだけじゃわからないので、とりあえず、

画像がpublic/imagesフォルダに保存

なら

$request->file->store('public/images');


じゃないかなぁ

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/27 16:55

    ご回答いただきありがとうございます。$request->file->store('public/images');で試してみたところ、以下のエラーが出ました。

    Call to a member function store() on null

    キャンセル

  • 2017/08/27 20:55

    すいません。 $request->file('fname')->store('public/images'); ですね。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る