Hey there -- thanks for the plugin! As the title says, the plugin currently does not recognise Twig stuff when defined via PHP instead of YAML config. I had my agent trace it down, so the below is AI summarised. I would love to help with a PR, but I am not at all familiar with this. So I figured before I send slop I let my agent prepare you a prompt for implementing the missing functionality. You can find it at the bottom under Agent Prompt.
From my agent...
Problem
Symfony UX Twig Component support currently works when twig_component.defaults is configured in YAML, but does not work reliably when the same config is provided through PHP config.
At Symfony runtime, both config styles are equivalent: the PHP config is normalized, compiled, and present in the generated container. However, PhpStorm/Symfony plugin component indexing appears to depend on source-level YAML config for component namespace discovery.
This means projects using PHP config for TwigComponent defaults can have working Symfony runtime behavior, working generated container XML, and working debug:twig-component, while the IDE still fails to resolve/navigate <twig:...> components unless duplicate YAML config is added.
Proof & Trace
Symfony setup:
// config/services.php
$container->extension('twig', [
'paths' => [
'%kernel.project_dir%/src/Shared/Ui/Web/Component' => 'Shared',
'%kernel.project_dir%/src/History/Ui/Web/Component' => 'History',
],
]);
$container->extension('twig_component', [
'defaults' => [
'App\\Shared\\Ui\\Web\\Component\\' => [
'template_directory' => '@Shared',
],
'App\\History\\Ui\\Web\\Component\\' => [
'template_directory' => '@History',
],
],
'anonymous_template_directory' => 'components',
]);
Example component:
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
#[AsTwigComponent('PageIntro', template: '@Shared/PageIntro/page-intro.html.twig')]
final class PageIntroComponent
{
public PageIntro $pageIntro;
}
Runtime works:
php bin/console debug:twig-component PageIntro
returns the expected component:
Name PageIntro
Class App\Shared\Ui\Web\Component\PageIntro\PageIntroComponent
Template @Shared/PageIntro/page-intro.html.twig
The compiled container XML also contains useful component data, for example:
<tag name="twig.component" key="PageIntro" template="@Shared/PageIntro/page-intro.html.twig"/>
and the generated component factory contains the resolved map:
'PageIntro' => [
'key' => 'PageIntro',
'template' => '@Shared/PageIntro/page-intro.html.twig',
'class' => 'App\\Shared\\Ui\\Web\\Component\\PageIntro\\PageIntroComponent',
]
But IDE support for <twig:PageIntro> only starts working after adding equivalent YAML config:
twig:
paths:
'%kernel.project_dir%/src/Shared/Ui/Web/Component': Shared
'%kernel.project_dir%/src/History/Ui/Web/Component': History
twig_component:
defaults:
'App\Shared\Ui\Web\Component\':
template_directory: '@Shared'
'App\History\Ui\Web\Component\':
template_directory: '@History'
anonymous_template_directory: components
Code trace from the installed plugin:
UxTemplateStubIndex indexes PHP files and finds #[AsTwigComponent].
UxUtil.getAllComponentNames() filters indexed PHP component classes through UxUtil.getNamespaces().
UxUtil.getNamespacesInner() reads only ConfigStubIndex entries named twig_component_defaults.
ConfigStubIndex only indexes YAML files. Its input filter checks YAMLFileType.YML.
UxComponentTemplateFinderParser reads compiled XML, but only for ux.twig_component.component_template_finder / anonymous template directories. It does not appear to read twig.component service tags or namespace defaults from the compiled container.
So the plugin already reads PHP attributes, and it already reads some compiled XML, but named component namespace discovery still appears YAML-only.
Expected Behavior
Projects using PHP Symfony config should receive the same UX Twig Component IDE support as projects using YAML config.
If the generated container XML exposes twig.component tags or the component factory map, the plugin should be able to discover named components without requiring duplicated YAML config.
At minimum, explicitly named components such as this should be resolvable without namespace-default discovery:
#[AsTwigComponent('PageIntro', template: '@Shared/PageIntro/page-intro.html.twig')]
because the public component name and template are already provided by the attribute.
Agent Prompt
You are working in the `Haehnchen/idea-php-symfony2-plugin` repository. Please improve Symfony UX Twig Component support so projects using PHP Symfony config for `twig_component.defaults` work without duplicate YAML config.
Current behavior to preserve:
- Existing YAML-based `twig_component.defaults` support must keep working.
- Existing `<twig:ComponentName>` completion/navigation must keep working.
- Existing `{{ component('ComponentName') }}` and `{% component ComponentName %}` support must keep working.
- Existing named-prefix behavior must keep working.
- Existing anonymous component template directory support must keep working.
- Existing tests around `UxUtil`, `UxTemplateStubIndex`, HTML tag navigation, and Twig completion must keep passing.
Problem to fix:
- `UxUtil.getNamespacesInner()` currently depends on `ConfigStubIndex` entries named `twig_component_defaults`.
- `ConfigStubIndex` only indexes YAML files.
- PHP-configured `twig_component.defaults` works at Symfony runtime and appears in the compiled container, but the plugin does not use that data for named component discovery.
Please add support beside the existing YAML path, not instead of it.
Suggested implementation direction:
1. Add a compiled-container parser for Symfony UX Twig components.
Parse services tagged with `twig.component` from configured Symfony container XML files.
For each service with tag:
```xml
<tag name="twig.component" key="PageIntro" template="@Shared/PageIntro/page-intro.html.twig"/>
```
collect:
- component name from tag attribute `key`
- template from tag attribute `template`
- PHP class from service attribute `class`, when available
- service id as fallback if it is a class-like service id
2. Expose this parsed data to UX component lookup.
The plugin already has `ServiceXmlParserFactory` and XML parsers such as `UxComponentTemplateFinderParser`. Add a focused parser, for example:
```text
UxComponentServiceParser
```
returning component entries:
```text
name
phpClass
template
```
3. Merge XML-derived component entries with existing indexed PHP/YAML-derived entries.
`UxUtil.getAllComponentNames()` should include:
- current PHP attribute index + YAML namespace behavior
- compiled-container `twig.component` entries
Avoid duplicates. Prefer explicit XML/tag data when it has a component key and class.
4. Support explicit `#[AsTwigComponent(name, template)]` components without requiring namespace defaults when possible.
If `UxTemplateStubIndex` has indexed a component with an explicit name from the attribute, it should be usable even if its class does not match a YAML-configured namespace.
This handles simple cases where the component name is fully declared in the attribute.
5. Add tests.
Add fixture/container XML containing a service like:
```xml
<service id="App\Shared\Ui\Web\Component\PageIntro\PageIntroComponent"
class="App\Shared\Ui\Web\Component\PageIntro\PageIntroComponent">
<tag name="twig.component"
key="PageIntro"
template="@Shared/PageIntro/page-intro.html.twig"/>
</service>
```
Test that with no YAML `twig_component.defaults`:
- `UxUtil.getTwigComponentNames(project)` contains `PageIntro`
- navigation from `<twig:PageIntro>` resolves to the PHP class
- template navigation resolves to `@Shared/PageIntro/page-intro.html.twig` when Twig namespace paths are configured or discoverable
- completion suggests `twig:PageIntro`
- `{{ component('PageIntro') }}` navigation/completion still works
6. Add tests for no regression in YAML behavior.
Keep or add a test where `twig_component.defaults` is provided through YAML and ensure the existing behavior is unchanged.
7. Add tests for named prefixes.
Ensure existing named-prefix components still work and that XML-derived entries do not break prefixed YAML components.
8. Keep the design conservative.
Do not attempt to statically parse arbitrary PHP config. Symfony PHP config is executable code and is not a good static-analysis target. Prefer compiled container XML because it is already the normalized runtime source of truth and the plugin already supports reading container XML for other features.
Acceptance criteria:
- A Symfony project with only PHP config for `twig_component.defaults` and a valid generated container XML gets working `<twig:...>` completion/navigation.
- No duplicate YAML config is required.
- Existing YAML-based projects behave exactly as before.
- Tests cover YAML-only, XML-only/PHP-config runtime output, explicit `AsTwigComponent` names, and named prefixes.
Hey there -- thanks for the plugin! As the title says, the plugin currently does not recognise Twig stuff when defined via PHP instead of YAML config. I had my agent trace it down, so the below is AI summarised. I would love to help with a PR, but I am not at all familiar with this. So I figured before I send slop I let my agent prepare you a prompt for implementing the missing functionality. You can find it at the bottom under
Agent Prompt.From my agent...
Problem
Symfony UX Twig Component support currently works when
twig_component.defaultsis configured in YAML, but does not work reliably when the same config is provided through PHP config.At Symfony runtime, both config styles are equivalent: the PHP config is normalized, compiled, and present in the generated container. However, PhpStorm/Symfony plugin component indexing appears to depend on source-level YAML config for component namespace discovery.
This means projects using PHP config for TwigComponent defaults can have working Symfony runtime behavior, working generated container XML, and working
debug:twig-component, while the IDE still fails to resolve/navigate<twig:...>components unless duplicate YAML config is added.Proof & Trace
Symfony setup:
Example component:
Runtime works:
returns the expected component:
The compiled container XML also contains useful component data, for example:
and the generated component factory contains the resolved map:
But IDE support for
<twig:PageIntro>only starts working after adding equivalent YAML config:Code trace from the installed plugin:
UxTemplateStubIndexindexes PHP files and finds#[AsTwigComponent].UxUtil.getAllComponentNames()filters indexed PHP component classes throughUxUtil.getNamespaces().UxUtil.getNamespacesInner()reads onlyConfigStubIndexentries namedtwig_component_defaults.ConfigStubIndexonly indexes YAML files. Its input filter checksYAMLFileType.YML.UxComponentTemplateFinderParserreads compiled XML, but only forux.twig_component.component_template_finder/ anonymous template directories. It does not appear to readtwig.componentservice tags or namespace defaults from the compiled container.So the plugin already reads PHP attributes, and it already reads some compiled XML, but named component namespace discovery still appears YAML-only.
Expected Behavior
Projects using PHP Symfony config should receive the same UX Twig Component IDE support as projects using YAML config.
If the generated container XML exposes
twig.componenttags or the component factory map, the plugin should be able to discover named components without requiring duplicated YAML config.At minimum, explicitly named components such as this should be resolvable without namespace-default discovery:
because the public component name and template are already provided by the attribute.
Agent Prompt