feat(form-builder): form_field_bindings table + polymorphic owner + cascade observer
WS-5a commit 1 of 4 per ARCH-CONSOLIDATION-ADDENDUM-2026-04-24 Q3. Creates the relational home for what was form_fields.binding JSON and form_field_library.default_binding JSON. Owner discriminator is polymorphic morph (owner_type/owner_id) — the pattern the rest of WS-5 (5b validation_rules, 5d options) will reuse. Migration backfills rows from both JSON sources in a single transaction and is genuinely reversible (rollback reconstructs the JSON). Old columns remain in place until commit 3 has switched all readers. Pattern B (binding=null) is represented by absence of row. mode enum covers entity_owned / mirrored only. Cascade on owner delete via observer — bindings are physical state, not historical audit. FormFieldBindingScope enforces multi-tenancy via UNION over both owner chains (form_field → schema → org OR form_field_library → org) — Q2's declarative tenantScopeStrategy() can't walk morph parents. Tests: migration forward/back, morph relation, cascade observer, scope isolation, enum coverage. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Observers\FormBuilder;
|
||||
|
||||
use App\Models\FormBuilder\FormField;
|
||||
use App\Models\FormBuilder\FormFieldLibrary;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* Cascade deletion of `form_field_bindings` rows when their polymorphic
|
||||
* owner is deleted. Bindings represent current state (not historical
|
||||
* intent) — they are physically deleted even when the owner is only
|
||||
* soft-deleted, which matches the Q3 decision that bindings have no
|
||||
* soft-delete semantic of their own.
|
||||
*/
|
||||
final class FormFieldBindingsCascadeObserver
|
||||
{
|
||||
public function deleted(FormField|FormFieldLibrary $owner): void
|
||||
{
|
||||
$ownerType = $owner instanceof FormField ? 'form_field' : 'form_field_library';
|
||||
|
||||
DB::table('form_field_bindings')
|
||||
->where('owner_type', $ownerType)
|
||||
->where('owner_id', $owner->getKey())
|
||||
->delete();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user