Skip to content

Media Storage

Laravel objects can use ‘hasMedia’ trait from the spatie/laravel-medialibrary package to attach media images in to ‘collections’.

Docs: https://docs.spatie.be/laravel-medialibrary

We are using version 7. Version 8 required PHP 7.4 and we are not using that version as of this setup.

Collections are stored in the medialibrary’s ‘cloud’ storage, which is defined in config/medialibrary.php pointing to the ‘linode’ filesystem disk.

config/filesystems.php defines a ‘linode’ disk pointing to linode object storage.

Buckets are defined as ‘indevets-user-assets’ for prod, ‘iv-staging’ for staging/testing, and ‘iv-dev’ for dev. Keys are defined in env files, and built in to configs during build process.

There are 2 ‘types’ of files used so far - dr images as a profile/avatar, and ‘bio’ files (assumed PDF).

We assume only one avatar and one biofile right now

EmployeeRepository::storeAvatar

$ext = $file->getClientOriginalExtension();
$this->employee->clearMediaCollection('avatars');
$this->employee->addMedia($file)
    ->setFileName($this->employee->core_id . '.' . $ext)
    ->setName($this->employee->core_id . '.' . $ext)
    ->toMediaCollectionOnCloudDisk('avatars');

EmployeeRepository::storeBio

$ext = $file->getClientOriginalExtension();
$this->employee->clearMediaCollection('biofile');
$this->employee->addMedia($file)
    ->setFileName($this->employee->core_id . '.' . $ext)
    ->setName($this->employee->core_id . '.' . $ext)
    ->toMediaCollectionOnCloudDisk('biofile');

The ‘clearMediaCollection’ will remove any previous bio file - both from local media table and the referenced objects on linode.

Other types of files might not be ‘cleared’, but because we only so far plan to have one profile pic and one bio file.

We grab the images and files like so…

Employee::getAvatarUrl

public function getAvatarUrl(int $minutes = 15, $returnDefault = false): string
{
    $avatar = $this->getMedia('avatars')->first();

    $default = $returnDefault ? url('images/'.self::$noUserIcon) : '';

    if (0 === $minutes) {
        return $avatar ? $avatar->getUrl('avatar') : $default;
    }

    return $avatar ? $avatar->getTemporaryUrl(Carbon::now()->addMinutes($minutes), 'avatar') : $default;
}
We can get a ‘temporary url’ which adds some access control and timeout protection to the image. The original filesystems config setup didn’t include ‘visibility’, so all files were private and required the ‘getTemporaryUrl’ call. The config is now set to ‘visibility=>true’, meaning all files are theoretically accessible if filenames are known.

Storage

Media is attached to objects, and metadata is stored in the ‘media’ table. The information points to a ‘disk’ and has filename stored in it. Metadata can include info about any related conversions processed.

Conversions

Images may be converted - ‘avatars’ collections are converted : conversion defined in Employee.php model file ‘registerMediaConversion’ method. When stored, the original file is stored, and a subfolder ‘conversions’ is stored.
There may be multiple conversions - thumbnail/large/small. Videos may be converted to preview files, etc. The ‘medialibrary’ package has a command to reconvert/process conversions against the original file if/when needed.