优点:
缺点:
优点:
缺点:
使用 spatie/laravel-settings 作为基础,通过扩展实现多级继承和权限控制功能。
composer require spatie/laravel-settings
<?php
namespace App\Settings;
use Spatie\LaravelSettings\Settings;
class CommissionSettings extends Settings
{
public float $default_rate;
public float $min_rate;
public float $max_rate;
// 定义分组
public static function group(): string
{
return 'commission';
}
}
<?php
namespace App\Services;
use Spatie\LaravelSettings\Settings;
use Illuminate\Support\Facades\Cache;
class HierarchicalSettingsService
{
private const CACHE_PREFIX = 'settings:';
private const CACHE_TTL = 3600;
/**
* 获取设置值(支持多级继承)
*/
public function getValue(string $settingsClass, string $key, string $objectType, int $objectId)
{
$cacheKey = $this->getCacheKey($settingsClass, $key, $objectType, $objectId);
return Cache::remember($cacheKey, self::CACHE_TTL, function () use ($settingsClass, $key, $objectType, $objectId) {
// 1. 查找当前对象的设置
$value = $this->getObjectValue($settingsClass, $key, $objectType, $objectId);
if ($value !== null) {
return $value;
}
// 2. 查找上级对象的设置
$parentObject = $this->getParentObject($objectType, $objectId);
if ($parentObject) {
return $this->getValue(
$settingsClass,
$key,
$parentObject['type'],
$parentObject['id']
);
}
// 3. 返回默认值
return app($settingsClass)->$key;
});
}
/**
* 设置值
*/
public function setValue(string $settingsClass, string $key, string $objectType, int $objectId, $value)
{
// 权限检查
if (!$this->checkPermission($settingsClass, $key, $objectType)) {
throw new \Exception('没有权限修改此设置');
}
// 值范围检查
if (!$this->validateValue($settingsClass, $key, $value, $objectType)) {
throw new \Exception('设置值超出允许范围');
}
// 保存设置
$this->saveObjectValue($settingsClass, $key, $objectType, $objectId, $value);
// 清除缓存
$this->clearCache($settingsClass, $key, $objectType, $objectId);
}
/**
* 获取对象的设置值
*/
private function getObjectValue(string $settingsClass, string $key, string $objectType, int $objectId)
{
return \DB::table('settings')
->where('group', app($settingsClass)->group())
->where('name', $key)
->where('object_type', $objectType)
->where('object_id', $objectId)
->value('payload');
}
/**
* 保存对象的设置值
*/
private function saveObjectValue(string $settingsClass, string $key, string $objectType, int $objectId, $value)
{
\DB::table('settings')->updateOrInsert(
[
'group' => app($settingsClass)->group(),
'name' => $key,
'object_type' => $objectType,
'object_id' => $objectId,
],
[
'payload' => $value,
'updated_at' => now(),
]
);
}
/**
* 获取上级对象
*/
private function getParentObject(string $objectType, int $objectId): ?array
{
// 实现获取上级对象的逻辑
// 例如: COACH -> SHOP -> AGENT -> PLATFORM
switch ($objectType) {
case 'COACH':
$shopId = \DB::table('coaches')
->where('id', $objectId)
->value('shop_id');
return $shopId ? ['type' => 'SHOP', 'id' => $shopId] : null;
case 'SHOP':
$agentId = \DB::table('shops')
->where('id', $objectId)
->value('agent_id');
return $agentId ? ['type' => 'AGENT', 'id' => $agentId] : null;
case 'AGENT':
return ['type' => 'PLATFORM', 'id' => 0];
default:
return null;
}
}
/**
* 检查权限
*/
private function checkPermission(string $settingsClass, string $key, string $objectType): bool
{
// 实现权限检查逻辑
return true;
}
/**
* 验证值范围
*/
private function validateValue(string $settingsClass, string $key, $value, string $objectType): bool
{
// 实现值范围验证逻辑
return true;
}
/**
* 获取缓存键
*/
private function getCacheKey(string $settingsClass, string $key, string $objectType, int $objectId): string
{
return self::CACHE_PREFIX . "{$settingsClass}:{$key}:{$objectType}:{$objectId}";
}
/**
* 清除缓存
*/
private function clearCache(string $settingsClass, string $key, string $objectType, int $objectId)
{
Cache::forget($this->getCacheKey($settingsClass, $key, $objectType, $objectId));
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::create('settings', function (Blueprint $table) {
$table->id();
$table->string('group');
$table->string('name');
$table->string('object_type');
$table->unsignedBigInteger('object_id');
$table->text('payload');
$table->timestamps();
$table->unique(['group', 'name', 'object_type', 'object_id']);
});
Schema::create('setting_permissions', function (Blueprint $table) {
$table->id();
$table->string('group');
$table->string('name');
$table->string('object_type');
$table->boolean('can_edit')->default(false);
$table->json('constraints')->nullable();
$table->timestamps();
$table->unique(['group', 'name', 'object_type']);
});
}
};
<?php
namespace App\Http\Controllers;
use App\Settings\CommissionSettings;
use App\Services\HierarchicalSettingsService;
class SettingsController extends Controller
{
private $settingsService;
public function __construct(HierarchicalSettingsService $settingsService)
{
$this->settingsService = $settingsService;
}
/**
* 获取分佣比例
*/
public function getCommissionRate($coachId)
{
$rate = $this->settingsService->getValue(
CommissionSettings::class,
'default_rate',
'COACH',
$coachId
);
return response()->json(['rate' => $rate]);
}
/**
* 设置分佣比例
*/
public function setCommissionRate($coachId, Request $request)
{
$this->settingsService->setValue(
CommissionSettings::class,
'default_rate',
'COACH',
$coachId,
$request->input('rate')
);
return response()->json(['message' => '设置成功']);
}
}
<?php
namespace App\Settings\Validators;
class CommissionSettingsValidator
{
public function validateDefaultRate($value, $objectType)
{
$constraints = [
'PLATFORM' => ['min' => 0, 'max' => 1],
'AGENT' => ['min' => 0.1, 'max' => 0.9],
'SHOP' => ['min' => 0.2, 'max' => 0.8],
'COACH' => ['min' => 0.3, 'max' => 0.7],
];
if (!isset($constraints[$objectType])) {
return false;
}
return $value >= $constraints[$objectType]['min']
&& $value <= $constraints[$objectType]['max'];
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class SettingLog extends Model
{
protected $fillable = [
'group',
'name',
'object_type',
'object_id',
'old_value',
'new_value',
'operator_id',
'operator_type'
];
}
<?php
namespace App\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
class SettingsExport implements FromCollection
{
private $objectType;
private $objectId;
public function __construct($objectType, $objectId)
{
$this->objectType = $objectType;
$this->objectId = $objectId;
}
public function collection()
{
return \DB::table('settings')
->where('object_type', $this->objectType)
->where('object_id', $this->objectId)
->get();
}
}