Skip to content

Instantly share code, notes, and snippets.

@kohki-shikata
Created September 26, 2024 03:06
Show Gist options
  • Save kohki-shikata/55072289d3c287e872ecaae2868898a6 to your computer and use it in GitHub Desktop.
Save kohki-shikata/55072289d3c287e872ecaae2868898a6 to your computer and use it in GitHub Desktop.
ファイルの操作を行うLaravelのTrait
<?php
namespace App\Traits;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Validator;
use Intervention\Image\Facades\Image; // Intervention Imageパッケージを使用
trait FileStorageTrait
{
protected $maxFileSize = 4 * 1024 * 1024; // 最大4MB
protected $maxFiles = 30; // 最大30件
protected $minImageSize = 200; // 短辺の最小サイズ(200px)
/**
* アップロードされたファイルを指定のディスクに保存します。
*
* @param UploadedFile[] $files
* @param string $directory
* @return array 保存したファイルのキー
*/
public function uploadFiles(array $files, string $directory = ''): array
{
// スロットリングの実装
$this->throttleRequests();
// バリデーション
$this->validateFiles($files);
$savedPaths = [];
foreach ($files as $file) {
// 画像のサイズを確認
if (!$this->isImageSizeValid($file->getPathname(), $this->minImageSize)) {
return ['error' => '画像が小さすぎます。'];
}
// ファイルの保存
$path = $this->uploadFile($file, $directory);
$savedPaths[] = $path;
}
return $savedPaths;
}
/**
* アップロードされたファイルを指定のディスクに保存します。
*
* @param UploadedFile $file
* @param string $directory
* @return string 保存したファイルのキー
*/
public function uploadFile(UploadedFile $file, string $directory = ''): string
{
$disk = Storage::disk('s3'); // ここで使用するディスクを指定
$filename = $this->generateUniqueFileName($file);
$path = $directory ? "{$directory}/{$filename}" : $filename;
$disk->put($path, file_get_contents($file));
return $path;
}
/**
* バリデーション
*
* @param UploadedFile[] $files
* @return void
*/
protected function validateFiles(array $files): void
{
$validator = Validator::make(['files' => $files], [
'files.*' => 'required|file|mimes:jpeg,png|max:' . ($this->maxFileSize / 1024), // KB単位
]);
if ($validator->fails()) {
throw new \Exception('バリデーションエラー: ' . json_encode($validator->errors()), 400);
}
if (count($files) > $this->maxFiles) {
throw new \Exception('最大' . $this->maxFiles . '件までのアップロードが可能です。', 400);
}
}
/**
* アップロードされた画像のサイズを確認します。
*
* @param string $filePath
* @param int $minSize
* @return bool
*/
protected function isImageSizeValid($filePath, $minSize): bool
{
$image = Image::make($filePath);
return min($image->width(), $image->height()) >= $minSize;
}
/**
* ファイルを指定のキーで取得します。
*
* @param string $path
* @return string|null ファイルの内容
*/
public function getFile(string $path): ?string
{
$disk = Storage::disk('s3');
return $disk->exists($path) ? $disk->get($path) : null;
}
/**
* ファイルを指定のキーで削除します。
*
* @param string $path
* @return bool 削除に成功したかどうか
*/
public function deleteFile(string $path): bool
{
$disk = Storage::disk('s3');
return $disk->exists($path) ? $disk->delete($path) : false;
}
/**
* ファイルを指定のキーで更新します。
*
* @param UploadedFile $file
* @param string $path
* @return bool 更新に成功したかどうか
*/
public function updateFile(UploadedFile $file, string $path): bool
{
return $this->deleteFile($path) && $this->uploadFile($file, dirname($path));
}
/**
* 一意のファイル名を生成します。
*
* @param UploadedFile $file
* @return string 一意のファイル名
*/
protected function generateUniqueFileName(UploadedFile $file): string
{
return Str::uuid()->toString() . '.' . $file->extension();
}
/**
* スロットリングの処理を実装
*
* @return void
*/
protected function throttleRequests(): void
{
// スロットリングの具体的な実装を追加
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment