1

Given a page retrieved at for example:

http://myapp.dev/path/subfolder?param=abc

Whenever the additional GET parameter called param is present it should be added automatically to all subsequent links in my navigation as constructed in the .volt template. For example:

<a href="{{ url('path/subfolder2') }}">Go to subfolder 2</a>

I.e. based on this .volt link the the goal is to generate:

<a href="http://myapp.dev/path/subfolder2?param=abc">Go to subfolder 2</a>
Timothy
  • 2,004
  • 3
  • 23
  • 29
Johan van den Broek
  • 384
  • 2
  • 5
  • 18

1 Answers1

0

If you want to append Query string parameters only for given links you can go with Luke's solution. However I think you want to achieve something a bit different and it involves custom logic. For this to happen we should create a custom Volt function.

Custom function definition:

public static function urlFor($params, $queryStringParams = [])
{
    $di = \Phalcon\DI::getDefault();
    if ($di->getRequest()->has('param')) {
        $queryStringParams['param'] = $di->getRequest()->get('param');
    }
    return $di->getUrl()->get($params, $queryStringParams);
}

The above function acts the same as url() function in Phalcon, it just allows us to write a bit of custom logic before passing the parameters to url(). In your case we check if URL contains desired query param and we add it to every URL generated on the current request. In my case the above function is in Helper file so I can use it anywhere I need to.

This is our View service definition:

$di->set('view', function() use ($di) {
    $view = new \Phalcon\Mvc\View();
    ...
    $view->registerEngines([
        '.phtml' => function($view, $di) {
            $volt = new \Phalcon\Mvc\View\Engine\Volt($view, $di);
            $options = [
                'compiledPath' => $di->getConfig()->site->path->cache . 'volt/frontend/',
                'compiledExtension' => '.php',
                'compileAlways' => $di->getConfig()->debug,
            ];
            $volt->setOptions($options);

            ...
            
            // IMPORTANT PART: Overwriting default url() function in Volt
            $compiler = $volt->getCompiler();
            $compiler->addFunction('url', function($resolvedArgs, $exprArgs){
                return 'Helpers\Common::urlFor(' . $resolvedArgs . ')';
            });
            return $volt;
        }
    ]);
    return $view;
});

Please note the IMPORTANT PART comment in the above code block.

Let us finish with example:

User is on this address: http://myapp.dev/path/subfolder?param=abc

But somewhere in your code you want to generate a link to News page:

<a href="{{ url('news/list') }}">News</a>

Our code will catch the param in the URL and will generate the following address:

http://myapp.dev/news/list?param=abc

Community
  • 1
  • 1
Nikolay Mihaylov
  • 3,868
  • 8
  • 27
  • 32
  • I don't see the point of NOT using standard url component. Don't reinvent the wheel. – Luke Sep 09 '16 at 09:02
  • Please read the question carefully. It's not reinventing the wheel, but extending with custom logic. If he goes with your solution he will have to check if the parameter exists and append it. – Nikolay Mihaylov Sep 09 '16 at 09:04
  • It would be much simpler to accomplish it by using parameters array managed for instance in base controller (to add it globally for all views). But this way is also working, just a bit longer and non standard – Luke Sep 09 '16 at 09:06
  • imo, this answer, answers the question better. Because the OP is specifically asking if `GET parameter called param is present`. (and not a "view" parameter) – Timothy Sep 09 '16 at 09:18
  • It is actually quite short. It appears longer because an excerpt of a View service definition is included however only one addFunction call is added. – Johan van den Broek Sep 09 '16 at 09:47
  • 1
    @Luke To maintain default behaviour of `{{ url(..) }}` the function can also be added using any other name allowing it to be used only in specific calls like `{{ urlFor(..) }}` – Johan van den Broek Sep 09 '16 at 09:54
  • @Joahn Yeah, and in my solution you just add one line to base controller and that's it. No new functions. You can still call {{ url("path/subfolder2"}} without parameters or use another parameter. We could argue for weeks. The most important is that you have your solution. Lets leave the decision to users which way they will follow – Luke Sep 09 '16 at 10:15
  • @Luke I agree that you can add it to baseController, but than every time you call `url()` in volt you have to add the second parameter. Also as Johan said you can add second function to Volt so you can have default `url()` and the new function with custom logic. – Nikolay Mihaylov Sep 09 '16 at 10:29