Laravel: Loading the settings from the database

For any project, an .env
file is preferred over anything else. But this file is referred as “The Environment” for the whole application. When an app must be configurable by the end user, it’s better to hold the configuration in other parts of the Application, like on the database.
Okay, you may argue that using a static file located somewhere (and editing that instead) could be better for storing the application settings than the database, leaving this for the real data itself. SQLite could help here if you don’t want to tamper with your main database, knowing current benchmarks of SQLite are not that kick in the balls against other RDBMS.
For this example I will stick to the “same Database” solution, which is quite simple.
Settings? What settings?
Let’s say in our Podcast webapp we need to pull out a settings list about if we want to show a global alert in the site, for example, to warn about a maintenance time, a new show, etc.
We need to add a settings with the warn text. If the text is empty, then no warning will be shown, since there is no point in showing an empty alert.
For that reason I will create an Eloquent Model called “Setting”, with a migration, and then I will add columns “name” and “value”, the latter being nullable.
php artisan make:model Setting --migration
After adding the columns in the migration file, I will add the settings that I want. In this case, the global alert. I did it inside one of my Database Seeders:
Setting::create([ ‘name’ => ‘global_alert’, ‘value’ => null ]);
Quite straightforward. Now, the magic.
Adding the settings to the global config
Laravel includes a handy function called config()
, which holds a class with a lot of settings so every Service that your application boots, like Cache, Database, etc. can pull its own configuration data.
The neat thing about this function is that it works as a getter if you only input a string with dot notation or absolutely nothing, and as a setter if you input an array.
So, we are going to open AppServiceProvider
and tell Laravel that, when the App boots, which is after all other Services are already registered, we are gonna add to the config array our own settings.
/** * Bootstrap any application services. * * @return void */ public function boot() { config([ 'global' => Setting:all([ 'name','value' ]) ->keyBy('name') // key every setting by its name ->transform(function ($setting) { return $setting->value // return only the value }) ->toArray() // make it an array ]) // ... }
Then the config will be added to the list, something you can check by dd(config())
after the boot method or anywhere.
That’s basically it. Of course, you could:
- Use the
DB
facade directly to avoid the Eloquent Model overhead (unless you are storing arrays or json, which you will have to convert them manually, I’m sure). - Add a column named “group” which will allow you to group sub-settings using, and then use
groupBy
after retrieving all the items. Or play with dot notation. - Use SQLite with just using the “connection” property of the Eloquent Model or the “connection” method when using
DB
facade directly. - Make your own
ServiceProvider
to load the configs to be part of the booting process of your application. - Add a boolean column telling if it’s global, and query only those who are true, leaving the rest for later.
You can do a lot to put your own settings here inside the config. Or you can use the Fluent class for more advanced (and time-saving) things.
Bonus: Adding the warning
In your hypothetically present HomeController
, I will check if the alert exists and if it’s empty before passing it to the view.
/** * Show the application dashboard. * * @return \Illuminate\Http\Response */ public function index() { $globalAlert = config('settings.global_alert'); return view('home', [ 'globalAlert' => $globalAlert ]); }
Then in some place high up the I will add an if
clause. PHP considers null
as false
, so if there is even a tiny dot on the value, it will considered as true
.
@if($globalAlert) {{ $globalAlert }} @endif
That’s pretty much it. Any other way, just it the comments.
/
/
0 Comments
Add a comment