Инстанцирование объектов
Без конструктора
Если в классе не определён конструктор, Speca заполняет публичные свойства непосредственно из массива входных данных.
class User extends Data {
public string $name;
public int $age;
}
$data = [
'name' => 'John Doe',
'age' => 30,
];
$user = User::from($data);
С конструктором
Если в классе определён конструктор, то он будет инициализирован свойствами из входного массива с соответствующим (возможно, "смапленым" через ParseFrom
) именем одного из его аргументов.
Источники данных
На данный момент поддерживается инстанцирование объектов из двух типов данных: массивы и Data-объекты.
Если на входе поступает Data-объект, он будет преобразован в массив с применением соответствующих правил.
Вложенность данных
Speca поддерживает вложенные данные, позволяя создавать сложные агрегаты, включающие в себя другие объекты.
use Looqey\Speca\Data;
class Percent extends ScalarValue {
}
class ScalarValueParser implements Transformer {
public function transform(mixed $value, Property $property): mixed {
// Реализуем парсинг скалярного ValueObject
// - для этого найдем в свойстве тип, отвечающий требованию
$types = $property->getTypes();
foreach ($types as $type) {
if (is_subclass_of($type, ScalarValue::class)) {
//Нашли тип, расширяющий значение - вернем значение, завернутое в него
return new $type($value);
}
}
// Не смогли найти нужный тип. Можно выбросить исключение,
// а можно вернуть значение, если после этого парсера вы разместите другой,
// который попробует привести значение к другой группе типов (если это потребуется)
throw new \Exception("No ScalarValue childs were declared in $property->name");
}
}
class SpecialDiscount extends Data {
public function __construct(
#[ParseBy(ScalarValueParser::class)]
public Percent $amount,
public array $category_ids
) {}
}
class UserDiscountAggregate extends Data {
public function __construct(
public User $user,
public ?SpecialDiscount $discount = null
) {}
}
Входные данные могут быть как обычными массивами, так и Data-объектами:
$data = [
'user' => [
'name' => 'John Doe',
'age' => 25
],
'discount' => [
'amount' => 10,
'category_ids' => [1, 2, 3]
]
];
$agg = UserDiscountAggregate::from($data);