Как сгенерировать ссылку на страницу с переменной запроса, отсутствующей в URL в symfony2

#php #symfony #twig

#php #symfony #twig

Вопрос:

Я использую Prismic.io в Symfony2

В Prismic вы должны запрашивать документ по идентификатору. Так, например, у меня есть это в моем шаблоне twig:

  <h3><a href="{{ path('postDetail', {'id': post.getId, 'slug': post.slug, 'ref': ctx.maybeRef}) }}">{{ title }}</a></h3>
  

который генерирует этот URL:

 /U3zRuQEAADoAGg7D/slug-of-document
  

Я получаю шестнадцатеричный идентификатор в контроллере и могу успешно запросить страницу. Однако использование идентификатора не очень удобно для человека. Я хотел бы сгенерировать URL-адрес, который может передавать переменную id в запросе, но не быть видимым в url. Возможно ли это?

Для пояснения, вот код процесса. У меня есть страница, на которой перечислены все статьи блога по названию:

 <article class="blogEntry">
    {% if date is defined %}
        <small>{{ date|date("m/d/Y") }}</small>
    {% endif %}
    {% if title is defined %}
        <h3><a href="{{ path('postDetail', {'id': post.getId, 'slug': post.slug, 'ref': ctx.maybeRef}) }}">{{ title }}</a></h3>
    {% endif %}
    {% if author is defined %}
        <small class="blogAuthor">{{ author }}</small>
    {% endif %}
    {% if excerpt is defined %}
        {{ excerpt|raw }}… <a href="{{ path('postDetail', {'id': post.getId, 'slug': post.slug, 'ref': ctx.maybeRef}) }}">Continue Reading »</a>
    {% endif %}
</article>
  

При нажатии на заголовок он переходит к действию pageDetail:

 /**
     * @Route("/blog/{id}/{slug}", name="postDetail")
     * @Template()
     */
    public function postDetailAction($id, $slug)
    {
        $ctx = $this->get('prismic.context');
        $post = $ctx->getApi()->forms()->everything->ref($ctx->getRef())->query('[[:d = at(document.id, "'.$id.'")]]')->submit();
        $post = $post->getResults();

        if ($post) {
                return array(
                    'ctx' => $ctx,
                    'bgImages' => $backgroundImages,
                    'siteInfos' => $siteInfos,
                    'post' => $post
                );
        } 

        throw $this->createNotFoundException('Document not found');
    }
  

Я хотел бы что-то более похожее на это, чтобы идентификатор был в запросе и мог использоваться для запроса, но не был виден:

     /**
    * @Route("/blog/{slug}", name="postDetail")
    * @Template()
    */
    public function postDetailAction($slug)
    {
       $request = $this->getRequest();
       $request->query->get('id');
       $ctx = $this->get('prismic.context');
       $post = $ctx->getApi()->forms()->everything->ref($ctx->getRef())->query('[[:d = at(document.id, "'.$id.'")]]')->submit();
       $post = $post->getResults();

       if ($post) {
          return array(
              'ctx' => $ctx,
               'post' => $post
          );
       } 

    throw $this->createNotFoundException('Document not found');
  

}

Я пробовал это, но я получаю исключение неопределенной переменной, что заставляет меня думать, что я неправильно отправляю идентификатор в запросе.

Я не думаю, что это вообще возможно, потому что идентификатор должен быть каким-то образом представлен, даже если он не поступает с этой конкретной страницы. Просто хотел задать вопрос и посмотреть, возможно ли это.

Комментарии:

1. Уникальны ли ваши слаги? Если они были, то вам не нужно передавать идентификатор.

2. prismic.io в настоящее время не генерирует уникальные слаги, поэтому я мог бы запрашивать с помощью slug, но нет никакой гарантии, что он всегда будет уникальным.

Ответ №1:

Почему бы не использовать простой js для отправки скрытой формы?

что-то вроде этого jquery-кода

 <span class="link">{{ title }}</span>

<form class="fooForm" method="POST" action="{{ path('postDetail', {'slug': post.slug, 'ref': ctx.maybeRef}) }}" style="display:none">
        <input name="id" type="hidden" value="{{post.getId}}">
</form>




<script>
    $(document).on("click",".link",function(){
        $('.fooForm').submit();
    })
</script>
  

и в контроллере просто сделайте :

    $request = $this->getRequest();
   $id=$request->get('id');
  

но не слишком круто, что ваш URL-адрес может обрабатывать только post-запросы, поэтому он доступен только через форму, это не слишком удобно для пользователя, но, похоже, это то, что вы хотите

Ответ №2:

Я не думаю, что это возможно, поскольку HTTP-метод GET, вы должны передавать переменные по URL.

Возможно, есть решение, если вы выполняете запрос с помощью метода POST. Вы можете настроить форму или использовать jQuery для создания POST-запроса, если пользователь нажимает на ссылку. С помощью этого вы можете передавать переменные контроллеру. Но если всем ссылкам нужна эта переменная id, это не слишком удобный способ. Может быть, если вы напишете глобальную функцию JavaScript для генерации ссылок и будете использовать эту функцию вместо {{ path('path_name') }} .

Другим способом может быть перенаправление пользователя сразу после запуска действия контроллера. Вы передаете переменные с помощью метода GET, а id в URL-адресе. в запущенном действии вы сохраняете эту переменную в сеансе и перенаправляете пользователя на другое действие, где переменная не нужна в url. Затем вы можете использовать id в своем новом контроллере, получив переменную сеанса. Это также не очень хорошее решение, потому что вам приходится создавать много избыточных действий.

Я бы рекомендовал версию JavaScript, если она нужна только на некоторых страницах, или вам следует подумать о том, чтобы не скрывать идентификатор. Возможно, это не стоит усилий, чтобы сделать это.

Комментарии:

1. Спасибо за предложения. Я рассмотрю вариант JS, но вы, возможно, поправите, что, возможно, это не стоит усилий. В большинстве современных веб-приложений просто кажется, что уникальный фрагмент — это в основном идентификатор. Я не уверен, почему идентификатор используется prismic, поскольку он не дружелюбен к человеку и несколько уродлив.