Files
sam-api/app/Models/ItemMaster/EntityRelationship.php

192 lines
4.7 KiB
PHP
Raw Normal View History

<?php
namespace App\Models\ItemMaster;
use App\Traits\BelongsToTenant;
use App\Traits\ModelTrait;
use Illuminate\Database\Eloquent\Model;
/**
* EntityRelationship - 엔티티 관계를 관리하는 링크 테이블 모델
*
* 지원하는 관계 유형:
* - page-section: 페이지와 섹션 연결
* - page-field: 페이지와 필드 직접 연결
* - section-field: 섹션과 필드 연결
* - section-bom: 섹션과 BOM 항목 연결
*/
class EntityRelationship extends Model
{
use BelongsToTenant, ModelTrait;
protected $fillable = [
'tenant_id',
'group_id',
'parent_type',
'parent_id',
'child_type',
'child_id',
'order_no',
'metadata',
'created_by',
'updated_by',
];
protected $casts = [
'group_id' => 'integer',
'parent_id' => 'integer',
'child_id' => 'integer',
'order_no' => 'integer',
'metadata' => 'array',
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
// 엔티티 타입 상수
public const TYPE_PAGE = 'page';
public const TYPE_SECTION = 'section';
public const TYPE_FIELD = 'field';
public const TYPE_BOM = 'bom';
// 그룹 ID 상수
public const GROUP_ITEM_MASTER = 1;
/**
* 부모 엔티티 조회 (Polymorphic)
*/
public function parent()
{
return $this->morphTo('parent', 'parent_type', 'parent_id');
}
/**
* 자식 엔티티 조회 (Polymorphic)
*/
public function child()
{
return $this->morphTo('child', 'child_type', 'child_id');
}
/**
* 부모 타입에 따른 모델 클래스 반환
*/
public static function getModelClass(string $type): ?string
{
return match ($type) {
self::TYPE_PAGE => ItemPage::class,
self::TYPE_SECTION => ItemSection::class,
self::TYPE_FIELD => ItemField::class,
self::TYPE_BOM => ItemBomItem::class,
default => null,
};
}
/**
* 특정 부모의 자식 관계 조회
*/
public static function getChildren(string $parentType, int $parentId, ?string $childType = null)
{
$query = self::where('parent_type', $parentType)
->where('parent_id', $parentId)
->orderBy('order_no');
if ($childType) {
$query->where('child_type', $childType);
}
return $query;
}
/**
* 특정 자식의 부모 관계 조회
*/
public static function getParents(string $childType, int $childId, ?string $parentType = null)
{
$query = self::where('child_type', $childType)
->where('child_id', $childId);
if ($parentType) {
$query->where('parent_type', $parentType);
}
return $query;
}
/**
* 관계 생성 또는 업데이트
*/
public static function link(
int $tenantId,
string $parentType,
int $parentId,
string $childType,
int $childId,
int $orderNo = 0,
?array $metadata = null,
int $groupId = self::GROUP_ITEM_MASTER
): self {
return self::updateOrCreate(
[
'tenant_id' => $tenantId,
'group_id' => $groupId,
'parent_type' => $parentType,
'parent_id' => $parentId,
'child_type' => $childType,
'child_id' => $childId,
],
[
'order_no' => $orderNo,
'metadata' => $metadata,
]
);
}
/**
* 관계 해제
*/
public static function unlink(
int $tenantId,
string $parentType,
int $parentId,
string $childType,
int $childId,
int $groupId = self::GROUP_ITEM_MASTER
): bool {
return self::where([
'tenant_id' => $tenantId,
'group_id' => $groupId,
'parent_type' => $parentType,
'parent_id' => $parentId,
'child_type' => $childType,
'child_id' => $childId,
])->delete() > 0;
}
/**
* 특정 부모의 모든 자식 관계 해제
*/
public static function unlinkAllChildren(
int $tenantId,
string $parentType,
int $parentId,
?string $childType = null,
int $groupId = self::GROUP_ITEM_MASTER
): int {
$query = self::where([
'tenant_id' => $tenantId,
'group_id' => $groupId,
'parent_type' => $parentType,
'parent_id' => $parentId,
]);
if ($childType) {
$query->where('child_type', $childType);
}
return $query->delete();
}
}