简体   繁体   中英

How to generate a link to a page with a request variable not in the url in symfony2

I am using Prismic.io in Symfony2

In Prismic, you have to query a document by the ID. So for instance, I have this in my twig template:

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

which generates this url:

/U3zRuQEAADoAGg7D/slug-of-document

I get the hexadecimal id in the controller and can query the page successfully. However, using the ID is not very human friendly. I would like to generate a url that can pass the id variable in the request, but not be visible in the url. Is this possible?

For clarification, here is the code through the process. I have a page that lists all blog articles by title:

<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>

When the title is clicked, it goes to the pageDetail Action:

/**
     * @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');
    }

I would like something more like this, so the id is in the request and can be used to query, but not visible:

    /**
    * @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');

}

I have tried this, but I get an undefined variable exception, making me think I am not sending the ID properly in the request.

I dont think this is even possible really, because the ID would need to be represented somehow, even when not coming from this particular page. Just wanted to throw out the question and see if it's possible.

Why not use simple js to submit a hidden form ?

sth like this jquery-code

<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>

and in controller just do :

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

but its not too cool that your url can only handle post-requests, so its only reachable through a form, thats not too user-friendly but it seems this is what you want

I don't think it's possible, as the HTTP method is GET, you should pass the variables over the url.

Maybe there is a solution, if you do the request with POST method. You can set up a form, or use jQuery to create POST request if the user clicks on the link. With this, you can pass variables to the controller. But if all the links need this id variable, it's not a too comfortable way. Maybe if you write a global JavaScript function for link generation, and use that function instead of {{ path('path_name') }} .

Another method can be if you redirect the user immediately after the controller action is fired. You pass the variables with GET method, and the id is in the url. in the fired action you save this variable to a session and redirect the user to another action, where the variable is not needed in the url. Then you can use the id in your new controller by get the session variable. It's not a nice solution as well, because you have to create a lot of redundant action.

I would recommend the JavaScript version if it's only needed in some pages, or you should consider to not to hide the id. Maybe it's not worth the effort to do that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM