$attributes * @param array $props * @return static */ public static function createWithProps(array $attributes, array $props = []): static { unset($attributes['props']); /** @var static $tenant */ $tenant = DB::transaction(function () use ($attributes, $props): self { /** @var static $createdTenant */ $createdTenant = static::query()->create($attributes); $createdTenant->syncPropValues($props); return $createdTenant; }); return $tenant; } /** * @return HasMany */ public function productos(): HasMany { return $this->hasMany(Product::class, 'tenant_codigo', 'codigo'); } /** * @return HasMany */ public function propValues(): HasMany { return $this->hasMany(TenantPropValue::class, 'tenant_codigo', 'codigo'); } public function getPropValue(TenantProp|string $prop): ?TenantPropValue { $resolvedProp = $this->resolveProp($prop); return $this->propValues() ->where('tenant_prop_codigo', $resolvedProp->codigo) ->first(); } public function setPropValue(TenantProp|string $prop, mixed $value): TenantPropValue { $this->ensurePropValuesCanBeManaged(); $resolvedProp = $this->resolveProp($prop); return $this->propValues()->updateOrCreate( ['tenant_prop_codigo' => $resolvedProp->codigo], ['value' => $value], ); } /** * @param array $props */ public function syncPropValues(array $props): void { foreach ($props as $codigo => $value) { $this->setPropValue((string) $codigo, $value); } } /** * @param array $attributes * @param array $props * @return static */ public function updateWithProps(array $attributes, array $props = []): static { unset($attributes['props']); DB::transaction(function () use ($attributes, $props): void { $this->update($attributes); $this->syncPropValues($props); }); return $this; } protected function ensurePropValuesCanBeManaged(): void { if (! $this->exists) { throw new LogicException('Cannot manage prop values for an unsaved tenant.'); } } protected function resolveProp(TenantProp|string $prop): TenantProp { if ($prop instanceof TenantProp) { return $prop; } return TenantProp::query() ->where('codigo', $prop) ->firstOrFail(); } }