Not able to create Volt function

Hi there,

I would like to create Volt function, which will return URI to the picture.

It will be called like that:

{{ get_image_url(_post.image, "640x291") }}

In this example I have _post, which is database object (an array in fact) and desired image resolution.

My function should return something like that: http://img.website.com/api/image/ad0733dc-1042-59ab-d5c1-dccfc23fe997/size/640x291

String ad0733dc-1042-59ab-d5c1-dccfc23fe997 is stored in the database under image property of the post.

What is difficult to me is that my Volt function looks like that:

                    $compiler->addFunction(
                        'get_image_url',
                        function ($resolvedArgs, $exprArgs) use ($compiler, $config)
                        {
                            $filename   = $compiler->expression($exprArgs[0]['expr']);
                            $resolution = $compiler->expression($exprArgs[1]['expr']);

                            // e.g. http://img.website.com/api/image/ad0733dc-1042-59ab-d5c1-dccfc23fe997/size/640x291
                            return sprintf(
                                '%s%s/api/image/%s/size/%s',
                                $config->app->imagesProviderUrl,
                                $config->app->imagesProviderBaseUri,
                                $filename,
                                $resolution
                            );
                        }
                    );

But as $filename I am getting something like:

$_post->image

not the value of the post property.

Yesterday I was getting following error regarding the filename: Array to string conversion for a similar code to the above.

Your help will be very welcome!

Today in error.log I am getting:

ParseError: syntax error, unexpected ':', expecting ',' or ';' in \/data\/projects\/web\/phalcon\/rabbitmq\/storage\/cache\/volt\/_data_projects_web_phalcon_website_app_views_partials_blog-item.volt.php

becasue PHP code looks as follow:

<img src="<?=  http://img.website.com/api/image/$_post->image/size/'640x291' ?>" alt="Ipsum" >

I forced it to work, but it was not so easy to figure out and I would like to have it written in another way:

                            return sprintf(
                                '\'%s%s/\'.%s.\'/size/%s\'',
                                $config->app->imagesProviderUrl,
                                $config->app->imagesProviderBaseUri,
                                $filename,
                                $resolution
                            );

which produces in PHP cache file made from Volt template:

<img src="<?= 'http://img.website.test/api/image/'.$_post->image.'/size/640x291' ?>" alt="Ipsum" >
edited Mar '18

Hi @webDeveloper the problem is the function must return an string with the function, then Volt include this "string function" in the view

$compiler->addFunction(
    'get_image_url',
    function ($resolvedArgs, $exprArgs) use ($compiler, $config)
    {
        $filename   = $compiler->expression($exprArgs[0]['expr']);
        $resolution = $compiler->expression($exprArgs[1]['expr']);

        // e.g. http://img.website.com/api/image/ad0733dc-1042-59ab-d5c1-dccfc23fe997/size/640x291
        return "sprintf(
            '%s%s/api/image/%s/size/%s'," .
            $config->app->imagesProviderUrl . ", " .
            $config->app->imagesProviderBaseUri . ", " .
            $filename . ", " .
            $resolution . ")";  // WARNING: don't end with a ";", because if the function is then nested in another it will give you an error
    }
);

More info about Volt functions

Good luck

Hi @emiliodeg,

Thank you for help! Now it is more clear for me!

After some adjustments my function looks as following:

                    $compiler->addFunction(
                        'get_image_url',
                        function ($resolvedArgs, $exprArgs) use ($compiler, $config)
                        {
                            $filename   = $compiler->expression($exprArgs[0]['expr']);
                            $resolution = $compiler->expression($exprArgs[1]['expr']);

                            // return e.g. http://img.website.com/api/image/ad0733dc-1042-59ab-d5c1-dccfc23fe997/size/640x291
                            return 'sprintf(\'' .
                                $config->app->imagesProviderUriMask . '\', \'' .
                                $config->app->imagesProviderUrl . '\', \'' .
                                $config->app->imagesProviderBaseUri . '\', ' .
                                $filename . ', ' .
                                $resolution .
                            ')'; // WARNING:don't end with a ";", because if the function is then nested in another it will give you an erro
                        }
                    );

I added mask, so here is my configuration:

return [
    'app'           => [
        // [...]    

        'imagesProviderUrl'     => getenv('IMAGES_PROVIDER_URL'),
        'imagesProviderUriMask' => getenv('IMAGES_PROVIDER_URI_MASK'),
        'imagesProviderBaseUri' => getenv('IMAGES_PROVIDER_BASE_URI'),

        // [...]
    ],
    // [...]
];

and environment values:

IMAGES_PROVIDER_URL="http://img.website.com"
IMAGES_PROVIDER_BASE_URI="/api/image"
IMAGES_PROVIDER_URI_MASK="%s%s/%s/size/%s"
edited Mar '18

I have one more question.

All works fine in the template, but what if I would like to have following text in my database under article.body:

<p>Nullam vestibulum dictum justo, sodales condimentum ex bibendum scelerisque. Mauris mattis posuere semper. Praesent molestie leo ac ipsum pulvinar, et vulputate lectus interdum. Fusce eu volutpat lectus. Proin et orci ut mauris dictum euismod.</p>
<p>Donec sodales hendrerit augue a egestas. Vestibulum quis eros id augue commodo placerat. Donec id ipsum consequat, vestibulum dui id, mattis nisi. Praesent convallis odio quis dignissim interdum.

<img src="{{ get_image_url('33fb27f8-ba2c-5ed5-b7e5-a3d7f02fa3f5', '460x272') }}" alt="33fb27f8-ba2c-5ed5-b7e5-a3d7f02fa3f5">

Duis lacinia enim turpis, ut condimentum nulla venenatis in. Pellentesque quam lacus, ultricies eget nisl nec, consectetur auctor mi.</p>
<p>Cras velit elit, sodales at convallis in, accumsan sed diam. Quisque sem lacus, sagittis ut maximus sed, imperdiet rutrum ante. Donec imperdiet dapibus enim, at convallis sapien auctor et.</p>

What do I need to make it working ( execute function get_image_url() )?

You have to create a filter with a regex to find this {{ get_image_url('33fb27f8-ba2c-5ed5-b7e5-a3d7f02fa3f5', '460x272') }} then call the function and return the image source ;)