Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[TwigBundle] Improve error when autoconfiguring a class with bothExtensionInterface and Twig callable attribute#60415

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
nicolas-grekas merged 1 commit intosymfony:7.3fromGromNaN:twig-attribute-error
May 14, 2025

Conversation

GromNaN
Copy link
Member

@GromNaNGromNaN commentedMay 13, 2025
edited
Loading

QA
Branch?7.3
Bug fix?no
New feature?no
Deprecations?no
Issues-
LicenseMIT

Reported by Javier:

I'm updating Twig extensions to use the#[AsTwig...] attributes. I removed thegetFunctions() method and had this:

class FooExtension extends AbstractExtension{    #[AsTwigFunction('name_of_function')]    public function foo(): string    {        // ...    }}

Then I saw this exception:Unable to register extension "App\Twig\FooExtension" as it is already registered.
My error is that I forgot to remove extendsAbstractExtension
But I think that Symfony's error exception should be more helpful. A quick example of something that could've helped me:"When using the AsTwigFunction attribute, your Twig extension cannot extend AbstractExtension"

The ExtensionSet exception is thrown because the same an extension is registered twice:

  1. It has thetwig.extension tag autoconfigured because it implementsTwig\Extension\ExtensionInterface
  2. AnAttributeExtension is registered for this class because it as one of the extension attributes (since[TwigBundle] Enable#[AsTwigFilter],#[AsTwigFunction] and#[AsTwigTest] attributes to configure runtime extensions #52748)

Previous exception whentwig service is instanciated:

LogicException : Unable to register extension "Symfony\Bundle\TwigBundle\Tests\Functional\InvalidExtensionWithAttributes" as it is already registered.

New exception during container compilation:

Symfony\Component\DependencyInjection\Exception\LogicException : The class "Symfony\Bundle\TwigBundle\Tests\Functional\InvalidExtensionWithAttributes" cannot both extend "Twig\Extension\AbstractExtension" and use the "#[Twig\Attribute\AsTwigFilter]" attribute on method "funFilter()", choose one or the other.

CheckingAbstractExtension makes the error message more specific to the code, as most extensions extend this class and doesn't implement the interface directly.

OskarStark reacted with heart emoji
@GromNaNGromNaNforce-pushed thetwig-attribute-error branch froma05c57b to83f0f07CompareMay 14, 2025 07:26
Copy link
Member

@javiereguiluzjaviereguiluz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Thanks a lot!

Copy link
Member

@nicolas-grekasnicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

just minor cs stuff

@GromNaNGromNaNforce-pushed thetwig-attribute-error branch from83f0f07 to2abcc87CompareMay 14, 2025 09:02
@GromNaN
Copy link
MemberAuthor

GromNaN commentedMay 14, 2025
edited
Loading

minor cs stuff

Fixed.

$class = $reflector->getDeclaringClass();
if ($class->implementsInterface(ExtensionInterface::class)) {
if ($class->isSubclassOf(AbstractExtension::class)) {
throw new LogicException(\sprintf('The class "%s" cannot both extend "%s" and use the "#[%s]" attribute on method "%s()", choose one or the other.', $class->name, AbstractExtension::class, $attribute::class, $reflector->name));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Suggested change
thrownewLogicException(\sprintf('The class "%s" cannotbothextend "%s" and use the "#[%s]" attribute on method "%s()", choose one or the other.',$class->name, AbstractExtension::class,$attribute::class,$reflector->name));
thrownewLogicException(\sprintf('The class "%s" cannot extend "%s" and use the "#[%s]" attribute on method "%s()", choose one or the other.',$class->name, AbstractExtension::class,$attribute::class,$reflector->name));

if ($class->isSubclassOf(AbstractExtension::class)) {
throw new LogicException(\sprintf('The class "%s" cannot both extend "%s" and use the "#[%s]" attribute on method "%s()", choose one or the other.', $class->name, AbstractExtension::class, $attribute::class, $reflector->name));
}
throw new LogicException(\sprintf('The class "%s" cannot both implement "%s" and use the "#[%s]" attribute on method "%s()", choose one or the other.', $class->name, ExtensionInterface::class, $attribute::class, $reflector->name));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Suggested change
thrownewLogicException(\sprintf('The class "%s" cannotbothimplement "%s" and use the "#[%s]" attribute on method "%s()", choose one or the other.',$class->name, ExtensionInterface::class,$attribute::class,$reflector->name));
thrownewLogicException(\sprintf('The class "%s" cannot implement "%s" and use the "#[%s]" attribute on method "%s()", choose one or the other.',$class->name, ExtensionInterface::class,$attribute::class,$reflector->name));

Copy link
Member

@chalasrchalasrMay 14, 2025
edited by stof
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

suggested it in#60415 (comment) :) what's wrong with it?

use Twig\Extension\AttributeExtension;

class AttributeExtensionTest extends TestCase
{
public function testExtensionWithAttributes()
/** @beforeClass */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Please also add the PHPUnit attribute, to be compatible with PHPUnit 11

GromNaN reacted with thumbs up emoji
Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Good idea, attribute added.

I've also seen the pre condition attributes, but none of them can check a composer package version or if a class exists:https://docs.phpunit.de/en/10.5/writing-tests-for-phpunit.html#skipping-tests-using-attributes

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Looks weird that they don't have aRequiresClass attribute (and probablyRequiresInterface). It would look consistent with the other attributes they have.

@GromNaNGromNaNforce-pushed thetwig-attribute-error branch from2abcc87 to752b41dCompareMay 14, 2025 11:51
@nicolas-grekas
Copy link
Member

Thank you@GromNaN.

@nicolas-grekasnicolas-grekas merged commit170b631 intosymfony:7.3May 14, 2025
10 of 11 checks passed
@GromNaNGromNaN deleted the twig-attribute-error branchMay 14, 2025 13:21
@PhilETaylor
Copy link
Contributor

PhilETaylor commentedMay 14, 2025
edited
Loading

Just came here while researching an error oncache:warmup after moving toAsTwigFilter

Twig\Environment::addExtension(): Argument #1 ($extension) must be of type Twig\Extension\ExtensionInterface, MyJoomla\Twig\Extension\Anon given, called in /app/var/build/ContainerN7Q6vq6/App_KernelProdContainer.php on line 20408

WhereMyJoomla\Twig\Extension\Anon is just

class Anon{privateint$anonTagIndex =0;publicfunction__construct(privatereadonlyClient$client,    ) {    }    #[AsTwigFilter(name:'anon')]publicfunctionanon(?string$string ='',string$type =''):string    {// snip}}

Running BETA2 in production ;-) I cant replicate it locally in dev

@GromNaN
Copy link
MemberAuthor

GromNaN commentedMay 14, 2025
edited
Loading

@PhilETaylor it looks like a cache issue. If you updated the class without rebuilding the container, this error is expected. On production, the cache is not automatically rebuilt when a file is modified. You should runAPP_ENV=prod bin/console cache:clear.

@PhilETaylor
Copy link
Contributor

prod is a docker container built from scratch each deploy, the build folder should be empty on deployment. I think my issue might be a shared redis cache... ignore me, I know Im at the bleeding edge here, and not looking for support, but hoping by testing the beta's to find real issues for you : )

GromNaN reacted with thumbs up emoji

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@stofstofstof left review comments

@OskarStarkOskarStarkOskarStark approved these changes

@chalasrchalasrchalasr left review comments

@javiereguiluzjaviereguiluzjaviereguiluz approved these changes

@nicolas-grekasnicolas-grekasnicolas-grekas approved these changes

@ycerutoycerutoAwaiting requested review from ycerutoyceruto is a code owner

Assignees
No one assigned
Projects
None yet
Milestone
7.3
Development

Successfully merging this pull request may close these issues.

8 participants
@GromNaN@nicolas-grekas@PhilETaylor@javiereguiluz@stof@OskarStark@chalasr@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp