Issue
I am currently using Laravel 5.2. I want to be able to store config properties (key-value pairs) in database, that I am willing to access from both my application on runtime and the console (either php artisan
command or Tinker
).
What is my best option?
.env
is one way, but it is not stored in the database, but in a file.Config::get
is another way, but it also writes in files. Can it be configured to write in database?Cache::get
is setup to work with the database, but is temporary, not permanent, so it is out of question.
The reason I am interested in database config, is because we often replace/delete files during deployment. Also it would be nice to store values encrypted. Also important feature here is to be able to easily get values via either php artisan
or tinker
Solution
- Make a migration:
php artisan make:migration CreateSettingsTable
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateSettingsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('settings', function (Blueprint $table) {
$table->id();
$table->string('key');
$table->string('value');
$table->timestamps();
$table->unique([
'key', //I add a unique to prevent double keys
]);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('settings');
}
}
- Make the model:
php artisan make:model Setting
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Setting extends Model
{
protected $fillable = [
'key',
'value'
];
//I would normally do this in a repository,
// but for simplicity sake, i've put it in here :)
static public $settings = null;
static function get($key, $default = null)
{
if (empty(self::$settings)) {
self::$settings = self::all();
}
$model = self
::$settings
->where('key', $key)
->first();
if (empty($model)) {
if (empty($default)) {
//Throw an exception, you cannot resume without the setting.
throw new \Exception('Cannot find setting: '.$key);
}
else {
return $default;
}
}
else {
return $model->value;
}
}
static function set(string $key, $value)
{
if (empty(self::$settings)) {
self::$settings = self::all();
}
if (is_string($value) || is_int($value)) {
$model = self
::$settings
->where('key', $key)
->first();
if (empty($model)) {
$model = self::create([
'key' => $key,
'value' => $value
]);
self::$settings->push($model);
}
else {
$model->update(compact('value'));
}
return true;
}
else {
return false;
}
}
}
Please note here, that I added the get and set functions, together with a static $settings
variable directly to the model, to keep the example small. Usually I would opt to making a repository or service(not serviceprovider) to handle these functions. This way you only query db once(per request) for all the settings. You could stick this in cache, but that is not part of this answer of now.
Run
php artisan migrate
to ge the table in the db.Run
composer dump-autoload
to make sure tinker can find theSetting
class.Use someting like
php artisan tinker
(https://laravel.com/docs/7.x/artisan#tinker) to test it, in this case you can do:
Setting::set('someKey', 'someValue'); //Set someKey to someValue
Setting::get('someKey'); //Get someKey, throws exception if not found
Setting::get('somekey2', 'someDefault'); //Shows someDefault because somekey2 is not set yet.
I hope it helps! :)
Answered By - Rob Biermann
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.