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

problem for to set array in volt

Hi ...

I'm trying to translate a php function in volts but I have a problem setting the array

this is the function php

<?php 
function formatTree($tree, $parent){
        $tree2 = array();
        foreach($tree as $i => $item){
            if($item['parent_id'] == $parent){
                $tree2[$item['id']] = $item;
                $tree2[$item['id']]['submenu'] = formatTree($tree, $item['id']);
            }
        }

        return $tree2;
    }

and this in volt

{%- macro formatTree(tree,parent = null) %}
  {% set tree2 = [] %}

    {% for i,item in tree %}

      {% if item["parent_id"] == parent %}

        {# {% set tree2 = [item["id"]:item] %} DON'T WORK #}
        {% set tree2 = [item["id"],["submenu":formatTree(tree,item["id"])]] %}      

      {% endif %}

    {% endfor %}

  {% return tree2 %}

{%- endmacro %}

the error is

Syntax error, unexpected token COLON


17.7k

This is that doesn't work

 {% set tree2 = [item["id"]:item] %}


3.9k
Accepted
answer
{% set tree2 = item["id"].["submenu"].formatTree(tree,item["id"]) %}

This have a syntax error itself independent of Phalcon\Volt. Volt is a children and has many bugs of construct and interpreter, that developers are doing an extensive job to made it better each day. The correct way to do that doesen't work at all, because volt doesn't have associative dynamic array. This key must be a string:

        {%- macro formatTree(tree,parent = null) %}
            {% set tree2 = [] %}
            {% for i,item in tree %}
                {% if item['parent_id'] == parent %}
                    {% set item_id = item['id'] %}
                    {% set tree2 = ['item_id':item] %}{# key has to be a string that's why doesen't work #}
                    {% set tree2 = ['item_id']['submenu':formatTree(tree,item['id']]) %}
                {% endif %}
            {% endfor %}
            {% return tree2 %}
        {%- endmacro %}

I use a lot of function in my volt calling they directly from an model, see the exemple bellow:

in Model:

public function formatTree($tree, $parent){
    $tree2 = array();
    foreach($tree as $i => $item){
        if($item['parent_id'] == $parent){
            $tree2[$item['id']] = $item;
            $tree2[$item['id']]['submenu'] = formatTree($tree, $item['id']);
        }
    }
    return $tree2;
}

in Controller:

$this->view->myModel = new myModel();

in Volt:

{% set item = myModel.formatTree(tree, parent) %}

This can't be the better way to do this, but works.



3.9k
edited May '15

You can use a custom function declared on services for volt too like this:

1 - Create a folder with a friendly name like "Customs" or "Helpers" anything you want

2 - Remeber to declare this on your applications config:

return new \Phalcon\Config(array(
    'database' => array(
        'adapter'     => 'Mysql',
        'host'        => 'localhost',
        'username'    => 'root',
        'password'    => 'your_pass',
        'dbname'      => 'your_base',
        'charset'     => 'utf8',
    ),
    'application' => array(
        'controllersDir' => __DIR__ . '/../../app/controllers/',
        'modelsDir'      => __DIR__ . '/../../app/models/',
        'migrationsDir'  => __DIR__ . '/../../app/migrations/',
        'viewsDir'       => __DIR__ . '/../../app/views/',
        'pluginsDir'     => __DIR__ . '/../../app/plugins/',
        'libraryDir'     => __DIR__ . '/../../app/library/',
        'helpersDir'      => __DIR__ . '/../../app/Helpers/', //here your folder
        'cacheDir'       => __DIR__ . '/../../app/cache/',
        'vendorDir'     => __DIR__ . '/../../vendors/',
        'baseUri'        => '/clinica_vita/',
    )
));

3 - Register this on your loader:

$loader->registerDirs(
    array(
        $config->application->controllersDir,
        $config->application->modelsDir,
        $config->application->helpersDir,
    )
)->register();

4 - Create a class inside this with the name you pick: (Ex: for me is: Filters.php)

class Filters
{
    public static formatTree($tree, $parent){
        $tree2 = array();
        foreach($tree as $i => $item){
            if($item['parent_id'] == $parent){
                $tree2[$item['id']] = $item;
                $tree2[$item['id']]['submenu'] = formatTree($tree, $item['id']);
            }
        }
        return $tree2;
    }
}

5 - Inside the services.php call this on the volt object:

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

    $view = new View();
    $view->setViewsDir($config->application->viewsDir);
    $view->setRenderLevel(\Phalcon\Mvc\View::LEVEL_ACTION_VIEW);
    $view->registerEngines(array(
        '.volt' => function ($view, $di) use ($config) {

            $volt = new VoltEngine($view, $di);
            $volt->setOptions(array(
                'compiledPath' => $config->application->cacheDir . '/volt/',
                'compiledSeparator' => '_'
            ));
            $compiler = $volt->getCompiler();

            //Aply here the name of your  custom function
            $compiler->addFunction('formatTree', function($resolvedArgs, $exprArgs) {
               return 'Filters::formatTree(' . $resolvedArgs . ')';
            });

            return $volt;
        }
    ));

    return $view;
}, true);

6 - Finally on volt you can call your custom function without model dependencies:

{% set item = formatTree(tree, parent) %}

Just another method to do that without Model way.