Zend Framework - setting up user-friendly URLs with routes and regex
Asked Answered
U

3

9

I have two issues with user-friendly URLs.

I have a router set up as follows:

  • The actual URL is http://www.example.com/course/view-batch/course_id/19
  • I want a friendlier URL http://www.example.com/java-training/19

I have setup the following route in application.ini:

resources.router.routes.viewbatchcourse.route = "/:title/:course_id/"
resources.router.routes.viewbatchcourse.defaults.controller = course
resources.router.routes.viewbatchcourse.defaults.action = view-batch
resources.router.routes.viewbatchcourse.reqs.course_id = "\d+"

This works perfectly well.

Now I have a new page - which contains user reviews for Java

  • The actual URL is http://www.example.com/course/view-reviews/course_id/19
  • I want a friendlier URL http://www.example.com/java-reviews/19

I realize its not possible because one route is already setup to match that format.

So I was thinking if its possible to use regex and check if title contains "reviews" then use this route.

I tried this approach, but it doesn't work. Instead, it opens the view-batch page:

resources.router.routes.viewreviews.type = "Zend_Controller_Router_Route_Regex"
resources.router.routes.viewreviews.route = "/:title/:course_id"
resources.router.routes.viewreviews.defaults.controller = "course"
resources.router.routes.viewreviews.defaults.action = "view-reviews"
resources.router.routes.viewreviews.reqs.course_id = "\d+"
resources.router.routes.viewreviews.reqs.title =  "\breviews\b"

The closest I have got this to work is

resources.router.routes.viewreviews.route = "/:title/:course_id"
resources.router.routes.viewreviews.defaults.controller = "course"
resources.router.routes.viewreviews.defaults.action = "view-reviews"
resources.router.routes.viewreviews.reqs.course_id = "\d+"
resources.router.routes.viewreviews.reqs.title =  "reviews"

Now if I enter the URL http://www.example.com/reviews/19, then the view-reviews action gets called. Is it possible - to check if title contains the word "reviews" - then this route should be invoked?


Going back to my earlier working route for http://www.example.com/java-training/19:

resources.router.routes.viewbatchcourse.route = "/:title/:course_id/"
resources.router.routes.viewbatchcourse.defaults.controller = course
resources.router.routes.viewbatchcourse.defaults.action = view-batch
resources.router.routes.viewbatchcourse.reqs.course_id = "\d+"

The number 19 is the course id, which I need in the action to pull the details from the database.

But when the page is displayed, I dont want the number 19 visible.

I just want the URL to be http://www.example.com/java-training

Is this possible?

Uvula answered 20/5, 2015 at 9:5 Comment(0)
P
1

1) You can use Route_Regex to achieve what you want

protected function _initRoutes()
{
    $router = Zend_Controller_Front::getInstance()->getRouter();

    $route = new Zend_Controller_Router_Route_Regex(
        '([a-zA-Z]+)-reviews/(\d+)',
        array(
            'module' => 'default',
            'controller' => 'course',
            'action'     => 'view-reviews'
        ),
        array(
            1 => 'language',
            2 => 'course_id',
        )
    );
    $router->addRoute('review', $route);

    $route = new Zend_Controller_Router_Route_Regex(
        '([a-zA-Z]+)-training/(\d+)',
        array(
            'module' => 'default',
            'controller' => 'course',
            'action'     => 'view-batch'
        ),
        array(
            1 => 'language',
            2 => 'course_id',
        )
    );
    $router->addRoute('training', $route);        
}

2) For the second point I can't see how it can be possible as is.

One thing you could do though is to use the name of the course, if you have one, to display an url like :

www.xyz.com/java-training/my-awesome-course-19
www.xyz.com/java-training/19/my-awesome-course

It would be pretty easy using the routes i mentionned above.

Plagiary answered 28/5, 2015 at 22:6 Comment(0)
C
0

for question 1. I think you can solve this problem quite simply by altering the route. You don't need to have :title as part of the route, instead it can be hard coded in your case. I would recommend the following configuration.

resources.router.routes.viewbatchcourse.route = "/java-training/:course_id/"
resources.router.routes.viewbatchcourse.defaults.controller = course
resources.router.routes.viewbatchcourse.defaults.action = view-batch
resources.router.routes.viewbatchcourse.defaults.title = java-training
resources.router.routes.viewbatchcourse.reqs.course_id = "\d+"

resources.router.routes.viewreviews.route = "/java-reviews/:course_id/"
resources.router.routes.viewreviews.defaults.controller = course
resources.router.routes.viewreviews.defaults.action = view-reviews
resources.router.routes.viewreviews.defaults.title = java-reviews
resources.router.routes.viewreviews.reqs.course_id = "\d+"

For question 2. As you describe it, simply no.

Centuplicate answered 22/5, 2015 at 21:20 Comment(2)
Hey Jeremy - hard coding is not an option because "java-reviews" is for one course java - there will be 10 other pages for other other courses like "php-reviews" - "python-reviews" etc - so thats why I was looking for a regex that just looks for the word reviews in the URL - ThanksUvula
Your option is still hard coding--but you just hard code the end. route = /:title-reviews/:course_id and route = /:title-training/:course_id.Centuplicate
M
0

Re: Q1. I haven’t tested this, but hopefully it is pointing you in the direction you want to go.

resources.router.routes.viewreviews.type = "Zend_Controller_Router_Route_Regex"
resources.router.routes.viewreviews.route = "(.+)-reviews/(\d+)"
resources.router.routes.viewreviews.defaults.controller = "course"
resources.router.routes.viewreviews.defaults.action = "view-reviews"
resources.router.routes.viewreviews.map.1 = "title"
resources.router.routes.viewreviews.map.2 = "course_id"

Re: Q2. I think you'd need to either forward the user to another (parameterless) URL or handle this via javascript. See Modify the URL without reloading the page.

Mythological answered 28/5, 2015 at 3:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.