Laravel

Custom path generation in Spatie Media Library while multi-tenant

Recently we use Spatie laravel-multitenancy package in our of our client's CRM project along with spatie/laravel-medialibrary.

The default behavior of the media library package is, it generates a folder for each media with its ID in our configured disk, like a public folder or s3 or whatever disk we configured.

This works really great when you are dealing with a single-tenant application. But while using multi-tenant, you got a media table in each of your tenant databases. so this pattern simply doesn't work. Because then you will end up having multiple media files under the same folder from different tenants.

So what we want to do is, instead of having a structure like,

public
-- media
---- 1
------ file.jpg
---- 2
------ file.jpg
...

What we want to achieve is, we want to have a folder structure where media of every tenant will be in a separate folder with tenant unique id,

public
-- media
---- abcd1234 // tenant1 Id
------ 1
-------- file.jpg
------ 2
-------- file.jpg
---- efgh5678 // tenant2 Id
------ 1
-------- file.jpg
------ 2
-------- file.jpg
...

Spatie Media library is very configurable out of the box where you can write your own media library path generator. That is documented very well over here: https://docs.spatie.be/laravel-medialibrary/v8/advanced-usage/using-a-custom-directory-structure

So what we did is, we wrote our own Path Generator, which can store files into tenants folder. Here is how it looks like,

<?php

namespace App\MediaLibrary;

use Spatie\MediaLibrary\MediaCollections\Models\Media;
use Spatie\MediaLibrary\Support\PathGenerator\DefaultPathGenerator;

class InfyCRMMediaPathGenerator extends DefaultPathGenerator
{
    /*
     * Get a unique base path for the given media.
     */
    protected function getBasePath(Media $media): string
    {
        $currentTenant = app('currentTenant');

        return $currentTenant->unique_id.DIRECTORY_SEPARATOR.$media->getKey();
    }
}

What we did here is, we just simply extended the Spatie\MediaLibrary\Support\PathGenerator\DefaultPathGenerator of Media Library and override the function getBasePath. We attached the prefix of the tenant's unique_id to the path. so instead of 1/file.png, it will return abcd1234/1/file.png.

All you need to make sure is, whenever you are uploading a media, your application should be tenant aware. Otherwise, it will not able to get the current tenant.

Hope this helps while using spatie media library along with spatie multi-tenant.

Even if you are not using a spatie multi-tenant, still you can create your own PathGenerator and use it your own way to have a media structure you want.