feat: menus 테이블 options JSON 컬럼 추가
- menus 테이블에 options JSON 컬럼 추가 (확장 데이터 저장용) - Menu 모델에 options 헬퍼 메서드 추가 - getOption(), setOption() - getRouteName(), getSection(), getMenuType() - requiresRole(), getBladeComponent(), getCssClass() - getMeta(), setMeta() - JSON 컬럼 기반 스코프 메서드 추가 - scopeSection(), scopeMenuType(), scopeRequiringRole()
This commit is contained in:
@@ -19,7 +19,7 @@ class Menu extends Model
|
|||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'tenant_id', 'parent_id', 'global_menu_id', 'name', 'url', 'is_active', 'sort_order',
|
'tenant_id', 'parent_id', 'global_menu_id', 'name', 'url', 'is_active', 'sort_order',
|
||||||
'hidden', 'is_customized', 'is_external', 'external_url', 'icon',
|
'hidden', 'is_customized', 'is_external', 'external_url', 'icon', 'options',
|
||||||
'created_by', 'updated_by', 'deleted_by',
|
'created_by', 'updated_by', 'deleted_by',
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -35,6 +35,7 @@ class Menu extends Model
|
|||||||
'hidden' => 'boolean',
|
'hidden' => 'boolean',
|
||||||
'is_customized' => 'boolean',
|
'is_customized' => 'boolean',
|
||||||
'is_external' => 'boolean',
|
'is_external' => 'boolean',
|
||||||
|
'options' => 'array',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -135,6 +136,140 @@ public function scopeRoots($query)
|
|||||||
*/
|
*/
|
||||||
public static function getSyncFields(): array
|
public static function getSyncFields(): array
|
||||||
{
|
{
|
||||||
return ['name', 'url', 'icon', 'sort_order', 'is_active', 'hidden', 'is_external', 'external_url'];
|
return ['name', 'url', 'icon', 'sort_order', 'is_active', 'hidden', 'is_external', 'external_url', 'options'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Options JSON 헬퍼 메서드
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* options에서 특정 키 값 조회
|
||||||
|
*/
|
||||||
|
public function getOption(string $key, mixed $default = null): mixed
|
||||||
|
{
|
||||||
|
return data_get($this->options, $key, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* options에 특정 키 값 설정
|
||||||
|
*/
|
||||||
|
public function setOption(string $key, mixed $value): static
|
||||||
|
{
|
||||||
|
$options = $this->options ?? [];
|
||||||
|
data_set($options, $key, $value);
|
||||||
|
$this->options = $options;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 라우트명 조회 (mng, api, react 등에서 사용)
|
||||||
|
*/
|
||||||
|
public function getRouteName(): ?string
|
||||||
|
{
|
||||||
|
return $this->getOption('route_name');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 메뉴 섹션 조회 (main, tools, labs 등)
|
||||||
|
*/
|
||||||
|
public function getSection(): string
|
||||||
|
{
|
||||||
|
return $this->getOption('section', 'main');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 메뉴 타입 조회 (normal, tool, lab 등)
|
||||||
|
*/
|
||||||
|
public function getMenuType(): string
|
||||||
|
{
|
||||||
|
return $this->getOption('menu_type', 'normal');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 필요 역할 조회
|
||||||
|
*/
|
||||||
|
public function getRequiresRole(): ?string
|
||||||
|
{
|
||||||
|
return $this->getOption('requires_role');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 특정 역할이 필요한지 확인
|
||||||
|
*/
|
||||||
|
public function requiresRole(?string $role = null): bool
|
||||||
|
{
|
||||||
|
$requiredRole = $this->getRequiresRole();
|
||||||
|
|
||||||
|
if ($requiredRole === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($role === null) {
|
||||||
|
return true; // 역할이 필요함
|
||||||
|
}
|
||||||
|
|
||||||
|
return $requiredRole === $role;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blade 컴포넌트명 조회
|
||||||
|
*/
|
||||||
|
public function getBladeComponent(): ?string
|
||||||
|
{
|
||||||
|
return $this->getOption('blade_component');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CSS 클래스 조회
|
||||||
|
*/
|
||||||
|
public function getCssClass(): ?string
|
||||||
|
{
|
||||||
|
return $this->getOption('css_class');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta 데이터 조회 (앱별 커스텀 데이터)
|
||||||
|
*/
|
||||||
|
public function getMeta(?string $key = null, mixed $default = null): mixed
|
||||||
|
{
|
||||||
|
if ($key === null) {
|
||||||
|
return $this->getOption('meta', []);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->getOption("meta.{$key}", $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta 데이터 설정
|
||||||
|
*/
|
||||||
|
public function setMeta(string $key, mixed $value): static
|
||||||
|
{
|
||||||
|
return $this->setOption("meta.{$key}", $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 특정 섹션 메뉴만 조회
|
||||||
|
*/
|
||||||
|
public function scopeSection($query, string $section)
|
||||||
|
{
|
||||||
|
return $query->whereJsonContains('options->section', $section);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 특정 메뉴 타입만 조회
|
||||||
|
*/
|
||||||
|
public function scopeMenuType($query, string $type)
|
||||||
|
{
|
||||||
|
return $query->whereJsonContains('options->menu_type', $type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 특정 역할이 필요한 메뉴만 조회
|
||||||
|
*/
|
||||||
|
public function scopeRequiringRole($query, string $role)
|
||||||
|
{
|
||||||
|
return $query->whereJsonContains('options->requires_role', $role);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* menus 테이블에 options JSON 컬럼 추가
|
||||||
|
* - 범용 확장 데이터 저장용 (mng, api, react 등에서 활용 가능)
|
||||||
|
* - nullable이므로 기존 데이터에 영향 없음
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('menus', function (Blueprint $table) {
|
||||||
|
$table->json('options')->nullable()
|
||||||
|
->after('external_url')
|
||||||
|
->comment('확장 옵션 JSON: route_name, section, menu_type, requires_role, meta 등');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('menus', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('options');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user