0

I have defined a shared service baseImagesURL in my configuration Class but when I try to use it in volt it throws this error Phalcon\Mvc\View\Exception: Macro 'baseImagesURL' does not exist

/**
 * This service helps in the setting base images folder URL 
 */
$di->setShared('baseImagesURL', function() use ($di) {
    /** @var Config $config */
    $config = $di->get('config');
    $url = new Url();
    $url->setStaticBaseUri( $config->path("environment.baseImagesUri"));
    return $url;
});

Volt:

<img src="{{baseImagesURL('Sale-big.jpg')}}" >
Iftikhar uddin
  • 3,117
  • 3
  • 29
  • 48

1 Answers1

1

Volt, by default, has already a function called url that can be used to handle what you want. I assume you are already familiar with the url function, so I imagine that you are using a different name (baseImagesURL) because you would like to have both functions simultaneously available inside the templating engine, with different base URI configurations.

To find out how to do what you whant, we can inspect the generated compiled code of a Volt template that uses the regular url function. We will see that the line {{url('foo.bar')}} gets translated to: <?= $this->url->get('foo.bar') ?> inside the generated PHP code (you can find this compiled file inside the cache/ dir of your Phalcon app).

Knowing that, we can do the same thing and create a new function called baseImagesURL to be used. First, we have to create a new service, like you already did in your question:

$di->setShared('baseImagesURLService', function () {                                                                                                                                                                                               
    $url = new UrlResolver();                                                                                            
    $url->setBaseUri('/tmp2/');                                                                                          
    $url->setStaticBaseUri('/tmp2/');                                                                                                                                                                                                                 
    return $url;                                                                                                         
});

The above is similar to what you had in your question, but I've simplified a little bit to have the base URIs hardcoded.

After creating this service, you can add a new Volt function:

$volt->getCompiler()->addFunction(
    'baseImagesURL',
    function ($url) {
        return '$this->baseImagesURLService->get(' . $url . ');';
    }
);

Now, we are ready to use the new function inside a Volt template:

{{ url('foo.bar') }}
<br/>
{{ baseImagesURL('foo.bar') }}

The above will result in:

/tmp/foo.bar
/tmp2/foo.bar

As you can see, I have used both url() and baseImagesURL() inside the same template, to show you that both are working as expected. For this demo, I've configured the url service almost identical to baseImagesURLService, except for the hardcoded path:

$di->setShared('url', function () {   
    $url = new UrlResolver();
    $url->setBaseUri('/tmp/');
    $url->setStaticBaseUri('/tmp/');
    return $url;
});

PS - I have only named the service baseImagesURLService (redundant name) to make a clear distinction between the service name, and the Volt function name (baseImagesURL). Of course, you could use the same name for both.

PS2 - Make sure that you have configured Volt to always recompile your template. If not, the function baseImagesURL will not be available and will trigger the same error you have already encountered (macro not found). Example:

$volt->setOptions([
    'compiledPath' => $config->application->cacheDir,
    'compiledSeparator' => '_',
    'compileAlways' => true
]);
pagliuca
  • 1,129
  • 13
  • 19
  • Thanks for the detailed answer mate. Let me give a try. – Iftikhar uddin Sep 03 '19 at 14:02
  • I tried the above code but the error still exist. What I want is to define a config variable which can store a path, and then that path is accessible to all volt views. I posted the question @ phalcon forums but waiting for a good answer https://forum.phalcon.io/discussion/19987/how-to-define-a-config-variable-in-phalcon – Iftikhar uddin Sep 04 '19 at 07:46
  • I don't think I understand 100% what you are saying. Which error are you getting? The function `baseImagesURL()` is not enough for your needs? If you want, you can call `{{ baseImagesURL() }}` inside the template to get the value of the config variable. But usually, calling directly baseImagesURL('my-file') is enough for most asset-serving needs. – pagliuca Sep 04 '19 at 13:30
  • @Iftikharuddin I tested the above code, it is working correctly, I just pushed my example to a git repo. You can check out the project here: https://github.com/rpagliuca/phalcon-base-images-url . Particularly, I think you would be interested in this file: https://github.com/rpagliuca/phalcon-base-images-url/blob/master/project/app/config/services.php – pagliuca Sep 04 '19 at 13:47