mirror of
https://github.com/symfony/ux-live-component.git
synced 2026-03-24 00:42:12 +01:00
This PR was squashed before being merged into the 2.x branch. Discussion ---------- [LiveComponent][TwigComponent] Fix reflection issues for private properties from trait and parent class | Q | A | -------------- | --- | Bug fix? | yes | New feature? | no | Deprecations? | no | Documentation? | no | Issues | <!-- none yet --> | License | MIT ## Problem When a component class *extends* another class that uses a trait with `#[ExposeInTemplate]` or `#[LiveProp]` attributes on **private** properties, those attributes are invisible to the metadata scanners. PHP's `ReflectionClass::getProperties()` called on a child class does not return private properties from traits used in *ancestor* classes — they are only returned when `getProperties()` is called on the exact class that declares `use TraitName`. This is standard PHP reflection behaviour. This affects any inheritance pattern where a base component uses `ComponentWithFormTrait` (or any custom trait with private `#[ExposeInTemplate]` properties) and app-level components extend it without re-declaring the trait. **Symptom in `ux-twig-component`:** `Variable "form" does not exist` in the child component's Twig template. **Symptom in `ux-live-component`:** `#[LiveProp(fieldName: 'callable()')]` declared in a trait used by a parent class is not registered with the correct `fieldName` on the child component, causing frontend model key mismatches. ## Fix ### `ux-twig-component` — `ComponentProperties::loadClassMetadata()` Replace the single `$refClass->getProperties()` call with a loop that walks up `getParentClass()`, calling `getProperties()` at each level. Results are deduplicated by property name (child-class declaration takes priority), giving a complete view of all `#[ExposeInTemplate]` properties across the full hierarchy. ### `ux-live-component` — `LiveComponentMetadataFactory::createPropMetadatas()` Pass `$property->getDeclaringClass()->getName()` instead of `$class->getName()` to `createLivePropMetadata()`. When a property is declared in a trait used by a parent class, the type extractor must be given the declaring class — not the leaf child class — to resolve the type correctly. `#[LiveAction]` and `#[LiveListener]` on parent class methods are **not** affected: `getMethods()` already walks the full inheritance chain, so those are discovered correctly on child components. ## Tests Added ``@group` trait-inheritance` tests in both packages using a minimal fixture: a trait with a private `#[ExposeInTemplate]` property / `#[LiveProp(fieldName: callable)]`, a parent component that uses the trait, and a child component that extends the parent without re-declaring the trait. Commits ------- 799736ff76c [LiveComponent][TwigComponent] Fix reflection issues for private properties from trait and parent class