olga
olga

Reputation: 969

Symfony2, How to pass array as parameter to controller action?

How to pass array as parameter to controller action using Symfony 2? Could you please write an example how to define route, which contains unknown length array as a parameter. For instance url: http://localhost:8000/blog/post/?tags=[tag1,tag2,tag3] where number of tags varies from 0 to 100. Also example controller for this route, where action returns values of tags array.

Using the following coding (see routing.yml and controller.php below) i am getting the error:

Catchable Fatal Error: Argument 3 passed to Symfony\Component\Routing\Route::__construct() must be of the type array, string given, called in C:\Bitnami\wampstack-5.5.30-0\sym_prog\dctr\vendor\symfony\symfony\src\Symfony\Component\Routing\Loader\YamlFileLoader.php on line 147 and defined in C:\Bitnami\wampstack-5.5.30-0\sym_prog\dctr\app/config\routing.yml (which is being imported from "C:\Bitnami\wampstack-5.5.30-0\sym_prog\dctr\app/config/routing_dev.yml").

url:

http://localhost:8000/blog/post/tag1
http://localhost:8000/blog/post/tag1/tag2/tag3/tag4
http://localhost:8000/blog/post/?tags=[tag1,tag2]

Below are different combinations of routing and controller files i have tried so far:

//version r1, routing.yml

blog_post_tags:
    path: blog/post/{tags}
    defaults: { _controller: DefaultController:list_postsByTagActionQ }
    requirements:
        tags : "[a-zA-Z0-9,]+"

//version r2, routing.yml

blog_post_tags:
    resource: "@BlogBundle/Controller/"
    type:     annotation
    prefix:   /blog/
    defaults: { _controller: DefaultController:list_postsByTagActionQ } 

//version r1,2-c1 , controller.php

//http://localhost:8000/blog/post/?tags=[tag1,tag2] .
/**
 * @Route("/posts/{tags}")
 * @Template()
 */
public function list_postsByTagAction($tags){
    var_dump($tags);
    return array('posts'=>['post1','post2']);
}

//version r1,2-c2 , controller.php

//url http://localhost:8000/blog/post/?tags=[tag1,tag2]
/**
 * @Route("/posts/{tags}")
 * @Method("GET")
 * @Template()
 */
public function list_postsByTagActionQ1(Request $request){
    $tags=$request->query->get('tags'); // get a $_GET parameter       
    var_dump($tags);
    return array('posts'=>['post1','post2']);
} 

//version r1,2-c3 , controller.php

//url http://localhost:8000/blog/post/?tags=[tag1,tag2]
/**
 * @Route("/posts/{tags}")
 * @Method("GET")
 * @Template()
 */
public function list_postsByTagActionQ3(Request $request, $tags){           
    var_dump($tags);
    return array('posts'=>['post1','post2']);
}

//version r3, routing.yml

blog_post_tags:
    path: blog/post/{tags}
    defaults: { _controller: DefaultController:list_postsByTagActionQ }

//version r3-c4 , controller.php

//url http://localhost:8000/blog/post/?tags=[tag1,tag2]
 public function list_postsByTagActionQ(Request $request){
    $tags=$request->query->get('tags'); // get a $_GET parameter
      var_dump($tags);
}

Upvotes: 7

Views: 15340

Answers (2)

olga
olga

Reputation: 969

Finally, i found an answer. Instead of passing an array, better encode it to a json string. Here is kind of example:

C:\Bitnami\wampstack-5.5.30-0\sym_prog\proj3_27\src\MeetingBundle\Controller\UserController.php

..
    /**
     * Displays a form to edit an existing User entity.
     *
     * @Route("/{id}/edit", name="user_edit")
     * @Method({"GET", "POST"})
     */
    public function editAction(Request $request, User $user)
    {
..
 $bredArr=array( 'user_edit' => array (  'id'=>$user->getId() ) );
..
        return $this->render( 'MeetingBundle::user/edit.html.twig', array(
            'user' => $user,
            'edit_form' => $editForm->createView(),
            'image_form' => $imageForm->createView(),
            'delete_form' => $deleteForm->createView(),
            'bredArr'=>$bredArr,
        ));

C:\Bitnami\wampstack-5.5.30-0\sym_prog\proj3_27\src\MeetingBundle\Controller\ImageController.php ..

   /**
     * Deletes a Image entity without displaying forms. nf = no forms
     *
     * @Route("/{id}/deletenf/{bredArrJ}", name="image_deletenf")
     * @Method("GET|POST")
     */    
     public function deletenfAction(Request $request, $id, $bredArrJ) 
     {

        $bredArr=json_decode($bredArrJ, $assoc = true);

            $em = $this->getDoctrine()->getManager();
            $entity = $em->getRepository('MeetingBundle:Image')->find($id);
            if (!$entity) {
                throw $this->createNotFoundException('Unable to find Image entity.');
            }
            $em->remove($entity);
            $em->flush();  

            if(array_key_exists('image_delete', $bredArr)) {
                return $this->redirect($this->generateUrl('image_index'));
            }
            else if (array_key_exists('user_edit', $bredArr)){
                return $this->redirect( $this->generateUrl('user_edit', array( 'id'=>$bredArr['user_edit']['id'] ) ) );
            }     
            else if {
                //redirect to other pages according key in $bredArr
            }
     }    

C:\Bitnami\wampstack-5.5.30-0\sym_prog\proj3_27\src\MeetingBundle\Resources\views\user\edit.html.twig

{# dispplays user, user_delete and image uplaod forms, also shows images which belongs to user, retrieving them via ManyToMany realation in User entity field "imgsuni" #}
 {% for img in user.imgsuni %}
 <br> {% include 'MeetingBundle:user:userimg.html.twig' %}
 {% endfor %}

C:\Bitnami\wampstack-5.5.30-0\sym_prog\proj3_27\src\MeetingBundle\Resources\views\user\userimg.html.twig

<img src="{{ asset( 'bundles/meeting/images/uploads/'~img.path~'' ) }}" height="100" />
<br><a href="{{  path('image_deletenf', { 'id': img.id,  'bredArrJ' : bredArr|json_encode }) }}"> Delete image </a>
"{{ img.title }}".

$bredArr is variable created in User controller edit_user action. It is used as an argument in path variable image_deletenf. I do not know how to pass it as array, but it works if encoded as Json string. I need image_deletenf action, in order to be able to redirect to paths where i want. I can delete images from user, event and comment entities, thus after deletion i would like to come back to user, event or comment instead of default image_index, thus i need this $bredArr to direct to correct entity with correct parameters.

Upvotes: 1

Sergio Ivanuzzo
Sergio Ivanuzzo

Reputation: 1922

Well, after some tries I've found next solution.

You can change your pattern in routing to this (tags : "[a-zA-Z0-9/]+"):

blog_post_tag:
    path: blog/post/{tags}
    defaults: { _controller: DefaultController:list_postsByTagActionQ }
    requirements:
        tags : "[a-zA-Z0-9\/]+"

Then you can pass http://localhost:8000/blog/post/tag1/tag2/tag3/tag4, but you still need explode() for getting parameters.

Upvotes: 3

Related Questions