doucong7963 2017-03-09 19:11
浏览 39
已采纳

在Symfony 3的基本布局中使用Twig Extension

I have a controller for setup a few things stored in DB. Pretty much the controller looks like:

class SetupController extends Controller
{   
    protected $foreground = '#fff';
    protected $background = '#333';
    protected $logo = 'default.png';
    protected $show_logo = true;

    public function HomePageAction()
    {
        ...          
        $options = [
            ...
            'logo'              => $this->logo,
            'foreground'        => $this->foreground,
            'background'        => $this->background
        ];

        return $this->render('CommonBundle:Layout:topbar_info.html.twig', ['options' => $options]);
    }
}

How I am using that function in /app/Resources/views/base.html.twig (this is my layout) as follow:

<head>
    ...
    {% block stylesheets %}
        ...
        <style type="text/css" media="all">
            .background, .dynamic_color {
                background-color: {{ options.background }};
            }    
        </style>
    {% endblock %}
</head>
<body>
    <div id="logo_id_area_container" class="topbar">
        {{ render(controller('CommonBundle:Setup:HomePage')) }}
    </div>
</body>

When I try to render the page it fails with the following error:

Variable "options" does not exist.

Of course where I am trying to use the var it doesn't exist because is coming out on the CommonBundle:Setup:HomePage action, does any one knows a better way to achieve this?

After some research I come up with the use of a Twig Extension but I am missing something since is not working as I expect. My Twig Extension code looks like the one above:

class SetupExtension extends \Twig_Extension
{
    use MMISessionTools;

    protected $em, $session, $zend, $session_record, $storage;
    protected $foreground = '#fff', $background = '#333', $logo = 'default.png', $show_logo = true;

    public function __construct(
        RegistryInterface $em,
        SessionInterface $session,
        ZendBridge $zb,
    ) {
        $this->em      = $em;
        $this->session = $session;
        $this->zend    = $zb;

        // Start the session before lookup for the required data
        $session->start();

        // Vars for internal usage
        $this->session_record = $record = $em->getRepository('CommonBundle:Session')->find($session->getId());
        $this->storage        = $this->UnserializeSessionData(explode('|', $record->getData())[1])['storage'];
    }

    public function renderLogo()
    {
        $logo = $this->storage->show_logo &&
        $this->storage instanceof \stdClass &&
        file_exists("/images/icons/logos/{$this->storage->prefix}_{$this->storage->host_companies_id}.gif")
            ? $this->storage->prefix.'_'.$this->storage->host_companies_id.'.gif'
            : $this->logo;

        return '<a href=""><img src="/images/icons/logos/'.$logo.'" alt="" height="60"></a>';
    }

    public function getFunctions()
    {
        return [
             new \Twig_SimpleFunction('render_logo', 'renderLogo', ['is_safe' => ['html']]),
        ];
    }
}

I am calling it from base.html.twig (the main layout or base template) as follow:

{{ render_logo() }}

But I end up with the following error:

CRITICAL - Call to undefined function renderLogo() CRITICAL - Uncaught PHP Exception Symfony\Component\Debug\Exception\UndefinedFunctionException: "Attempted to call function "renderLogo" from the global namespace."

I have the extension registered as follow in services.yml:

setup.twig_extension:
    class: CommonBundle\Twig\SetupExtension
    arguments: ['@doctrine','@session', '@zend_bridge']
    tags:
        - { name: twig.extension }

What else I am missing here? I am using Symfony 3.2.5

  • 写回答

1条回答 默认 最新

  • dongsheng6056 2017-03-09 20:57
    关注

    Inside your Twig extension's getFunctions() method you are telling Twig that the callable is the string renderLogo. This is interpreted by PHP as the function renderLogo(). For object methods, you need to pass an array where the first element is the object and the second one is the method name (see http://php.net/manual/en/language.types.callable.php):

    public function getFunctions()
    {
        return [
             new \Twig_SimpleFunction('render_logo', [$this, 'renderLogo'], ['is_safe' => ['html']]),
        ];
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?