SitePoint Sponsor

User Tag List

Results 1 to 3 of 3
  1. #1
    SitePoint Addict bronze trophy
    Join Date
    Apr 2013
    Location
    Ithaca
    Posts
    351
    Mentioned
    6 Post(s)
    Tagged
    1 Thread(s)

    Help with complicated URL routing...

    Well right now my site has only a simple URL routing mechanism, in which the router/dispatcher simply interprets the url as domain.com/scriptpath/controller/action/param-1/param-2.../param-n. However, real life can get complicated at times, consider the AdminCP url in which you have a user controller that you can add, search, edit and delete users. The add and search actions are pretty easy to set up, but the edit and delete can be a bit tricky as you always need user id to be supplied to carry out these actions(thus always a parameter userid is required).

    What if the userid is not supplied? Well, you may either search for it in the search action, or to be directed to a special manager controller for its outer/master user controller(called UserManager in this case). This user manager either displays an HTML table showing users available in the system with links to edit or delete them(its index action), or delegates to the edit or delete action if these actions and user id are specified. If no id is specified, the manager will always show the default user table. With this, the edit and delete actions actually become actions of UserManager and sub-actions of UserController.

    Now you see how it gets complicated, the user controller now have two actions add, search, and a manager/sub-controller with two sub-actions edit, delete. The url patterns get a bit complex, as you can see below:

    domain.com/scriptpath/user/add
    domain.com/scriptpath/user/search
    domain.com/scriptpath/user/manage
    domain.com/scriptpath/user/manage/edit/1
    domain.com/scriptpath/user/manage/delete/1

    I want to design the manager as a class using the composition pattern, in which the controller has a manager property. However, the router cannot easily distinguish whether the word 'manage' represents an action or an inner controller, which creates routing problem. In simple scenario, I can make the manage a keyword for the router to search when it conducts regular expression matching. It works if the manager is the only special inner-controller, but can get quite messy when you have lots of such inner controllers.

    So what would you do if you were facing this problem? I know HMVC may work, but not sure how to design it. How about other possible ways to get it done?

  2. #2
    Community Advisor bronze trophy
    fretburner's Avatar
    Join Date
    Apr 2013
    Location
    Brazil
    Posts
    1,388
    Mentioned
    45 Post(s)
    Tagged
    12 Thread(s)
    I've never seen it done the in the way you describe, with a subcontroller object inside of a controller object.

    In this sort of situation, you could use a nested controller structure where your classes might be laid out something like this:
    Code:
    controllers
    controllers/user.php
    controllers/user/manage.php
    and then have your router try matching the nested controllers first, and if they don't exist, fallback to a main level controller. So if the URL was domain.com/scriptpath/user/manage/edit/1 it would look for controllers/user/manage.php, with an edit action, passing in the parameter 1. If that controller can't be found, it would try controllers/user.php looking for a manage action, passing edit and 1 as params.

    Although to me it seems that overcomplicates things a little. Rather than having a manage sub-controller, why not just make these actions in your user controller?
    Code:
    /user/add
    /user/edit/1
    /user/delete/1
    /user/list
    Here, user/list would be your action showing the list of all users (although I'd probably make it the default action for the user controller, so that the URL would simply be /users. For cases where the edit or delete actions are called without an id (or an invalid id) why not show a 404 error? Or if you prefer, just redirect back to the list action.

  3. #3
    SitePoint Wizard bronze trophy Jeff Mott's Avatar
    Join Date
    Jul 2009
    Posts
    1,246
    Mentioned
    16 Post(s)
    Tagged
    0 Thread(s)
    Developers sometimes talk about convention vs configuration. Your code sounds like it's heavily built around convention: URLs will always have a specific format and will always map to controllers in the same way. Personally, I think that leaves your code inflexible (hence, your current problem). I think it's better if your code relies on configuration. It lets you be as specific as you need, and you can also define generic configurations to create conventions only when it's useful.

    A configuration for all your URLs might look something like this:

    Code:
    user_add:
        path: /user/add
        params: { controller: UserController::addAction }
    
    user_search:
        path: /user/search
        params: { controller: UserController::searchAction }
    
    user_manage:
        path: /user/manage
        params: { controller: UserController::manageAction }
    
    user_manage_edit:
        path: /user/manage/edit/{id}
        params: { controller: UserController::manageEditAction }
    
    user_manage_delete:
        path: /user/manage/delete/{id}
        params: { controller: UserController::manageDeleteAction }
    Or if you want your "manage" actions to be in a different controller, then that's easy to do too. (They don't need to be nested or anything.)

    Code:
    user_manage:
        path: /user/manage
        params: { controller: UserManagerController::indexAction }
    
    user_manage_edit:
        path: /user/manage/edit/{id}
        params: { controller: UserManagerController::editAction }
    
    user_manage_delete:
        path: /user/manage/delete/{id}
        params: { controller: UserManagerController::deleteAction }
    And for URLs that do fit a generic template, like your first two, you could define a generic configuration:

    Code:
    generic:
        path: /{controller}/{action}
    "First make it work. Then make it better."


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •