🦁
Laravel × Spatie Medialibrary:S3に保存するための実装手順
AWS上でIAMの設定とS3のバケット作成が済んでいる前提で進めていきます。
1. 必要なパッケージをインストール
必要なライブラリをインストールします。
composer require league/flysystem-aws-s3-v3
composer require spatie/laravel-medialibrary
2. Medialibrary 設定の初期化
spatie/laravel-medialibrary の設定を公開してマイグレーションを実行します。
php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider"
php artisan migrate
3. S3ドライバを設定
config/filesystems.php で S3 への接続設定をします。
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
'endpoint' => env('AWS_ENDPOINT'),
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
'throw' => false,
],
.env ファイルに環境変数を追記します。
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=ap-northeast-1
AWS_BUCKET=
4. モデルに HasMedia トレイトを追加
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
class Video extends Model implements HasMedia
{
use HasFactory,
InteractsWithMedia;
protected $fillable = ['name'];
}
5. アップロードロジックを作成
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Video;
use Illuminate\Http\Request;
class VideoController extends Controller
{
/**
* 動画アップロードフォームを表示
*/
public function create()
{
return view('videos.create');
}
/**
* 動画を保存(S3 にアップロード)
*/
public function store(Request $request)
{
// バリデーション
$request->validate([
'name' => 'required|string|max:255',
'video' => 'required|file|mimes:mp4,mov,avi,wmv|max:20480', // ファイルサイズや拡張子は必要に応じて調整
]);
// モデルを作成
$video = new Video();
$video->name = $request->input('name');
$video->save();
// Spatie MediaLibrary のメソッドでアップロード
// 第2引数でアップロード先ディスクを指定("s3" など)
$video->addMediaFromRequest('video')
->toMediaCollection('videos', 's3');
return redirect()
->back()
->with('success', '動画をアップロードしました!');
}
}
ポイント解説
addMediaFromRequest('video') でリクエストの video フィールドを指定しています。
toMediaCollection('videos', 's3') の第2引数でアップロード先のディスクを指定できます。
6. カスタムパス
spatie/laravel-medialibraryのデフォルト設定では[id]/[ファイル名]というディレクトリ構成でアップロードされます。
設定ファイルを作成し、任意のディレクトリ構成にしたい設定(カスタムパスジェネレータ)を書くことで変更することができます。
php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="medialibrary-config"
カスタムパスジェネレータを作成
ここでは Services\MediaLivrary\CustomMoviePathGenerator.php という名前でカスタムパスジェネレータを作成し、[コレクション名]/[id名]/[ランダム文字列.拡張子] というディレクトリ構成で保存されるように設定しました。
<?php
namespace App\Services\MediaLibrary;
use Spatie\MediaLibrary\Support\PathGenerator\PathGenerator;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
class CustomMoviePathGenerator implements PathGenerator
{
/**
* メディアの保存パスをカスタマイズ
*/
public function getPath(Media $media): string
{
// コレクション名/id名/ランダム文字列.拡張子
return "{$media->collection_name}/".$this->getBasePath($media).'/';
}
/*
* Get the path for conversions of the given media, relative to the root storage path.
*/
public function getPathForConversions(Media $media): string
{
return $this->getBasePath($media).'/conversions/';
}
/*
* Get the path for responsive images of the given media, relative to the root storage path.
*/
public function getPathForResponsiveImages(Media $media): string
{
return $this->getBasePath($media).'/responsive-images/';
}
/*
* Get a unique base path for the given media.
*/
protected function getBasePath(Media $media): string
{
$prefix = config('media-library.prefix', '');
if ($prefix !== '') {
return $prefix.'/'.$media->getKey();
}
return $media->getKey();
}
}
最後にconfig/media-libray.phpに Video モデルの場合、このカスタムパスジェネレータの設定が反映されるようにしています。
'custom_path_generators' => [
// Model::class => PathGenerator::class
// or
// 'model_morph_alias' => PathGenerator::class
Video::class => App\Services\MediaLibrary\CustomMoviePathGenerator::class,
],
Discussion