You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
84 lines
2.7 KiB
84 lines
2.7 KiB
<?php
|
|
namespace App\Livewire\Concerns;
|
|
|
|
use BackedEnum;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Support\Collection;
|
|
use ReflectionException;
|
|
use ReflectionProperty;
|
|
|
|
trait HasModelFill
|
|
{
|
|
/**
|
|
* Override Livewire Form's native fill method.
|
|
* Safely hydrates attributes and automatically handles Collection <-> Array and BackedEnum conversions.
|
|
*
|
|
* @param mixed $values Data array or Eloquent Model instance.
|
|
* @return void
|
|
* @throws ReflectionException
|
|
*/
|
|
public function fill(mixed $values = []): void
|
|
{
|
|
$data = $values instanceof Model ? $values->attributesToArray() : (array) $values;
|
|
|
|
foreach (get_object_vars($this) as $property => $defaultValue) {
|
|
$hasModelValue = $values instanceof Model && isset($values->{$property});
|
|
|
|
if (! array_key_exists($property, $data) && ! $hasModelValue) {
|
|
continue;
|
|
}
|
|
|
|
$value = $values instanceof Model ? $values->{$property} : $data[$property];
|
|
|
|
$refProperty = new ReflectionProperty($this, $property);
|
|
$type = $refProperty->getType();
|
|
|
|
if($type) {
|
|
$typeName = null;
|
|
if ($type instanceof \ReflectionNamedType) {
|
|
$typeName = $type->getName();
|
|
} elseif ($type instanceof \ReflectionUnionType) {
|
|
$typeName = (string) $type;
|
|
}
|
|
|
|
if ($typeName === 'array' && $value instanceof Collection) {
|
|
$value = $value->toArray();
|
|
}
|
|
|
|
if (($typeName === Collection::class || is_subclass_of($typeName, Collection::class)) && is_array($value)) {
|
|
$value = collect($value);
|
|
}
|
|
|
|
if (enum_exists($typeName) && ! ($value instanceof BackedEnum) && $value !== null) {
|
|
$value = $typeName::tryFrom((string) $value);
|
|
}
|
|
}
|
|
|
|
// Assign hydrated value back to the Form property
|
|
$this->{$property} = $value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Dehydrate form properties into a clean array representation suitable for DTOs or Models.
|
|
* Converts Collections to arrays and Enums to primitive values.
|
|
*
|
|
* @return array<string, mixed>
|
|
*/
|
|
public function toModelArray(): array
|
|
{
|
|
$result = [];
|
|
|
|
foreach (get_object_vars($this) as $property => $value) {
|
|
if ($value instanceof Collection) {
|
|
$result[$property] = $value->toArray();
|
|
} elseif ($value instanceof BackedEnum) {
|
|
$result[$property] = $value->value;
|
|
} else {
|
|
$result[$property] = $value;
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
}
|
|
|