Laravelでファイルをデータベースで管理するライブラリを公開した

今回はLaravel上で簡単にファイルをデータベースで管理できるようにするライブラリを公開したので紹介したいと思います。

laravel-eloquent-storage

github.com

このライブラリはEloquentモデルに

<?php

use MatchinGood\EloquentStorage\EloquentStorage;

class UserFile extends EloquentStorage
{

}

という感じで継承させるだけで、そのモデルでファイルを管理できるようになります。

仕組み

データベースにファイルを保存するのはデータベースの容量を圧迫するだけでなくパフォーマンスにも影響が出てきます。

なので、容量単位の単価がはるかに安いS3にファイルを保存するようにしました。このライブラリではこの辺りのファイル管理を隠蔽しています。

概念的には以下の図で表せます。 f:id:takuseno:20161206132835j:plain

S3にはファイル名の衝突を避けるためにユニークなファイル名で保存し、MySQLには保存したユニークなファイル名とオリジナルのファイル名を保存します。

これにより、ファイル名の衝突を避けつつダウンロード時にはオリジナルのファイル名を使うことができます。

実際に使うと

例えばユーザーがアップロードしたファイルをUserFileというモデルで保存しようと思った時は

<?php

$file = $request->file('file');
$userFile = new UserFile;
$userFile->saveFromUploadedFile($file);

たったこれだけでファイルを保存することができました。さらにそのファイルをダウンロードさせようと思ったらコントローラで、

<?php
$userFile = UserFile::find(1);

return response()->downloadEloquentStorage($userFile);

とするだけでダウンロードさせることができます。これはResponse Macroをサービスプロバイダーで定義することでdownloadEloquentStorageという関数を使うことができるようになっているからです。

laravel.com

開発環境時の工夫

システムを開発時にS3に繋げたくありません。そこでconfig/eloquentstorage.phpでドライバーを設定することができるようになっています。

<?php
return [
    // this is the same drivers as Storage facade on Laravel
    // ELoquentStorage uses Storage facade internally
    'driver' => 'local'
];

このライブラリは内部的にはStorageを使っているので、S3にあげたくない場合はドライバーをlocalにすることでローカル環境にファイルを保存します。

実際にデプロイするときにこのドライバーをs3とすることでS3に保存できるようになります。

まとめ

最近弊社では積極的にオープンソースのライブラリを公開してコミュニティに貢献しようという熱が高まってきました。このような軽量なものから、まだ公開していない大きなライブラリまであります。このような環境はエンジニアにとってはとても魅力的な環境であると考えているからこそ実践させてもらっています。