«Прокидывание» параметра через все ссылки

Задача: добавить параметр ко всем ссылкам, генерируемые Symfony UrlGenerator`ом, если он был в текущем запросе.
Например, у вас есть особой шаблон, на тот случай, если модуль отображается в iframe другого модуля.
Если знаете как это сделать средствами Symfony, то расскажите. Я такого способа не нашел, поэтому сделал свою реализацию.

Сначала определимся какие именно параметры нужно прокинуть. У меня они хранятся в конфиге:

1
2
3
4
5
6
7
8
9
    //config.php
    ...
    'routing' => array(
        'through_GET_parameters' => array( //эти _GET-параметры(если они есть в запросе) будут добавлены ко всем генерируемым ссылкам
            'param1',
            'param2',
            ...
        ),
    ...

Теперь сделаем свой генератор на основе генератора от Symfony

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php
//VendorsDir/MySpace/Core/UrlGenrator.php

namespace MySpace\Core;

use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouteCollection;

class UrlGenerator extends \Symfony\Component\Routing\Generator\UrlGenerator
{
    //тут будет список пар "параметр => значение", которые нужно давить ко всем генерируемым ссылкам
    public $through_GET_parameters = array();

    public function __construct(RouteCollection $routes, RequestContext $context) {
        parent::__construct($routes, $context);
    }

    public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) {
        $url = parent::generate($name, $parameters, $referenceType);
        if ($this->through_GET_parameters) {
            $gets = array();
            foreach ($this->through_GET_parameters as $k=>$v) {
                if ($v) {
                    $gets[] = urlencode($k) . '=' . urlencode($v);
                } else {
                    $gets[] = urlencode($k);
                }
            }
            // добавим пару символов "&?", что бы после генерации html заменить на нужный символ
            $url .= "?".implode('&', $gets)."&?";
        }

        return $url;
    }
}

После создания генератора, туда нужно положить нужные параметры и их значения из запроса, если они там есть:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    //bootstrap.php
    use Symfony\Component\Routing\RequestContext;
    use Symfony\Component\HttpFoundation\Request;
    ...
    $generator = new \MySpace\Core\UrlGenerator($routes, new RequestContext(''));

    if(isset($config['routing']['through_GET_parameters'])) {
        foreach ($config['routing']['through_GET_parameters'] as $p) {
            $v = Request::createFromGlobals()->get($p);
            if (!is_null($v)) {
                $generator->through_GET_parameters[$p] = $v;
            }
        }
    }
    ...

После генерации html страницы, мы будем иметь ссылки вида:

1
  http://domain/module/route/to/action?param1=val1&param2=val2&??custom_param1=cval1&...

В этих ссылках нужно заменить «&??» и «&?» на &

1
2
3
4
5
6
    //view.php
    ...
    $html = str_replace('&??', '&', $html);
    $html = str_replace('&?', '&', $html);
    echo $html;
    ...

Но есть проблема: когда url генерируем в JS, то такая подмена не произойдет. Поэтому в JS генерируем url «с умом»:

1
2
3
4
    ...
    //в url к данному моменту уже лежит какая то ссылка. Поэтому нужно определить какой символ нужно поставить перед нашими параметрами
    url += ((url.search(/\?/) == -1) ? '?' : '&') + "custom_param2=test"
    ...

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *