Laravel: Store Settings in Database with Defaults in the config file

I personally prefer to have my site settings in the database to make them more customizable than to have them in the /config/settings.php file, Here’s how i do it:

assuming you want to have the file’s name settings.php inside the /config path, then whatever you put in there will be config(‘settings.some_option’);

<?php 
return [
    'title'       =>'App Title',
    'description' =>'App Description',
    'performance' => [
        'cache'   => 1,
        'lifetime'=> 120,
    ]
];

That’s how my config file will look like, intentionally i had performance key as array for demostration.

Now i want to store these inside the database, and for that i have to create a migration (with or without model), preferably with a controller to keep things clean.

Do the php artisan make:migration SiteSettings -mc, that will generate the migration + the model + the controller

The Migration then should have two columns (option, value) [name them whatever you want].

public function up()
    {
        Schema::create('site_settings', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('option');
            $table->string('value');
            $table->timestamps();
        });
    }

Now here come’s the actual work, we’re going to convert the config of /config/settings.php to flat array then store it as it is in the database, for that i used a snippet from stackoverflow.

 public static function prefixKey($prefix, $array)
    {
        $result = array();
        foreach ($array as $key => $value) {
            if (is_array($value)) {
                $result = array_merge($result, self::prefixKey($prefix . $key . '.', $value));
            } else {
                $result[$prefix . $key] = $value;
            }
        }
        return $result;
    }

That method will flatten the config and makes it compatible with how you usually retrieve keys from Laravel’s config() helper. Let’s say you want to retrieve the title from the config, we usually write it like that: config(‘settings.title’); and for something that is under performance we write it like that: config(‘settings.performance.cache’); but in order to make all this tree as one flat tree you need to use that function prefixKey (). that will make the config array looks like this

array[
'title'=>xxx,
'description=>xxx,
'performance.cache'=>xxx,
'performance.lifetime=>xxx,
];

And that’s how you actually write the config syntax to retrieve something: config(‘performance.lifetime’) and we want to keep it like that.

Now that we made the settings configs flat we can insert them in the database, but before we do and make things too complex let’s do it from the controller through a method we call it init(), and in there we check and set the configs.

    /**
     * Initialize the config
     *
     * @throws \Exception
     */
    public static function init(): void
    {

        # Just in case config('settings') doesn't exist
        if (is_array(config('settings'))) {

            # Create the default setting option if the key doesn't exist in database
            foreach (Helpers::prefixKey('', config('settings')) as $_key => $_value) {
                SiteSettings::firstOrCreate(['option' => $_key], ['value' => $_value]);
            }

            # Retrieve the settings from database
            $Settings = SiteSettings::all()->pluck('value', 'option')->toArray();

            # Update the config helper to retrieve the database values
            # not the default values
            foreach ($Settings as $_option => $_value) {
                config(['settings.' . $_option => $_value]);
            }

        } else {
            throw new \Exception('The config `settings` does not exist.');
        }
        
    }
  • First of all i loaded all the config(‘settings’) from the actual file located in /config/settings.php and made it flat array.
  • Insert SiteSettings DB row using the firstOrCreate because we don’t want to have two identical rows of the same settings. and we don’t want to use the updateOrCreate method because this row will be inserted from the default /config/settings.php key and not updated all the time, that’s how the file there becomes only for defaults and nothing more then it will be inserted in the database for future user updates.
  • Then we retrieve the Settings, make them as array[value=>option], that will make it well formatted to match the config default syntax.
  • Then we set the config(‘settings.*’) to use the database instead of the actual file.

Now for tests, try to to add a line in the actual config/settings.php, for example : ‘test’=>1 and run the init() method, That should add a row of that option in the database, now try to change the value of the test in the /config/settings.php file and try to output it using config(‘settings.test’) it will not show the updated value, but the database value. Try to change the value in the database and that should return the updated value. try to remove the row from the database and refresh, that should re-insert a db row of that missing value with the value set in /config/settings.php.

Now to make this check happens everytime without manually running the init() method, you can include that in the AppServiceProvider using : \App\Http\Controller\SiteSettingsController::init(); or whatever way you prefer.

That’s is, Hope you found this useful.

How to change PHP version in WHM/cPanel

Change your PHP Version in WHM

  • Login to your WHM using the default port 2087.
  • On the left sidebar locate MultiPHP Manager.
  • You will find a tab that says System PHP Version, under that you will find the selected php version for the whole system.
  • Press the Edit button next to it and choose the PHP version you want.
  • In case you cannot find the PHP version you’re looking for, then you will probably need to install it in the EasyApache page first.
  • In case you want to change the PHP version for a specific site, then you will need to scroll down a little and you will find a table which contains all the domains you have on that server. One of the columns contain a PHP Version list, choose one.

How to Change PHP Version from cPanel

  • Login to you cPanel page (usually at port 2083 or example.com/cpanel).
  • If you are allowed to change the PHP Version from your cPanel then you will find MultiPHP Manager, click that. But if you cannot find that Feature then you will need to contact your server’s administrators to change it for you and to enable that feature.
  • You will find a table with the domains you have on that account in case you have more than one domain/subdomain there, select the ones you want to change.
  • On the top you will find a dropdown list which says PHP Version. Choose one then click Apply.