Twig view renderer

Не лучшая идея при каждом рендере проверять атрибуты аж двух файлов. Очищать такой мусор лучше по крону.

That’s just what I was looking for! It should really go into the official extension, it’s pretty much unusable without it by default.

We are going to use this extension for our site as wel… Tnx!

btw., latest version is in yiiext: http://yiiext.github.com/

Hi Sam, I am receiving this error (was also mentioned before) about the app not being able to find the view file. It is in ../protected/views/site/home.html.

Do you have any ideas what the problem might be? I did not alter extension (it’s standard .html) via my config or anything…




CException


SiteController cannot find the requested view "home".


/Library/WebServer/Documents/framework/web/CController.php(875)



Shouldn’t it be ‘home.php’?

Unless you instruct the controller, it assumes that the extension of view files is .php

If you are using TwigRenderer it should be


home.twig

if it is not twig, it should be as jacmoe said:


home.php

Hi, thanks for your replies!

I tried to use .twig at first but I got the same error. Then I overruled the .twig extension in my config to .html but still got the same error. Do i need to specify somewhere what the path to the .twig/.html files should be?

Thanks.

Tried some things but can’t get it to work… problem is still the same… anyone able to push me in the right direction? :)

Here is an example from the default app converted to twig templates, feel free anyone to use it:

github (dot) com/johsbk/Yii-with-twig

(im not allowed to post links just yet, this forum is really making it hard for somebody to contribute)

Hi there,

With the help of johsbk’s code I have been able to get most of the Twig extension working. However I am not able to use the extension on other controllers. I get the error message that it can’t find the view file. So it only works in the SiteController class. Is this normal behavior or am I doing something wrong… ? If it’s normal then I will try to fork and fix the issue…

Hope someone is able to give me an answer :) Tnx.

Hmm… shouldn’t be so.

If you have


$this->render('index');

in your SiteCntroller it tries views/site/index.twig, for PostController it will search for views/post/index.twig. Well, at least it was like that when I’ve released first version.

Hi Samdark, thanks for pointing me to the fact that i have to use a directory for each controller… still learning Yii :)

I need to test this

Everything is working great… however I can’t seem to get a Twig extension working… Wrote a very simple Twig extension class, added it to the Yii config but it does not seem to recognize my function…

There were some problems with it. Try latest version from github, maybe it’s fixed already: http://yiiext.github.com/extensions/twig-renderer/index.html

I have been using the Twig view renderer v.1.1.2.

The following is how should I write?




<?php

$this->breadcrumbs=array(

	'Words',

);


$this->menu=array(

	array('label'=>'Create Word', 'url'=>array('create')),

	array('label'=>'Manage Word', 'url'=>array('admin')),

);

?>


<?php $form=$this->beginWidget('CActiveForm', array(

	'id'=>'word-form',

	'enableAjaxValidation'=>false,

)); ?>


<?php echo Yii::getVersion(); ?>



Sam, thanks for the update. WIll try that.

Another question: i have extended the renderer a bit so it’s now possible to fetch .twig templates from an S3 bucket (since this is where I want our customers to store their templates, and not on our servers). With the AWS SDK I can easily get the contents of the .twig templates in a variable.

Would it be possible to parse a ‘template’ which is in a variable (as a string) instead of using a URL? Something like:




//function renderFile in ETwigViewRenderer.php holds these lines. It needs a $sourceFile path string. 

$sourceFile = substr($sourceFile, $this->_basePathLength);

$template = $this->_twig->loadTemplate($sourceFile)->render($data);


//I have the body of a twig template available (from S3) and would like to use that for parsing. 

$templateBody = $s3->get_object('bucket-name',$s3SourceFile);

$template = $this->_twig->loadTemplateFromBody($templateBody)->render($data);



Currently I have no idea how I could fix this… perhaps someone can give me a direction? Perhaps it’s very simple… don’t know :)

With this solution we could also implement some caching (we use Elasticache from AWS) and only fetch the files when the cache is empty (which is done when the templates on S3 are updated).

Update: i can see that I can create a new loader


$loader = new Twig_Loader_String();

. However, creating a new S3 loader would be the best thing to do I guess.

In addition to my previous post. I now have altered the renderFile function in this way:




     /**

     * Renders a view file.

     * This method is required by {@link IViewRenderer}.

     * @param CBaseController $context the controller or widget who is rendering the view file.

     * @param string $sourceFile the view file path

     * @param mixed $data the data to be passed to the view

     * @param boolean $return whether the rendering result should be returned

     * @return mixed the rendering result, or null if the rendering result is not needed.

     */

    public function renderFile($context, $sourceFile, $data, $return)

    {

        // current controller properties will be accessible as {{ this.property }}

        $data['this'] = $context;

        $sourceFile = substr($sourceFile, $this->_basePathLength);

        

        $s3 = new AmazonS3();

        $s3path = substr($sourceFile, 1);

        if ($s3->if_object_exists(Yii::app()->params->aws['s3bucket'],$s3path))

        {

            $this->_twig->setLoader(new Twig_Loader_String());

            $sourceFile = $s3->get_object(Yii::app()->params->aws['s3bucket'],$s3path)->body;

        }

        

        $template = $this->_twig->loadTemplate($sourceFile)->render($data);


        if ($return) {

            return $template;

        }


        echo $template;

    }



It basically takes the template from the bucket if the .twig template is there and change the loader to a Twig_Loader_String().

The problem now is that all the ‘other’ stuff in the Twig templates is not getting rendered. This could be the case because the parser is not getting the view file from S3 when it’s parsing things like {%extends …%} and widgets. However, these files are available in the application views dir as well.

If I remove stuff like {% extends ‘views/layouts/main.twig’ %} from the templates on S3 it works but i would like to keep that stuff in and get it parsed of course :)

I guess this is as much a Twig thing as it is a Yii thing (or even more so :)).

If you use {% include … %}, the parser tries to find the file in yii/protected instead of yiiapp/protected/views…, it’s very annyoing <_<