Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

phayes0289's avatar

Looking for a Way To Use Media-Library-Pro to set a Global Setting in Laravel-Settings

I am using Spatie Larvael-Settings to manage global settings for my project. I want the user to be able to save a logo URL to the settings. I have an idea to use my existing Spatie Media-Libray Pro package to somehow allow the user to to chose and upload an image. My thought is that once the image is uploaded, that I can use the “getFirstMediaPath” and save it to the settings.

But the problem is that the Media-Libray Pro images are associated with a model (specifially a row in the database). Since the data structure of the how Spatie Larvel_settings are saved is not your standard model relationship, I am not sure how this can be done.

I have the following controller:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use \App\Models\lookup;
use \App\Settings\GeneralSettings;

class SettingsController extends Controller
{
    public function index(Request $request)
    {
        $pubStatus =Lookup::where('taxonomy' , 'publishing-status')->get();

       return view('settings/index', compact('pubStatus','settings'));

    }

    public function __invoke(Request $request, GeneralSettings $settings)
    {

        $settings->site_status = $request->boolean('site_status');
        $settings->page_help = $request->boolean('page_help');
        $settings->site_name = $request->input('site_name');
        $settings->agency_name = $request->input('agency_name');
        $settings->agency_address = $request->input('agency_address');

        $settings->save();

        return redirect()->back()->with('message', 'The SETTINGS have been updated!');
    }
}

A “settings” form is presented using the index function in the controller above. The form is modified and the submitted to the controller’s __invoke function. These are the routes for both.

Route::get('/settings', [SettingsController::class, 'index'])->name('settings.index');
Route::patch('/settings', [SettingsController::class, '__invoke'])->name('settings.update');

Below is my settings form page where all the settings can be set by the client. I have commented out a place where I hope to put the Media-Library Comnponent.

<form action="{{route('config.settings.update')}}" method="post" name="form1" id="form1">
            @csrf
            @method('PATCH')
        <div class="row">
            <div class="col-xl-8 col-md-8">
                <div id="panel-basic-info2" class="panel">
                    <div class="panel-hdr bg-primary-700" data-panel-fullscreen="true">
                        <h2>
                            Basic Information
                        </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">
                                <label class="form-label col-form-label @error('page_help') is-invalid @enderror"
                                    for="page_help">Site Status</label>
                                <br>
                                <div class="btn-group btn-group-toggle" data-toggle="buttons">
                                    <label class="btn btn-lg custom-btn-color p-1" style="width:80px">
                                        <input type="radio" name="site_status" id="site_status" value="false"
                                        @unless ($site_status) checked @endif> Off
                                    </label>
                                    <label class="btn btn-lg custom-btn-color p-1" style="width:80px">
                                        <input type="radio" name="site_status" id="site_status" value="true"
                                        @if ($site_status) checked @endif> On
                                    </label>
                                </div>
                            </div>

                            <div class="form-group">
                            <label class="form-label col-form-label @error('site_name') is-invalid @enderror"
                                for="site_name">Site Name</label>

                            <input type="text" class="form-control mb-5px @error('site_name') is-invalid @enderror"
                                placeholder="Enter Training Record site_name" id="site_name" name="site_name"
                                value="{{ $site_name }}" />
                            @error('site_name')
                                <span class="invalid-feedback">
                                    {{ $message }}
                                </span>
                            @enderror
                        </div>

                        <div class="form-group">
                            <label class="form-label col-form-label @error('page_help') is-invalid @enderror"
                                for="page_help">Page Help</label>
                            <br>
                            <div class="btn-group btn-group-toggle" data-toggle="buttons">
                                <label class="btn btn-lg custom-btn-color p-1" style="width:80px">
                                    <input type="radio" name="page_help" id="page_help" value="false"
                                    @unless ($page_help) checked @endif> Off
                                </label>
                                <label class="btn btn-lg custom-btn-color p-1" style="width:80px">
                                    <input type="radio" name="page_help" id="page_help" value="true"
                                    @if ($page_help) checked @endif> On
                                </label>
                            </div>
                        </div>

                        <div class="form-group">
                            <label class="form-label col-form-label @error('agency_name') is-invalid @enderror"
                                for="site_name">Agency Name</label>

                            <input type="text" class="form-control mb-5px @error('agency_name') is-invalid @enderror"
                                placeholder="Enter Training Record agency_name" id="agency_name" name="agency_name"
                                value="{{ $agency_name }}" />
                            @error('agency_name')
                                <span class="invalid-feedback">
                                    {{ $message }}
                                </span>
                            @enderror
                        </div>

                        <div class="form-group">
                            <label class="form-label col-form-label @error('agency_address') is-invalid @enderror"
                                for="site_name">Agency Name</label>

                            <input type="text" class="form-control mb-5px @error('agency_address') is-invalid @enderror"
                                placeholder="Enter Training Record agency_address" id="agency_address" name="agency_address"
                                value="{{ $agency_address }}" />
                            @error('agency_address')
                                <span class="invalid-feedback">
                                    {{ $message }}
                                </span>
                            @enderror
                        </div>
                        </div>
                    </div>
                </div>

                <div id="panel-publishing" class="panel">
                    <div class="panel-hdr bg-primary-700" data-panel-fullscreen="true">
                        <h2>
                            Media
                        </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">
                            {{-- <x-media-library-collection max-items="5" collection="settings-media" name="logo"
                                :model="$settings" rules="MIMES:pdf|max:10024" editableName /> --}}
                        </div>
                    </div>
                </div>
            </div>
            <div class="col-xl-4 col-md-4">
                <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"
                                                onclick="goBack()">
                                                Cancel
                                            </button>
                                        </div>
                                    </div>
                                </div>
                            </div>

                        </div>
                    </div>
                </div>
            </div>

        </div>

        </form>

How can I use Spatie Media Library Pro to upload the image, get the URL of the image and allow for the continued managment of the image from the same settings edit page? According to what i know, the image must be related to a model, specicially, an ID in the model.

I was thinking of creating an images model with a one field called “type”. Then I would create records and use the following unique “types”.

logo

report_logo

login_logo

Then maybe we could retrieve the records using the index method above and associate each of the media_library components with associated “images’ record on the settings edit page?

Is there any reason why that may not work? What would the code look like?

0 likes
1 reply
LaryAI's avatar
Level 58

To achieve the functionality you're looking for with Spatie Media Library Pro and Laravel Settings, you can indeed create a dedicated model to handle the global settings media. This model will act as a container for the various types of media you want to associate with your settings, such as logos.

Here's a step-by-step solution:

  1. Create a model to handle the settings media. Let's call it SettingMedia.
php artisan make:model SettingMedia -m
  1. In the migration file for SettingMedia, add a type column to differentiate between different media types.
Schema::create('setting_media', function (Blueprint $table) {
    $table->id();
    $table->string('type')->unique(); // Ensure that the type is unique
    $table->timestamps();
});
  1. Run the migration to create the table.
php artisan migrate
  1. Add the HasMedia trait to the SettingMedia model and register the media collections you need.
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Illuminate\Database\Eloquent\Model;

class SettingMedia extends Model implements HasMedia
{
    use InteractsWithMedia;

    protected $fillable = ['type'];

    public function registerMediaCollections(): void
    {
        $this->addMediaCollection('logo')
            ->singleFile(); // Assuming you only want one file for the logo
    }
}
  1. In your SettingsController, you can now handle the upload and association of media with the SettingMedia model.
public function updateSettings(Request $request)
{
    // ... handle other settings

    // Handle the logo upload
    if ($request->hasFile('logo')) {
        $logoMedia = SettingMedia::firstOrCreate(['type' => 'logo']);
        $logoMedia->addMediaFromRequest('logo')->toMediaCollection('logo');
    }

    // ... handle other media types similarly

    return redirect()->back()->with('message', 'The SETTINGS have been updated!');
}
  1. In your settings form, you can use the Media Library Pro component to upload and manage the logo.
{{-- Assuming you have a SettingMedia instance for the logo --}}
<x-media-library-attachment name="logo" :model="$logoMedia" collection="logo" />
  1. To retrieve the URL of the logo in your views or elsewhere, you can do something like this:
$logoMedia = SettingMedia::where('type', 'logo')->first();
$logoUrl = optional($logoMedia)->getFirstMediaUrl('logo');
  1. Finally, make sure to update your routes and views to handle the file upload.
Route::patch('/settings', [SettingsController::class, 'updateSettings'])->name('settings.update');

This approach allows you to manage global media settings in a structured way, with each type of media associated with a unique record in the setting_media table. The type column ensures that you can easily retrieve and manage the media for each setting type.

Please or to participate in this conversation.