You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feature #1090 [LiveComponent] Implement hydratation of DTO object (matheo, WebMamba)
This PR was merged into the 2.x branch.
Discussion
----------
[LiveComponent] Implement hydratation of DTO object
| Q | A
| ------------- | ---
| Bug fix? | yes
| New feature? | no
| Tickets | Fix#955
| License | MIT
With this PR you van easily use DTO with your LiveComponents.
```php
class CustomerDetails
{
public string $name;
public Address $address;
public string $city;
}
```
```php
class Address
{
public string $street;
public string $postCode;
}
```
```php
#[AsLiveComponent(name: 'CustomerDetails')]
class CustomerDetailsComponent
{
use DefaultActionTrait;
#[ExposeInTemplate]
public string $hello = 'hello';
#[LiveProp(writable: true)]
public ?CustomerDetails $customerDetails = null;
public function mount(): void
{
$this->customerDetails = new CustomerDetails();
$this->customerDetails->name = 'Matheo';
$this->customerDetails->city = 'Paris';
$this->customerDetails->address = new Address();
$this->customerDetails->address->street = '3 rue de la Paix';
$this->customerDetails->address->postCode = '92270';
}
#[LiveAction]
public function switch(): void
{
$this->customerDetails = new CustomerDetails();
$this->customerDetails->name = 'Paul';
$this->customerDetails->city = 'Paris';
$this->customerDetails->address = new Address();
$this->customerDetails->address->street = '3 rue des mimosas';
$this->customerDetails->address->postCode = '92270';
}
}
```
```twig
<div {{ attributes }}>
<p>{{ customerDetails.name }}</p>
<p>{{ customerDetails.address.street }}</p>
<button
data-action="live#action"
data-action-name="switch"
>Switch</button>
</div>
```
Commits
-------
970ba16 fix Doc ci
ba53343 fix exeception and use PropertyAccessor to read the value
6e4854d Update docs
feb1f44 rewrite errors and renames variable
28e3b39 edit error message
30d4fdb add doc
9d738d6 refactoring and renaming
11b9210 Remove checksum in tests
7595c70 Tests and centralize logic in LiveComponentMetadataFactory
bd7e719 use LiveComponentMetadataFactory logic to generate LivePropMetadata
bac591e Implement hydratation of DTO object
thrownew \LogicException(sprintf('The LiveProp "%s" on component "%s" is an array. We determined the array is full of %s objects, but at least on key had a different value of %s', $propMetadata->getName(), $component::class, $collectionClass, get_debug_type($objectItem)));
357
+
thrownew \LogicException(sprintf('The LiveProp "%s" on component "%s" is an array. We determined the array is full of %s objects, but at least on key had a different value of %s', $propMetadata->getName(), $parentObject::class, $collectionClass, get_debug_type($objectItem)));
thrownew \LogicException(sprintf('The LiveProp "%s" on component "%s" is an array, but it contains one or more keys that are not scalars: %s', $propMetadata->getName(), $component::class, $badKeysText));
367
+
thrownew \LogicException(thrownew \LogicException(sprintf('Unable to dehydrate value of type "%s" for property "%s" on component "%s". Change this to a simpler type of an object that can be dehydrated. Or set the hydrateWith/dehydrateWith options in LiveProp or set "useSerializerForHydration: true" on the LiveProp to use the serializer.', get_debug_type($value), $propMetadata->getName(), $parentObject::class)));
365
368
}
366
369
367
370
return$value;
368
371
}
369
372
370
373
if (!\is_object($value)) {
371
-
thrownew \LogicException(sprintf('Unable to dehydrate value of type "%s" for property "%s" on component "%s". Change this to a simpler type of an object that can be dehydrated. Or set the hydrateWith/dehydrateWith options in LiveProp or set "useSerializerForHydration: true" on the LiveProp to use the serializer.', get_debug_type($value), $propMetadata->getName(), $component::class));
374
+
thrownew \LogicException(sprintf('Unable to dehydrate value of type "%s" for property "%s" on component "%s". Change this to a simpler type of an object that can be dehydrated. Or set the hydrateWith/dehydrateWith options in LiveProp or set "useSerializerForHydration: true" on the LiveProp to use the serializer.', get_debug_type($value), $propMetadata->getName(), $parentObject::class));
372
375
}
373
376
374
377
if (!$propMetadata->getType() || $propMetadata->isBuiltIn()) {
375
-
thrownew \LogicException(sprintf('The "%s" property on component "%s" is missing its property-type. Add the "%s" type so the object can be hydrated later.', $propMetadata->getName(), $component::class, $value::class));
378
+
thrownew \LogicException(sprintf('The "%s" property on component "%s" is missing its property-type. Add the "%s" type so the object can be hydrated later.', $propMetadata->getName(), $parentObject::class, $value::class));
376
379
}
377
380
378
381
// at this point, we have an object and can assume $propMetadata->getType()
thrownew \LogicException(sprintf('Unable to dehydrate value of type "%s" for property "%s" on component "%s". Either (1) change this to a simpler value, (2) add the hydrateWith/dehydrateWith options to LiveProp or (3) set "useSerializerForHydration: true" on the LiveProp.', $value::class, $propertyPathForError, $componentClassForError));
if (!method_exists($component, $propMetadata->hydrateMethod())) {
407
-
thrownew \LogicException(sprintf('The "%s" component has a hydrateMethod of "%s" but the method does not exist.', $component::class, $propMetadata->hydrateMethod()));
416
+
if (!method_exists($parentObject, $propMetadata->hydrateMethod())) {
417
+
thrownew \LogicException(sprintf('The "%s" object has a hydrateMethod of "%s" but the method does not exist.', $parentObject::class, $propMetadata->hydrateMethod()));
thrownewHydrationException(sprintf('Unable to hydrate value of type "%s" for property "%s" on component "%s". Change this to a simpler value, add the hydrateWith/dehydrateWith options to LiveProp or set "useSerializerForHydration: true" on the LiveProp to use the serializer..', $className, $propertyPathForError, $componentClassForError));
thrownewHydrationException(sprintf('Unable to hydrate value of type "%s" for property "%s" on component "%s". it looks like something went wrong by trying to guess your property types.', $className, $propertyPathForError, $componentClassForError));
if ($typeinstanceof \ReflectionUnionType || $typeinstanceof \ReflectionIntersectionType) {
75
-
thrownew \LogicException(sprintf('Union or intersection types are not supported for LiveProps. You may want to change the type of property %s in %s.', $property->getName(), $property->getDeclaringClass()->getName()));
if ($typeinstanceof \ReflectionUnionType || $typeinstanceof \ReflectionIntersectionType) {
83
+
thrownew \LogicException(sprintf('Union or intersection types are not supported for LiveProps. You may want to change the type of property %s in %s.', $property->getName(), $property->getDeclaringClass()->getName()));
0 commit comments