Skip to content

[Twig] Decouple Twig commands from the Famework#9855

Closed
GromNaN wants to merge 12 commits intosymfony:masterfrom
GromNaN:twig-commands
Closed

[Twig] Decouple Twig commands from the Famework#9855
GromNaN wants to merge 12 commits intosymfony:masterfrom
GromNaN:twig-commands

Conversation

@GromNaN
Copy link
Copy Markdown
Member

@GromNaN GromNaN commented Dec 24, 2013

I want to use the command twig:lint in a Silex project.

In this PR, I've moved the class Symfony\Bundle\TwigBundle\Command\LintCommand to Symfony\Bridge\Twig\Command\LintCommand and removed dependency to the ContainerAwareCommand.

Q A
Bug fix? no
New feature? yes
BC breaks? yes (renamed class)
Deprecations? no
Tests pass? yes
Fixed tickets #9818 (comment)
License MIT
Doc PR n/a
  • Move command twig:debug once merged.
  • Lazy load twig service

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why not just Twig_Environment or is the \ also needed here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If you remove the \, it becomes a relative class name, and you need to add a use statement for it. and Symfony does not add use statements for classes of the global namespace

@cordoval
Copy link
Copy Markdown
Contributor

nice, great move decoupling ftw! 👍

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You don't need this getter IMO

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

My idea is that someone can extend the command class to customize how the twig instance is located.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

then you should make $this->twig protected and remove this getter, following the Symfony standards

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

And I don't even think it make sense. Someone extending the command will still need to call the parent constructor, and so would still need to inject twig through the constructor

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Method removed.

@GromNaN
Copy link
Copy Markdown
Member Author

GromNaN commented Dec 24, 2013

In addition, I've just added tests for the command.

@ggam
Copy link
Copy Markdown

ggam commented Dec 24, 2013

I think you should add a note on the changelog about the BC break.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Happy to see this feature used.
But two little questions: did you try this in a symfony2 project ? And does this make the application slower ?
Because in SF2 project, twig depends of lot of things (like security...).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is actually an issue with the commands defined as service (introduced in 2.4): commands are not loaded lazily, so all their dependency graph is instantiated for any unrelated console call

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It would be better if the getDefinition method was static.

@fabpot
Copy link
Copy Markdown
Member

fabpot commented Dec 28, 2013

This one cannot be merged before we find a solution for lazy-loading console command as services.

@realityking
Copy link
Copy Markdown
Contributor

Couldn't this be done by moving it to the bridge as an abstract class with an abstract method getTwigEnvironment? This would mean no change for Symfony2 but make it easier reusable outside of it.

@fabpot
Copy link
Copy Markdown
Member

fabpot commented Dec 28, 2013

Whatever we decide to do here should be done also in #9855

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please allow passing the name trough, sometime one wants to rename a command for consistency.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Actually, it's not possible to set a name in the constructor as it will be overwritten by the method configure(). The only solution is to set the command name explicitly with setName().

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's very easy to implement: just add a $name parameter here with the standard name as default and pass it to parent::__construct(). After that, remove it from configure

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

could you please also add this feature?

@wouterj
Copy link
Copy Markdown
Member

wouterj commented Dec 28, 2013

@fabbot I think something did go wrong, you linked to the same PR...

And I think this can be solved by overriding this command in the TwigBundle:

namespace Symfony\Bundle\TwigBundle\Command;

use Symfony\Bridge\Twig\Command\LintCommand as BaseLintCommand;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

class LintCommand extends BaseLintCommand implements ContainerAwareInterface
{
    protected $container;

    public function __construct()
    {
        // override constructor to not set the twig environment yet
        parent::__construct(new \Twig_Environment());
    }

    public function setContainer(ContainerInterface $container)
    {
        $this->container = $container;
        $this->twig = $container->get('twig');
    }
}

This requires the twig property to be protected though. Or we can use the getTwig method to retrieve the environment and override that.

Then we can investigate more time into lazy loading service commands and after that, we can remove this "hack".

@GromNaN
Copy link
Copy Markdown
Member Author

GromNaN commented Dec 30, 2013

Seeing that using "commands as services" requires initializing a deep dependency tree each time the application is run, I can't find a solution to lazy-inject the twig service into the command.

So, I think that's better not using the "commands as a service" feature; even if this is a very brilliant approach. In my last commit, I've followed the suggestions from @realityking and @wouterj and I've created a class in the bundle that extends the class in the bridge and retrieve the service from the container.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would say moved instead of added

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Changed

@fabpot
Copy link
Copy Markdown
Member

fabpot commented Dec 30, 2013

... and tests are broken.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Afaik, container can't be null,as it's set by setContainer during initialization?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Exact, I took that portion of code from ContainerAwareCommand; but it looks like a legacy fallback.
I've removed it.

@GromNaN
Copy link
Copy Markdown
Member Author

GromNaN commented Dec 30, 2013

@fabpot everything as been fixed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'd make this abstract and remove the setter. This would prevent making the setter non-functioning in the Bundle Command.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

As a developer, I don't want to be forced to create a class to use this command.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants