I have updated my site settings function to allow for casting settings as their data type. Due to all settings being stored in the database as a string, some people will need use of storing user boolean settings like receive_notification_emails etc.
// UserSettingsTrait
<?php namespace App\cablework\_Traits;
use App\cablework\Models\Settings;
use Cache;
trait UserSettingsTrait {
// get setting value
public function getSetting($key)
{
$settings = $this->getCache();
$data = $this->searchSetting($key, $settings);
$value = $data['value'];
$type = $data['type'];
switch($type) {
case 'string':
return (string) $value;
case 'boolean':
return (bool) $value;
case 'integer':
return (int) $value;
}
}
private function searchSetting($key, $array, $column = 'key')
{
foreach ($array as $k => $val) {
if ($val[$column] == $key) {
return $val;
}
}
return null;
}
// create-update setting
public function setSetting($key, $value, $type = 'string')
{
$this->storeSetting($key, $value, $type);
$this->setCache();
}
// create-update multiple settings at once
public function setSettings($data = [])
{
foreach($data as $setting)
{
$key = $setting['key'];
$value = $setting['value'];
$type = isset($setting['type']) ? $setting['type'] : 'string';
$this->storeSetting($key, $value, $type);
}
$this->setCache();
}
private function storeSetting($key, $value, $type)
{
$record = Settings::where(['user_id' => $this->id, 'key' => $key])->first();
if($record)
{
$record->value = $value;
$record->type = $type;
$record->save();
} else {
$data = new Settings(['key' => $key, 'value' => $value, 'type' => $type]);
$this->settings()->save($data);
}
}
private function getCache()
{
if (Cache::has('user_settings_' . $this->id))
{
return Cache::get('user_settings_' . $this->id);
}
return $this->setCache();
}
private function setCache()
{
if (Cache::has('user_settings_' . $this->id))
{
Cache::forget('user_settings_' . $this->id);
}
$settings = Settings::where('user_id',$this->id)->get()->toArray();
Cache::forever('user_settings_' . $this->id, $settings);
return $this->getCache();
}
}
// settings table migration
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateSettingsTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('settings', function(Blueprint $table)
{
$table->bigIncrements('id');
$table->bigInteger('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
$table->string('key');
$table->string('value');
$table->string('type');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function(Blueprint $table)
{
$table->dropForeign('settings_user_id_foreign');
});
Schema::drop('settings');
}
}
// Settings Model
<?php namespace App\cablework\Models;
use Illuminate\Database\Eloquent\Model;
class Settings extends Model {
protected $fillable = ['key','value','type'];
public function user()
{
return $this->belongsTo('App\cablework\Models\User', 'id');
}
}
Example usage
$array = [
[
'key' => 'first_name',
'value' => 'John'
],
[
'key' => 'last_name',
'value' => 'Smith'
],
[
'key' => 'age',
'value' => 20,
'type' => 'integer'
],
[
'key' => 'receive_notification_emails',
'value' => 1, // or true
'type' => 'boolean'
]
];
// $user is User object - no third parameter means default 'string'
$user->setSettings($array);
// set a single setting - no third parameter means default 'string'
$user->setSetting('first_name','John');
$user->setSetting('profile_is_public',1,'boolean'); // or ('profile_is_public',true,'boolean') or 0 / false
if($user->getSetting('receive_notification_emails')) // returns boolean true, if not set, returns null
{
// Send user notification email
}
Just for those needing extra functionality. I am sure there is more than one way to do settings but this works for me.