user3531149 user3531149 - 1 month ago 12
PHP Question

What's the "right" way to override a symfony extension from another bundle

I need to override the file
/vendor/symfony/symfony/src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php

It loads the twig getAssetUrl from the bundle using the twig function 'asset'

/**
* Returns a list of functions to add to the existing list.
*
* @return array An array of functions
*/
public function getFunctions()
{
return array(
new \Twig_SimpleFunction('asset', array($this, 'getAssetUrl')),
new \Twig_SimpleFunction('assets_version', array($this, 'getAssetsVersion')),
);
}


I want to override the asset() twig function without touching the core files, which otherwise would be overridden by the next symfony update

kba kba
Answer

Consider that your code live in AppBundle namespace. First create service configuration in app/config.yml or src/AppBundle/Resources/config/something.yml (you have to load this configuration file in bundle extension). Don't forget place it under services key.

twig.extension.assets:
    class:     AppBundle\Twig\AssetsExtension
    arguments: ["@service_container", "@?router.request_context"]
    public: false
    tags:
        - { name: twig.extension }

Now let's create extension src/AppBundle/Twig/AssetsExtension.php. This class inherits from original extension and I will override just one method (in template asset()).

<?php

namespace AppBundle\Twig;

class AssetsExtension extends \Symfony\Bundle\TwigBundle\Extension\AssetsExtension
{
    public function getAssetUrl($path, $packageName = null, $absolute = false, $version = null)
    {
        return parent::getAssetUrl('/something/' . $path, $packageName, $absolute, $version);
    }
}

Now, after reload, all your assets should be incorrect and prefixed with /something/ by default. You can try to delete Symfony cache in case of problems. I tested this scenario on Symfony 2.5.5.

Another way how to work with built-in services is compiler pass. In compiler pass you can modified whole Symfony service container (delete, replace, modify services). Symfony is all about DIC. I hope it is good enough solution.