Skip to content

Commit 2dccdcb

Browse files
committed
bug #1820 [TwigComponent] Allow input props to have the same name as context variables (squrious)
This PR was merged into the 2.x branch. Discussion ---------- [TwigComponent] Allow input props to have the same name as context variables | Q | A | |--------------|-----| | Bug fix? | yes | | New feature? | no | | Issues | - | | License | MIT | It looks like #1652 introduced an issue with input props and parent context. If: - A component prop has the same name as a variable in the parent context - The context variable is used to set the prop value as an input prop - The component is rendered with the embed strategy Then, the default value of the prop is used instead of the one passed to the component. Example: ```twig {# templates/components/Hello.html.twig #} {% props name = 'John' %} <div {{ attributes }}> Hello {{ name }}! </div> ``` ### Render embedded ```twig {% set name = 'Bryan' %} <twig:Hello :name="name"></twig:Hello> ``` Wrong output: ```html <div> Hello John! </div> ``` ### Render with function ```twig {% set name = 'Bryan' %} <twig:Hello :name="name" /> ``` Correct output: ```html <div> Hello Bryan! </div> ``` Commits ------- 7c4030b8 [TwigComponent] Allow input props to have the same name as context variables
2 parents 8bb0c0c + 356a167 commit 2dccdcb

File tree

4 files changed

+19
-11
lines changed

4 files changed

+19
-11
lines changed

src/ComponentRenderer.php

+4-3
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,9 @@ private function preRender(MountedComponent $mounted, array $context = []): PreR
117117
// first so values can be overridden
118118
$context,
119119
// add the context in a separate variable to keep track
120-
// of what is coming from outside the component
121-
['__context' => $context],
120+
// of what is coming from outside the component, excluding props
121+
// as they override initial context values
122+
['__context' => array_diff_key($context, $props)],
122123
// keep reference to old context
123124
['outerScope' => $context],
124125
// add the component as "this"
@@ -180,7 +181,7 @@ private function exposedVariables(object $component, bool $exposePublicProps): \
180181
$name = $attribute->name ?? (str_starts_with($method->name, 'get') ? lcfirst(substr($method->name, 3)) : $method->name);
181182

182183
if ($method->getNumberOfRequiredParameters()) {
183-
throw new \LogicException(sprintf('Cannot use %s on methods with required parameters (%s::%s).', ExposeInTemplate::class, $component::class, $method->name));
184+
throw new \LogicException(sprintf('Cannot use "%s" on methods with required parameters (%s::%s).', ExposeInTemplate::class, $component::class, $method->name));
184185
}
185186

186187
if ($attribute->destruct) {

src/Twig/PropsNode.php

+3-8
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public function compile(Compiler $compiler): void
5757
if (!$this->hasNode($name)) {
5858
$compiler
5959
->indent()
60-
->write('throw new \Twig\Error\RuntimeError("'.$name.' should be defined for component '.$this->getTemplateName().'");')
60+
->write('throw new \Twig\Error\RuntimeError("'.$name.' should be defined for component '.$this->getTemplateName().'.");')
6161
->write("\n")
6262
->outdent()
6363
->write('}')
@@ -100,18 +100,13 @@ public function compile(Compiler $compiler): void
100100
$compiler
101101
->write('if (isset($context[\'__context\'][\''.$name.'\'])) {')
102102
->raw("\n")
103-
->write('$contextValue = $context[\'__context\'][\''.$name.'\'];')
104-
->raw("\n")
105-
->write('$propsValue = $context[\''.$name.'\'];')
106-
->raw("\n")
107-
->write('if ($contextValue === $propsValue) {')
108-
->raw("\n")
103+
->indent()
109104
->write('$context[\''.$name.'\'] = ')
110105
->subcompile($this->getNode($name))
111106
->raw(";\n")
107+
->outdent()
112108
->write('}')
113109
->raw("\n")
114-
->write('}')
115110
;
116111
}
117112
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{% set message = 'bar' %}
2+
3+
<twig:Message :message="message">
4+
<p>Hey!</p>
5+
</twig:Message>

tests/Integration/ComponentExtensionTest.php

+7
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,13 @@ public function testComponentPropsOverwriteContextValue(): void
204204
$this->assertStringContainsString('<p>foo</p>', $output);
205205
}
206206

207+
public function testComponentPropsOverwriteContextValueWithInputProp(): void
208+
{
209+
$output = self::getContainer()->get(Environment::class)->render('anonymous_component_with_input_prop_with_same_name_in_context.html.twig');
210+
211+
$this->assertStringContainsString('<p>bar</p>', $output);
212+
}
213+
207214
public function testComponentPropsWithTrailingComma(): void
208215
{
209216
$output = self::getContainer()->get(Environment::class)->render('anonymous_component_props_trailing_comma.html.twig');

0 commit comments

Comments
 (0)