phayes0289's avatar

Building a Custom Path for Spatie Media Library

I have a custom path generator for the Spatie Media Library that works pretty well. But what I would like to do now is to pass value to further customize the path, but I am not sure how to get it into the media object. Something like a parent ID value (pibs_id) or the user_id. This is my current custom path generator called PibsPathGenerator.php. I'm guessing this is something obvious but currently above my knowledge level.

class PibsPathGenerator implements BasePathGenerator
{
    /**
     * Get the path for the given media, relative to the root storage path.
     *
     * @param \Spatie\MediaLibrary\MediaCollections\Models\Media $media
     *
     * @return string
     */
    public function getPath(Media $media): string
    {
        return  'media/pibs/' . $media->id . '/';
    }

    /**
     * Get the path for conversions of the given media, relative to the root storage path.
     *
     * @param \Spatie\MediaLibrary\MediaCollections\Models\Media $media
     *
     * @return string
     */
    public function getPathForConversions(Media $media): string
    {
        return 'media/pibs/conversions/' . $media->id . '/';
    }

    /**
     * Get the path for responsive images of the given media, relative to the root storage path.
     *
     * @param \Spatie\MediaLibrary\MediaCollections\Models\Media $media
     *
     * @return string
     */
    public function getPathForResponsiveImages(Media $media): string
    {
        return  'media/pibs/responsive-images/' . $media->id . '/';
    }
}

This is my form as it stands now, the Spatie Media Pro component can be seen about half way down.

            <form action="{{route('pibs.features.store', $pibs->id)}}" method="post" name="form1" id="form1" class="needs-validation" enctype="multipart/form-data" >
                @csrf
                <input type="hidden" name="pibs_id" id="pibs_id" value="{{$pibs->id}}">
                <!-- BEGIN row -->
                <div class="row">
                    <div class="col-xl-8 col-md-8">
                        <div id="panel-name" class="panel">
                            <div class="panel-hdr bg-primary-700" data-panel-fullscreen="true">
                                <h2>
                                    Panel name
                                </h2>
                                <div class="panel-toolbar">
                                    <button class="btn btn-panel" data-action="panel-collapse" data-toggle="tooltip" data-offset="0,10" data-original-title="Collapse"></button>
                                    <button class="btn btn-panel" data-action="panel-fullscreen" data-toggle="tooltip" data-offset="0,10" data-original-title="Fullscreen"></button>
                                </div>
                            </div>
                            <div class="panel-container show">
                                <div class="panel-content">

                                    <div class="col-xl-12 col-md-12">
                                        <label class="form-label" for="post_date">Feature Type:</label>
                                    <select class="select2 form-control w-100" id="type" name="type">
                                        @foreach ($feature as $group => $options)
                                            <optgroup label="{{ $group }}">
                                                @foreach ($options as $option)
                                                    <option value="{{ $option->value }}">{{ $option->name }}</option>
                                                @endforeach
                                            </optgroup>
                                        @endforeach

                                    </select>
                                        <div class="help-block">Choose A <code>NFIRS Occupancy Construction Type</code>
                                        </div>
                                    </div>

                                    <div class="col-xl-12 col-md-12 mt-2">
                                        <label class="form-label" for="title">Feature Title</label>
                                        <input type="text" id="title" name="title" class="form-control
                                           @error('title') is-invalid @enderror" value="{{old('title')}}">
                                        @error('title')
                                        <p class="invalid-feedback">
                                            {{$message}}
                                        </p>
                                        @enderror
                                    </div>

                                    <div class="col-xl-12 col-md-12 mt-2">

                                        <label class="form-label" for="tags">Tags</label>
                                        <input type="text" id="tags" name="tags" class="form-control selectized" value=""
                                               tabindex="-1">

                                        <small class="fs-10px text-gray-500-darker">Tag instructions.</small>
                                        @error('tags')
                                        <p class="invalid-feedback">
                                            {{$message}}
                                        </p>
                                        @enderror
                                    </div>

                                    <div class="col-xl-12 col-md-12 mt-2">
                                        <label class="form-label" for="description">Feature Notes:</label>
                                        <textarea class="ckeditor  @error('description') is-invalid @enderror" id="description"
                                                  name="description" rows="20">
                        </textarea>
                                        @error('description')
                                        <p class="invalid-feedback">
                                            {{$message}}
                                        </p>
                                        @enderror
                                    </div>

                                    <div class="col-xl-12 col-md-12 mt-2">

                                        <label class="form-label" for="image">Images</label>
                                    <x-media-library-attachment
                                        multiple max-items="3"
                                        name="image"
                                        rules="MIMES:png,jpg,jpeg|max:3024"
                                        editableName
                                        fields-view="pibs.partials.custom-properties"/>
                                    </div>

                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="col-xl-4 col-md-4">

                        {{--BEGIN PUBLISHING CONTROLS--}}
                        <div id="panel-publishing" class="panel">
                            <div class="panel-hdr bg-primary-700" data-panel-fullscreen="true">
                                <h2>
                                    Publishing Controls
                                </h2>
                                <div class="panel-toolbar">
                                    <button class="btn btn-panel" data-action="panel-collapse" data-toggle="tooltip"
                                            data-offset="0,10" data-original-title="Collapse"></button>
                                    <button class="btn btn-panel" data-action="panel-fullscreen" data-toggle="tooltip"
                                            data-offset="0,10" data-original-title="Fullscreen"></button>
                                </div>
                            </div>
                            <div class="panel-container show">
                                <div class="panel-content">


                                    <div class="form-group row">

                                        <div class="col-xl-12 col-md-12">

                                            <div class="row mt-2">
                                                <div class="col-xl-6 col-med-6">
                                                    <button type="submit" class="btn btn-block btn-success">
                                                        Submit / Save
                                                    </button>
                                                </div>
                                                <div class="col-xl-6 col-med-6">
                                                    <button type="button" class="btn btn-block btn-secondary">
                                                        Cancel
                                                    </button>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        {{--END PUBLISHING CONTROLS--}}
                    </div>
                </div>

            </form>

This is my controller

  public function store(Request $request, Pibs $pibs)
    {
        $formFields = $request->validate([
            'pibs_id' => ['required'],
            'title' => ['required', 'min:3'],
            'type' => ['required', 'min:3'],
            'tags' => ['nullable'],
            'description' => ['required'],
            'image' => ['nullable'],
        ]);

        $formFields['user_id'] = auth()->id();
        $pibsFeature = PibsFeature::create($formFields);
        $pibsFeature->addFromMediaLibraryRequest($request->image)
            ->withCustomProperties('extra_field', 'extra_field2', 'category')
            ->toMediaCollection($request->type);

        return view('pibs.features.index', compact('pibs'))->with('message', 'User updated successfully!');
    }

Thanks in advance.

0 likes
2 replies
hariadi's avatar

You can set MEDIA_PREFIX=prefix/folder on your .env, then your custom path generator:

public function getPath(Media $media): string
{
    $prefix = config('media-library.prefix', '');

    if ($prefix !== '') {
        return $prefix.'/'.$media->model_id.'/'.$media->id.'/'.$media->getKey();
    }

    return $media->model_id.'/'.$media->getKey().'/';
}

public function getPathForConversions(Media $media): string
{
    return $this->getPath($media).'/conversions/';
}

public function getPathForResponsiveImages(Media $media): string
{
    return $this->getPath($media).'/responsive/';
}

You can also make it global (by replace the config for path_generator) or only for given model class using custom_path_generators on your config/media-library.php:

'custom_path_generators' => [
    \App\Models\User::class => PibsPathGenerator::class,
],
Andrewchukwu's avatar

You can set custom properties on the media object and grab it in your custom path generator. I have implemented the Repository pattern and using the App facade I can load data from any model via a Repository implementation for any model. e.g.

Anyhow, once you have set the customer properties, they can be accessed as below (Laravel 9) $parent_id=$media->getCustomProperty('parent_id');

Please or to participate in this conversation.