Twig and dependency injector

I'm adding Twig support on existing apps that has been written in Volt.

I'm looking to replicate the same behavior of Volt that expose DI services: {{ config }} or {{ this.config }} but I'm not sure how volt do that (even by looking source).

For now my working way is to iterate over $di->getServices() and assign each services to the view object

Is the right way to do that?

Mat

<?php
class Twig extends Engine implements EngineInterface
{
  protected $twig;

  public function __construct($view, $di, $options = [])
  {
    $this->setDI($di);

    $loader     = new \Twig_Loader_Filesystem($di->getView()->getViewsDir());
    $this->twig = new TwigEnvironment($di, $loader, [
      'debug' => $di->getEnv()->development
    ]);

    $this->twig->addExtension( new \Twig_Extension_Debug() );

    // Expose phalcon services to twig
    foreach ($di->getServices() as $name => $obj) {
      $view->$name = $obj;
    }

    parent::__construct($view, $di);

  }

}
edited Mar '17

https://github.com/phalcon/incubator/tree/master/Library/Phalcon/Mvc/View/Engine Engine class extends Injectable, so it will work the same as in volt.

edited Mar '17

Hm I can't get this working (no errors, no warnigs). After looking the constructor, ( https://github.com/phalcon/cphalcon/blob/master/phalcon/mvc/view/engine.zep#L40 ), they need ViewBaseInterface and DiInterface.

But in my Twig class, the constructor $view is View and $di is FactoryDefault even from the simple service :

$di->set('view', function() {

    $view = new \Phalcon\Mvc\View();

    $view->setViewsDir('../app/views/');

    $view->registerEngines(
        ['.twig' => 'My\View\Engine\Twig']
    );

    return $view;
});

In the incubator Twig class, they use $view ViewBaseInterface and $di DiInterface => https://github.com/phalcon/incubator/blob/master/Library/Phalcon/Mvc/View/Engine/Twig.php#L28-L30

Well there are not twig tests in incubator, can't you just use classes from incubator and check it out? As i see this code just same as volt should work, so for example to acces service config just {{ config.someKey }}

I can't use the Incubator Twig class because I need to apply some business logic in both constructor and render method.

I'm finally using $this->twig->addGlobal(&#039;config&#039;, $di->get(&#039;config&#039;)); and work as expected.

Seems better since I do not need all services, I was just thinking the services will automagically exposed like volt

edited Mar '17

You can always extend them. Well i will need to check incubator then if it works like in volt or not. To be honest it fells more like you should use some twig extension.