Reputation: 928
Using Twig 3.0, I was wondering if it is possible to create Twig extensions that intervene when the dot operator is being processed?
So, suppose I have this expression
{{ myRecord.myField }}
and it won't work even though myRecord
is a known thing, because it doesn't have a field called myField
.
But I would want Twig to run my own custom extension code to figure out what to use for .myField
, is that possible? How?
I know this can be achieved with different notations using a function or filter (e.g. myRecord|getCustomField(myField)
), but I want to keep the dot notation because I feel it's particularly adequate for my purposes.
Upvotes: 2
Views: 110
Reputation: 9162
The CoreExtension
supports get*
, is*
, has*
method lookups for the dot.
https://github.com/twigphp/Twig/blob/3.x/src/Extension/CoreExtension.php#L1563
So if your class has a myRecord::getMyField
method you can access it via myRecord.myField
in Twig.
Another option is to use the __call
magic method: https://www.php.net/manual/en/language.oop5.overloading.php#object.call
The more complex and flexible approach that doesn't require altering the myRecord
class would involve writing a custom Extension to replace nodes. Here's a simple example that you can modify to create MethodCall nodes on the class, for example.
$twig->addExtension(new class extends Twig\Extension\AbstractExtension {
public function getNodeVisitors(): array {
return [
new class implements Twig\NodeVisitor\NodeVisitorInterface {
public function enterNode(Node $node, Environment $env): Node {
return $node;
}
public function leaveNode(Node $node, Environment $env): ?Node {
if (!$node instanceof Twig\Node\Expression\GetAttrExpression) {
return $node;
}
if ('myRecord' !== $node->getNode('node')->getAttribute('name')) {
return $node;
}
// Custom lookup logic goes here...
$attribute = $node->getNode('attribute')->getAttribute('value');
$node->setNode('attribute', new Twig\Node\Expression\ConstantExpression('get_' . $attribute, 0));
return $node;
}
public function getPriority(): int {
return 1;
}
}
];
}
});
Hope this helps.
Upvotes: 0