skip to Main Content

Is there a way that I can generate multiple URLs within the same controller that use the same structure?

#[Route('/project/posts/{id}', name:"project-post-view")] //old url
#[Route('/project/posts/{post_ulid}', name:"project-post-view")]
#[Route('/project/posts/{slug}', name:"project-post-view")] // alternative url
function projectViewPost(int $id, string $post_ulid, string $slug, ManagerRegistry $doctrine)
{
    //Function stuff here...
}

The ID url is specifically for legacy emails, where ideally we’d like to forward to the ulid version. Alternatively, if a post uses a slug, it should be in place of the ulid. Is this the format used or how exactly is this defined to fit these conditions?

2

Answers


  1. You have to use Parameter Validation

    The requirements option defines the PHP regular expressions that route parameters must match for the entire route to match.

    So your routes should look something like this:

    #[Route('/project/posts/{id}', name:"project-post-view", 
      requirements: ["id" => "d+"]
    )] //old url
    #[Route('/project/posts/{post_ulid}', name:"project-post-view", 
      requirements: ["post_ulid" => "ulid-pattern"]
    )]
    #[Route('/project/posts/{slug}', name:"project-post-view", 
      requirements: ["slug" => ".+"]
    )] // alternative url
    function projectViewPost(?int $id = null, ?string $post_ulid = null, ?string $slug, ManagerRegistry $doctrine = null)
    {
        //Function stuff here...
    }
    
    Login or Signup to reply.
  2. It really depends on the difference between the parameter patterns, but you can make this work using Parameter Validation as suggested by Code Spirit.
    You need to put all three nullable parameter slugs together in one route definition:

    #[Route(
        '/project/posts/{id}{post_ulid}{slug}',
        name: "project-post-view",
        requirements: ['id' => 'd*', 'post_ulid' => '([A-Z]+-[0-9]+)?', 'slug' => '.*']
      )]
      public function testMulti(ManagerRegistry $doctrine, ?string $id = null, ?string $post_ulid = null, ?string $slug = null): Response
      {
        return new JsonResponse(['id' => $id, 'post_ulid' => $post_ulid, 'slug' => $slug]);
      }
    

    Also note that the non-optional argument $doctrine must come before all of the optional arguments.

    Tested in v 7.2 (dev):

    • /project/posts/45 returns:
      {"id":"45","post_ulid":"","slug":""}
    • /project/posts/A-45 returns:
      {"id":"","post_ulid":"A-45","slug":""}
    • /project/posts/soupy-soup returns:
      {"id":"","post_ulid":"","slug":"soupy-soup"}

    Be advised this has the potential to match all three parameters. (This is why I say it depends on the difference in the patterns):

    • /project/posts/45A-27soup returns:
      {"id":"45","post_ulid":"A-27","slug":"soup"}

    So if your patterns have the potential to overlap, it will be better to use separate functions.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search