10
votes

I'm trying to set up some routes in symfony2 for the following pattern:

www.myaweseomesite.com/payment/customer/{customernumber}/{invoicenumber}

Both parameters are optional - so the following scenarios must work:

www.myaweseomesite.com/payment/customer/{customerNumber}/{invoiceNumber}
www.myaweseomesite.com/payment/customer/{customerNumber}
www.myaweseomesite.com/payment/customer/{invoiceNumber}

I set up my routing.yml according to the symfony2 doc.

payment_route:
pattern:  /payment/customer/{customerNumber}/{invoiceNumber}
defaults: { _controller: PaymentBundle:Index:payment, customerNumber: null,  invoiceNumber: null }
requirements:
    _method:  GET

This works great so far. The problem is, that if both parameters are missing or empty, the route should not work. So

www.myaweseomesite.com/payment/customer/

should not work. Is there any way to do this with Symfony2?

3
How does the params look like? Do they have length specificity or just digits ? Just letters? Letters and digits? Because if they are both of any length with only digits this is impossible, since you can't know which is which.Hugo Dozois
customerNumber is a digit, invoiceNumber is a stringmarty

3 Answers

16
votes

You can define it in two routes to be sure to have only 1 slash.

payment_route_1:
    pattern:  /payment/customer/{customerNumber}/{invoiceNumber}
    defaults: { _controller: PaymentBundle:Index:payment, invoiceNumber: null }
    requirements:
        customerNumber: \d+
        invoiceNumber: \w+
        _method:  GET

payment_route_2:
    pattern:  /payment/customer/{invoiceNumber}
    defaults: { _controller: PaymentBundle:Index:payment, customerNumber: null }
    requirements:
        invoiceNumber: \w+
        _method:  GET

Please note that you might have to change the regex defining the parameters depending of your exact needs. You can look at this. Complex regex have to be surrounded by ". (Example myvar : "[A-Z]{2,20}")

4
votes

To elaborate on @Hugo answer, please find below the config with annotations :

/**
 * @Route("/public/edit_post/{post_slug}", name="edit_post")
 * @Route("/public/create_post/{root_category_slug}", name="create_post", requirements={"root_category_slug" = "feedback|forum|blog|"})
 * @ParamConverter("rootCategory", class="AppBundle:Social\PostCategory", options={"mapping" : {"root_category_slug" = "slug"}})
 * @ParamConverter("post", class="AppBundle:Social\Post", options={"mapping" : {"post_slug" = "slug"}})
 * @Method({"PUT", "GET"})
 * @param Request $request
 * @param PostCategory $rootCategory
 * @param Post $post
 * @return array|\Symfony\Component\HttpFoundation\RedirectResponse
 */
public function editPostAction(Request $request, PostCategory $rootCategory = null, Post $post = null)
{ Your Stuff }
0
votes

As per documentation:

http://symfony.com/doc/current/routing/optional_placeholders.html

set a default value for optional parameters in the annotations in the controller:

/**
* @Route("/blog/{page}", defaults={"page" = 1})
*/
public function indexAction($page)
{
   // ...
}

This way you only need one route in routing.yml