We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Compile volt before render view

Hi

I have items in database and I want to add volt code in the content for exemple :

"blalbla {{  myfunction('param') }} blabla".

the problem is that I get

blalbla {{ myfunction('param') }} blabla

I tried to compile the content in my controller but still not working.

$item->content = (new Volt($this->view, $this->getDI()))->getCompiler()->compileString($item->content);

How I can achieve this?



43.9k

Hi,

you have to register your function in volt compiler see here: https://docs.phalcon.io/en/3.2/volt#extending-functions



3.3k

thx le51

I already added my function to the compiler like this

$compiler->addFunction(
                            'myfunction', function ($param) {
                                return '\Namespace::myfunction(' . $param . ')';
                            }
                    );

But I get this

callMacro('myfunction', ['test']) ?>

Hmm if I understand, you want to achieve something like Worpdress "shortcodes"?

// Example of replacing a string with entire partial template
{{ str_replace(
    '[flight-search-form]',
    view.getPartial("_layouts/parts/flight-search-form", ['searchType': 'simple']),
    obj.content
) }}

// Simple replacement in your case
{{ str_replace(
    '__PLACEHOLDER_BLABLABLA__',
    someFunction(obj.someVariable),
    obj.content
) }}


3.3k

Hmm if I understand, you want to achieve something like Worpdress "shortcodes"?

// Example of replacing a string with entire partial template
{{ str_replace(
   '[flight-search-form]',
   view.getPartial("_layouts/parts/flight-search-form", ['searchType': 'simple']),
   obj.content
) }}

// Simple replacement in your case
{{ str_replace(
   '__PLACEHOLDER_BLABLABLA__',
   someFunction(obj.someVariable),
   obj.content
) }}

Hi

Yes I want to achieve something like loadposition in Joomla, I have entity named blocks, with block position field, I want to be able to load my block in the content. So I need to convert {{ displayBlock("position") }} to the content of the block.



3.3k

the problem of your piece of code is that my function parameter can change, the placeholder not fixed text.

edited Jan '18

Well not 100% sure what you want to achieve, but judging from your question you want to execute some code inside of a Text block generated from WYSIWYG editor for example?

1) If above is correct, your best option is to use placeholders. It is easier for non programmer users to use and less fragile to break your app. It is easy to pass parameters in shortcodes:

'[flight-search-form blabla=123 test=44 bla2="haha"]'

You just have to replace str_replace with more advanced function that can parse parameters.

2) If your page is built with "blocks" then you have to use some other logic. In this case i would do something like:

// Lets say your Blocks setup in the CMS looks like:
BLOCK-0 (header navigation)
BLOCK-1 (generic slideshow)
BLOCK-2 (news widget)
BLOCK-3 (products slideshow)
BLOCK-4 (footer navigation)

// Volt code may look something like:
{% for block in blocks %}
    {{ block.render() }} // This is a random function name
{% endfor %}

In the example above the block can be a Model object, which will contain all needed DB properties/parameters which can be used in the related block template.



3.3k
Accepted
answer

thx Nikolay

I find a quick solution, I created a class with the functions for rendering the content and I add this function

    public function prepareContent($content) {
        return preg_replace_callback("/{{2}[^{}]*\}{2}/", function($matches) {
            foreach ($matches as $m) {
                return eval('return \PathToMyClass::' . substr(substr($m, 0, -2), 3, strlen($m)) . ';');
            }
        }, $content);
    }

and in my content controller I do:

$content->description = $this->elements->prepareContent($content->description);

Its' working and I don't need to declare my functions in volt compiler.

As long as you trust the content source it should do the job. Well done :)