Laravel8で動画投稿機能を実装した話

Keytoneです。はじめまして。
現在、エンジニアになるべく転職活動中です。<br>
ポートフォリオも作成しております。
(https://ytanabe-potoforio.com/)
良ければ見てもらえれば嬉しいです。

知識のアウトプットも兼ねて、私が作成したアプリMemorizeの中で最も力を入れた部分の動画投稿機能の実装について実装した時を思い返しながら書いていこうと思います。
それでは本題に入ります。

# 動画投稿機能の記述
前提としてLaravel8で本機能を実装しました。
以降、その前提で読み進めてもらえると嬉しいです。
## ルート
今回は投稿部分のみのルートを記述します。
resourceで作成しました。
```php:web.php(一部)
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostController;
Route::resource('posts',PostController::class);
```
## ビュー
まずビューファイルの動画を表示する部分を説明します。（動画表示部分)
```php:index.blade.php(表示部分)
<div class="contents_video_form">
     @if($post->movie !==''&&$post->filename($post)==='mp4'||$post->filename($post)==='mov'||$post->filename($post)==='x-ms-wmv'||$post->filename($post)==='mpeg')
          <video controls width="250" src="{{asset('storage/'.$post->movie)}}" muted class="contents_width">
          </video>
     @elseif($post->filename($post)==='jpg'||$post->filename($post)==='jpeg'||$post->filename($post)==='png')
          <img src="{{asset('storage/'.$post->movie)}}" class="contents_width">
     @else
          <img src="{{asset('images/no_image.png')}}">
          <p>ファイルはありません。</p>
     @endif
</div>
```
概要を説明すると＄post->movieでファイルのURLを格納し、filenameで投稿ファイルの形式を調べています。動画の時はvideoタグ、画像ファイル形式の時はimgタグで表示を分けるような表示にしています。

また、動画投稿部分のソースを記述します。
```php:index.blade.php(動画投稿部分)
<form method="post" action="{{route('posts.store')}}" class="posts_form" enctype="multipart/form-data">
    @csrf
    --中略--
    <div class="posts_item">
        <p>ファイル投稿:<br>(上限:20MB)</p>
            <div class="posts_file_list">
                <label class="posts_file_input">
                    <input type="file" name="movie">
                        ファイルを選択
                </label>
                <p class="posts_filename">選択されていません</p>
            </div>
     </div>
     <button type="submit" class="posts_submit">新規投稿</button>
</form>
```
概要を説明すると、画像を送信するためformのenctypeをmultipart/form-dataに設定し、コントローラーの処理に送信してます。
## コントローラー
次にコントローラーの記述について説明します。
ここでは実際に書き込みを行なっているstoreメソッドについてのみ説明します。
```php:PostController.php(store)
public function store(PostRequest $request)
   {
       //動画ファイル投稿用のパス
       $path='';
       $movie=$request->file('movie');
       if(isset($movie)===true)
       {
           //storage/app/public/videosにパスを保存
           $path=$movie->store('videos','public');
       }
       Post::create([
           'user_id'=>\Auth::user()->id,
           'category_id'=>$request->category,
           'name'=>$request->name,
           'description'=>$request->description,
           'movie'=>$path,
       ]);
       session()->flash('success','投稿しました。');
       return redirect()->route('posts.index');
    }
```
movieにフォームから送信されたrequestを格納します。
その後、ファイルが空でないか調べた上で、パス情報をstorage内に保存します。後は新規Postモデルを作成し、結果をpostsテーブルに格納します。
これが一連の流れです。

※実際に画像を表示するためにはstorageに保存したファイルを公開フォルダであるpublicにシンボリックリンクを立ててやる必要があります。(php artisan storage:link)
### リクエスト処理
```php:PostRequest.php(一部)
class PostRequest extends FormRequest
{
    public function rules()
    {
        return [
            // 画像、動画ファイル(mp4,mov,wnv,mpeg,avi,jpg,png,jpeg)をチェック
            'movie'=>['required','file','mimes:mp4,mov,x-ms-wmv,mpeg,avi,jpeg,jpg,png',
            'max:1000000'],
        ];
    }
}
```
mimesでファイル形式をチェックし、ファイルの最大容量を1GBに設定しています。
しかし、実際に１GBのファイルを投稿するためにはデプロイするサーバーのPHP,Apacheの設定を変更する必要があります。私は以下の記事を参考にしましたが、２０MBぐらいのものまでしか投稿できませんでした。

[大容量ファイルアップロードに関係するPHP・Apacheの設定](https://b-risk.jp/blog/2013/03/megafile/)
[Laravelでファイルアップロードが失敗する場合の対処法](https://qiita.com/sano1202/items/b2babd55a6b11109de9a)
## 作成してみての感想
大切な出来事や日々の瞬間をソートして残せるようなアプリを作りたいなと思い、動画投稿機能を取り入れました。一つの機能を実装するためには多くの下調べと知識が必要なんだなと制作を通して実感しました。
今後はもっと理解した知識をアウトプットしていきたいと思っています。
ここまで読み進めてくれた方、ありがとうございました！