本日は既存のアプリへファイルアップロード機能の追加を行い、それに伴うデータベースの変更処理を勉強していきましょう!
むずかしそうだワン。。。
コマンドからデータベースの変更とかしないといけないのかにゃ?
Laravel ではマイグレーションから簡単にデータベースの変更ができます。ファイルアップロードも便利なメソッドがあり少ない記述で実装できますのでやっていきましょう!
こんにちは!あっきーです!
前回の記事で紹介したデータベースを使った Webアプリを元にデータベースに変更を加え機能を追加する方法を記事にしました。
元の Webアプリの作り方を確認する場合はこちらを確認してください。
今回の記事で得られる知識以下になります。
・ファイルアップロード機能の実装方法
それではまとめていきます。
完成イメージ
前回記事の完成イメージの画面に赤枠部分を追加していきます。
・表示ページ
・登録ページ
・バリデーション
マイグレーションでデータベースを変更する
開発を続けていくと、テーブルにカラムを追加する必要があったり、初期で決めたカラムの定義を変更する(カラム名の変更・カラムの追加など)必要も出てくる場合があります。その時に Laravel はマイグレーションで構築が簡単に行うことができます。
その場合は、最初のデータベースを構築するときに作成したマイグレーションファイルを編集するのではなく、新たにマイグレーションファイルを作成し、その都度スキーマビルダで記述していきます。
カラムを変更するためのパッケージをインストール
Laravelでは、デフォルトのままではカラム変更のマイグレーションは行えません。新たにパッケージを導入する必要があります。
パッケージをインストールするために以下のコマンドを実行してください。
・Composer からパッケージのインストール
ターミナル
1 |
$ composer require doctrine/dbal |
1 |
変更用のマイグレーションファイルを作成
・変更用のマイグレーションファイル生成
ターミナル
1 |
$ php artisan make:migration change_comics_table --table=comics |
コマンドで生成したマイグレーションファイルに変更内容を記述していきます。
database/migrations/2019_02_28_144834_change_comics_table.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class ChangeComicsTable extends Migration { public function up() { Schema::table('comics', function (Blueprint $table) { $table->string('image')->index('index_image')->after('description')->nullable(); //追加 }); } public function down() { Schema::table('comics', function (Blueprint $table) { $table->dropColumn('image')->nullable(); //追加 }); } } |
※メソッド以外は部分的に省略しています。
string 型の新規のカラム「image」を既存のカラム「description」の後ろに追加し null での追加を許可するという記述を up() メソッド内に記述しました。
追加でなく変更の場合は対象のカラムを指定して ->change() とメソッドを記述すればできるのじゃ。
続いて down() メソッド内に up() メソッドでのデータを記述しておき間違えた時に戻せるようにしておきます。
・マイグレーションの実行
ターミナル
1 |
$ php artisan migrate |
・元に戻したい時
ターミナル
1 |
$ php artisan migrate:rollback |
アップロード機能の実装
デフォルトでのアップロードファイルは storage/app/public フォルダ配下のディレクトリに保存されます。Web からのアクセスを許可するためには public/storage からのシンボリックリンクを配置する必要があります。
シンボリックリンクはショートカットフォルダをイメージしていただければ良いかと思います。
以下のコマンドからシンボリックリンクを生成します。
・シンボリックリンクの生成
ターミナル
1 |
$ php artisan storage:link |
画像の保存先の設定ができましたのでアップロード機能の記述をしていきましょう。
バリデーション設定
前回の記事で作成したバリデーションのファイルに以下の記述を追加します。
app/Http/Requests/ComicRequest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
class ComicRequest extends FormRequest { public function authorize() { return true; } public function rules() { return [ 'comic_name' => 'required', 'image' => 'image|mimes:jpeg,png,jpg|max:2048',//追加 ]; } public function messages() { return [ 'comic_name.required' => ' ※コミック名は必須項目です', 'image.image' => ' ※画像ファイルを選択してください',//追加 ]; } } |
rules() メソッドにバリデーションの内容を記述して messages() メソッドでレスポンスで画面に表示されるバリデーションのメッセージをオーバーライドします。
rules() メソッドには拡張子の指定と画像ファイルの大きさを指定しています。
コントローラーの編集
前回記事で作成したコントローラに以下の修正を加えます。
app/HTTP/Controllers/ComicController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public function create(ComicRequest $request) { /* Postされた画像データを public/storage/imagesフォルダ配下に保存 */ if(isset($request->image)) { $path = $request->file('image')->store('images', 'public'); $image = basename($path); }else { $image = ''; } /* データベースへの追加処理 */ $comic = new Comic; $form = [ 'comic_name' => $request->comic_name, 'magazine_id' => $request->magazine_id, 'author_id' => $request->author_id, 'description' => $request->description, 'image' => $image, ]; unset($form['_token']); $comic->fill($form)->save(); return redirect('/comic'); } |
ビューテンプレート
同じく前回記事で作成したビューテーンプレートファイルに以下の修正を加えていきます。
・登録ページ
resources/views/comic/add.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
<!-- 'files' => true の追加 --> {!! Form::open(['url' => '/comic/add', 'method' => 'post', 'files' => true]) !!} @if($errors->has('comic_name')) <p>{{$errors->first('comic_name')}}</p> @endif <!-- 追加 --> @if($errors->has('image')) <p>{{$errors->first('image')}}</p> @endif {{Form::label('comic', 'コミック名')}} {{Form::text('comic_name', old('comic_name'))}} {{Form::label('authors', '作者')}} <select name="author_id"> @foreach($authors as $author) <option value={{$author->id}} @if(old('author_id')==$author->id) selected @endif> {{$author->author}} </option> @endforeach </select> {{Form::label('magazines', '連載誌')}} <select name="magazine_id"> @foreach($magazines as $magazine) <option value={{$magazine->id}} @if(old('magazine_id')==$magazine->id) selected @endif> {{$magazine->magazine}} </option> @endforeach </select> {{Form::label('comic', '説明')}} {{Form::text('description', old('description'))}} <!-- 追加 --> {{Form::label('image', '画像')}}ここ {{Form::file('image', $attributes = [])}}ここ {!! Form::submit('登録') !!} {!! Form::close() !!} @endsection |
・表示ページ
resources/views/comic/index.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
@section('content') {!! Form::open(['url' => '/comic/add', 'method' => 'get']) !!} {!! Form::submit('登録', ['class' => 'form-control', 'id' => '']) !!} {!! Form::close() !!} <!-- view --> <table> <tr> <th>コミック</th> <th>作者</th> <th>連載誌</th> <th>説明</th> <th>画像</th> </tr> @foreach($items as $item) <tr> <td>{{$item->comic_name}}</td> <td>{{$item->magazine->magazine}}</td> <td>{{$item->author->author}}</td> <td>{{$item->description}}</td> <!-- 追加 --> @if($item->image) <td> <img src="/storage/images/{{$item->image}}" alt="images" width="300" height="300"> </td> @else <td> <img src="/storage/images/Noimage_image.png" alt="images" width="300" height="300"> </td> @endif </tr> @endforeach </table> @endsection |
画像データの有無をチェックしてからデータがない場合はあらかじめ保存しておいた画像(今回では NOIMAGE の画像)を表示するようにしています。
以上で完成です。
完成イメージのように追加した画像データが表示されるようになっているかと思います。
さいごに
最後まで読んでいただいてありがとうございます。
ファイルアップロード機能の記事だけでは物足りないかなと思い既存のデータベースに変更を加えてから行う記事にしてみましたがいかがでしたでしょうか。
次は CRUD 処理の機能の追加なども記事にしてみようかと思います。
プログラムの間違えなどありましたら教えていただけましたら幸いです。
この記事を気に入っていただけましたらTwitter でもプログラミングのことについてツイートしていますので是非ご一緒にフォローの方もお願いします!
それでは次の記事でまたお会いしましょう!
・参考書籍