SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 49

Thread: URL mapping

  1. #1
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    URL mapping

    I've been working on a mapping sceme for urls to controllers and actions. At this point it works fine. I don't know if I've every seen anyone doing it quite like this so I wanted to get some feedback.

    Example 1

    http://localhost/shop/cart/add/id/43

    Would get a controller called ShopCartController inside of the controller directory like:

    controllers/shop/cart.php

    Then the ShopCartController::add() action is called. The id parameter is available in the request object, which is passed to the action method.


    Example 2

    http://localhost/about

    Would get a controller called DefaultController, because the about controller does not exist, and the default controller has an action called about().

    Example 3

    http://localhost/admin/product/edit/id/54

    This would call the AdminProductController (controllers/admin/product.php) and call it's edit() action. "id" is available as a parameter in the request object.

    -------

    Basically, my URL parser starts at the begining of the path and iterates through each value checking to see if it is a valid controller OR folder OR action

    If it finds a value that is NOT a controller, it checks to see if the last found controller (or default controller if no previous) in the path has an action matching the current path fragment. If it does, the remaining path is paired into parameters. If not, the path from that point is paired into parameters and the default action is called.

    So, if the ShopCartController didn't exist, the ShopController::default() action would be called. At that point, "add" would be a key with a value of "is" and "43" would be a key with no value.

    This all sounds confusing, but it actually works very nicely. If you (anyone) is interested, I'd be happy to post the code so you can see how it works.

    I'm just curious to see what people think of this, and ultimately maybe get some feedback on the code I have.

    - matt

  2. #2
    SitePoint Zealot
    Join Date
    May 2001
    Posts
    193
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    i'd be interested.

  3. #3
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    OK, I've made an archive of what I have. What are your thoughts?

    -matt
    Attached Files Attached Files

  4. #4
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    > I'm just curious to see what people think of this, and ultimately maybe get some feedback on the
    > code I have.

    I can't say for good or bad that there would be enough flexibility in the approach that you've taken; I would advice that you take a look at Ruby On Rails to see how that does it though

    On that point, Zend Framework has a proposal at the moment that accomplishes the route approach but be aware that from what testing I have done with the SVN that there are a few bugs I noted...

    I fixed the issues I had, now need to find the time to see if anyone else has had issues via the frameworks mailing list

    Send off a private message to Jarred (Ren) to see what he has to say I suppose?

  5. #5
    SitePoint Zealot Serberus's Avatar
    Join Date
    Oct 2005
    Location
    Herts, UK
    Posts
    113
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Looks good. Regarding verbs in your URLs (add, edit etc), I think it's worth reading this thread, particularly HarryF's post, about REST.

    Update: While I'd respect the URL theme REST outlines I would not go with HTTP Auth due to it's short comings (no logout, plain text storage of login details by the browser, ugly login box that does not fit with the theme of your site).

  6. #6
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Serberus
    Update: While I'd respect the URL theme REST outlines I would not go with HTTP Auth due to it's short comings (no logout, plain text storage of login details by the browser, ugly login box that does not fit with the theme of your site).
    Most browsers allow you to do a logout, although it's not standard. It doesn't bother me a lot.
    Storing plain text is something you often see with other solutions aswell. If you see it as a problem, use the Digest-mode to authenticate with. Or get a SSL certificate.

  7. #7
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    I can't say for good or bad that there would be enough flexibility in the approach that you've taken; I would advice that you take a look at Ruby On Rails to see how that does it though

    Send off a private message to Jarred (Ren) to see what he has to say I suppose?
    Hey thanks for looking. What do you mean in terms of flexibility? You mean something like routes? I actually planned on adding that when the need came. I know that this setup would allow for routes without much hassle. If not routes, what do you mean? The thing I like about this is that you can nest your controllers, based off of the content structure of your site. Also, there is no config file.

  8. #8
    SitePoint Zealot Serberus's Avatar
    Join Date
    Oct 2005
    Location
    Herts, UK
    Posts
    113
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Just to bounce ideas around, has anyone ever seen a set up where the dispatcher only examines the first element of the REQUEST_URI to instantiate the appropriate controller, then queries that controller for the rest of the mapping instructions (where the action would be, or any product/article IDs)? Or does this sounds like a horrible way to fragment your mapping/route data through your controllers?

  9. #9
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    > What do you mean in terms of flexibility?

    The point of url mapping is that the dependence of selecting the required controller and action are independent (separate) from how the url is composed; By flexibility you do not have this with the approach that you've taken at the moment

    I'm not a Ruby (or Ruby On Rails) fan but God I've got to give due credit to the framework as routes delivers that separation nicely...

  10. #10
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Serberus
    Just to bounce ideas around, has anyone ever seen a set up where the dispatcher only examines the first element of the REQUEST_URI to instantiate the appropriate controller, then queries that controller for the rest of the mapping instructions (where the action would be, or any product/article IDs)? Or does this sounds like a horrible way to fragment your mapping/route data through your controllers?
    Funny ... I'm putting the final touch on a library which does exactly that. http://svn.sourceforge.net/viewcvs.cgi/konstrukt/ if you're interested. (And sorry for hijacking your thread matt)

  11. #11
    SitePoint Zealot Serberus's Avatar
    Join Date
    Oct 2005
    Location
    Herts, UK
    Posts
    113
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    Funny ... I'm putting the final touch on a library which does exactly that. http://svn.sourceforge.net/viewcvs.cgi/konstrukt/ if you're interested. (And sorry for hijacking your thread matt)
    Great, I'll check it out! I figured combining this part in the controller had it's advantages because if you refactor your controller you've easy access to tweak the mapping data as well, no need to modify additional classes such as ActionMapper.

    Sorry for the hijack!

  12. #12
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Following original script taken from SVN proposals of Zend Framework; Matt, does this give you a better idea of routes?

    PHP Code:
    class Route {
            const 
    URL_VARIABLE ':';
            const 
    REGEX_DELIMITER '#';
            const 
    DEFAULT_REGEX '[a-z0-9\-_]+';
            
            private 
    $parts;
            private 
    $defaults = array();
            private 
    $required = array();
            
            public function 
    __construct$route$defaults = array(), $required = array() ) {
                
    $route trim$route'/' ); 
                
    $this -> defaults array_merge$this -> defaults$defaults );
                
    $this -> required array_merge$this -> required$required );
                
                foreach( 
    explode'/'$route ) as $position => $part ) { 
                    if( 
    self::URL_VARIABLE == $part[0] ) { 
                        
    $name substr$part);
                        
    // added fix here
                        // removes : from string, ie
                        // :controller, :action, et al becomes controller, action, et al
                        
    $realname substr$name);
                        
    // following statement uses $realname instead of originally using $name
                        // 13 apr 2006 les quinn
                        
    $regex = isset( $required[$realname] )? $required[$realname]: self::DEFAULT_REGEX;
                        
    $this -> parts[$position] = array( 'name' => $name'regex' => $regex );
                    } else { 
                        
    $this -> parts[$position] = array( 'regex' => preg_quote$partself::REGEX_DELIMITER ) );
                    }
                }
            }
            
            public function 
    match$path ) { 
                
    $values $this -> defaults;
                
    $path explode'/'trim$path'/' ) ); 
                
                foreach( 
    $this -> parts as $position => $part ) { 
                    
    $name = isset( $part['name'] )? $part['name']:null
                    
    $regex self::REGEX_DELIMITER.'^'.$part['regex'].'$'.self::REGEX_DELIMITER.'i';
                    
    // added fix here
                    
    $realname substr$name); 
                    if( !empty( 
    $path[$position] ) && preg_match$regex$path[$position] ) ) {
                        if( !
    is_null$name ) ) { 
                            
    // following statement(s) uses $realname instead of originally using $name
                            // 13 apr 2006 les quinn
                            
    $values[$realname] = $path[$position];
                        }
                    } else if( !
    is_null$name ) && isset( $this -> defaults[$realname] ) ) { 
                        continue;
                    } else { 
                        return 
    false;
                    }
                }
                return 
    $values;
            }
            
            public function 
    assemble$data ) {
                
    // ... not got around to this yet ;)

            
    }
        }
        
        class 
    Router {
            private 
    $routes = array();
            
            public function 
    __construct() {}
            public function 
    addRoute$map$defaults = array(), $required = array() ) {
                
    $this -> routes[] = new Route$map$defaults$required );
            }
            
            public function 
    route() {
                
    $path $_SERVER['REQUEST_URI']; 
                if( 
    strstr$path'?' ) ) {
                    
    $path substr$path0strpos$path'?' ) );
                }
                
                foreach( 
    $this -> routes as $route ) {
                    if( 
    $parameters $route -> match$path ) ) {
                        return 
    $parameters;
                        
    // break;
                    
    }
                }
                return array();
            }
        }
        
        
    $router = new Router();
        
    // archives is static parameter and is the controller portion of the url
        
    $router -> addRoute'archives/:action/date/:yrs/:mth/:day'
            array( 
    'action' => 'tmp_action_index''yrs' => '2006''mth' => '1''day' => '1' ),
            array( 
    'action' => '[a-z]+''yrs' => '[0-9]{4}''mth' => '[0-9]{2}''day' => '[0-9]{2}' ) );
        
        
    // controller, action with static parameter (category), with additional (may be optional) parameter
        
    $router -> addRoute':controller/:action/category/:category'
            
    // defaults are used where there are no matched parameter in url
            
    array( 'controller' => 'index''action' => 'index''category' => 'home' ),
            
    // requires are to determine the matched parameter from url validates against a given regex
            // if no regex given for a specific parameter in this array, a default regex is used instead, ie
            // the default regex ([a-z0-9\-_]+) will be used to validate the category parameter
            
    array( 'controller' => '[a-z]+''action' => '[a-z]+' ) );
        
        
    // controller, action, with static parameter (date), with additional (may be optional) parameters
        
    $router -> addRoute':controller/:action/date/:yrs/:mth/:day'
            
    // uses defaults for year, month and day
            // would use php's date functions to set defaults to current date
            
    array( 'controller' => 'index''action' => 'index''yrs' => '2006''mth' => '1''day' => '1' ),
            
    // only specify the requires where the regex is different from the default regex
            
    array( 'controller' => '[a-z]+''action' => '[a-z]+''yrs' => '[0-9]{4}''mth' => '[0-9]{2}''day' => '[0-9]{2}' ) );
        
        
    // controller, action and an id only
        
    $router -> addRoute':controller/:action/id/:id'
            array( 
    'controller' => 'index''action' => 'index''id' => '' ),
            array( 
    'controller' => '[a-z]+''action' => '[a-z]+''id' => '[0-9]+' ) );
        
        
    // default route
        // controller and action only
        
    $router -> addRoute':controller/:action'
            array( 
    'controller' => 'controller_index''action' => 'action_index' ), 
            array( 
    'controller' => '[a-z]+''action' => '[a-z]+' ) );
        
    $rs $router -> route(); 
    Hope this is of some use anyways, it's helped me to understand it some more anyways.

  13. #13
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    One problem is the _removeSlashes() function is recursive. Making it possible to crash the server by

    http://localhost/shop/cart/add/id/43?a=[][][][][] ..lots more [].. [][][][][]

  14. #14
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ren
    One problem is the _removeSlashes() function is recursive. Making it possible to crash the server by

    http://localhost/shop/cart/add/id/43?a=[][][][][] ..lots more [].. [][][][][]
    There's a limit to the size of a querystring, so I would guess that it isn't a problem. Did you try it ?
    Either way, that should cause a stack overflow, which just crashes the running pocess of PHP. I don't think it would cause any leaks or take down apache ?

  15. #15
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    There's a limit to the size of a querystring, so I would guess that it isn't a problem. Did you try it ?
    Either way, that should cause a stack overflow, which just crashes the running pocess of PHP. I don't think it would cause any leaks or take down apache ?
    It does crash. Im not actually sure there is a limit, outside of the browsers (4k for mozilla, and something smaller for IE). but

    file_get_contents('http://localhost/index.php?a='.str_repeat('[]', 10000); will crash things

    One method, taken from php|architect’s Guide to PHP Security by Ilia Alshanetsky, is to use iteration instead.
    PHP Code:
    if (get_magic_quotes_gpc()) 
    {
         
    $input = array(&$_GET, &$_POST, &$_COOKIE, &$_ENV, &$_SERVER);
         while (list(
    $k,$v) = each($input))
         {
             foreach (
    $v as $key => $val
             {
                 if (!
    is_array($val)) 
                 {
                     
    $input[$k][$key] = stripslashes($val);
                     continue;
                 }
                 
    $input[] =& $input[$k][$key];
             }
         }
         unset(
    $input);


  16. #16
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    There's a limit to the size of a querystring, so I would guess that it isn't a problem.
    Per RFC 2616 Section 3.2.1 there is no defined limit in the specification, you are therefore only dealing with implementation (both server and client) limitations.

    Quote Originally Posted by RFC
    RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1

    3.2.1 General Syntax

    URIs in HTTP can be represented in absolute form or relative to some
    known base URI [11], depending upon the context of their use. The two
    forms are differentiated by the fact that absolute URIs always begin
    with a scheme name followed by a colon. For definitive information on
    URL syntax and semantics, see "Uniform Resource Identifiers (URI):
    Generic Syntax and Semantics," RFC 2396 [42] (which replaces RFCs
    1738 [4] and RFC 1808 [11]). This specification adopts the
    definitions of "URI-reference", "absoluteURI", "relativeURI", "port",
    "host","abs_path", "rel_path", and "authority" from that
    specification.

    The HTTP protocol does not place any a priori limit on the length of
    a URI. Servers MUST be able to handle the URI of any resource they
    serve, and SHOULD be able to handle URIs of unbounded length if they
    provide GET-based forms that could generate such URIs. A server
    SHOULD return 414 (Request-URI Too Long) status if a URI is longer
    than the server can handle (see section 10.4.15).

    Note: Servers ought to be cautious about depending on URI lengths
    above 255 bytes, because some older client or proxy
    implementations might not properly support these lengths.
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  17. #17
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    Following original script taken from SVN proposals of Zend Framework; Matt, does this give you a better idea of routes?
    Nice. Thanks for that I should have looked at that earlier. That's the kind of thing I want to add. I think there is a need though for a pre-setup default style of routing. It'd be a drag to set up routes for every application/request. That was my goal for the code I originally posted.

    Also, thanks for the solution to the recursive strip_slashes problem!

    Any other comments on the code I posted?

    -matt

  18. #18
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    > I think there is a need though for a pre-setup default style of routing.



    You could have a Factory of some sort to generate the required routes for you, ie

    PHP Code:
    // index.php
    Map::getInstance() -> load'path/to/xml/file.xml' ); 
    This would then fetch the routes to use and preload them, so you could use something like this for example,

    PHP Code:
    if( Map::getInstance() -> match$path ) ) {
    // found a suitable route...
    }
    // ... 
    The Map::match( $path ); class method would iterate over the routes that were previously loaded, and return the appropriate one for you

  19. #19
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    > Any other comments on the code I posted?

    I had a brief look but not had the time to delve too much into it unfortunately... Any luck I'll get a chance to look at them properly soon

  20. #20
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    One thing I'm not clear on is how "stable" indexed parameters are compared to paired params? Example:

    /myapp/listview/per-page/4/sort-by/name

    Now, with indexed params:

    /myapp/listview/4/name

    Short and sweet... But what happens if the url changes: no per-page value? As in:

    /myapp/listview/name

    Doesn't "name" become the new per-page value? With paried params, this works fine:

    /myapp/listview/sort-by/name

    How is this dealt with? It seems like it's MORE work to validate the value type of each param than just using pairs. I know it's good practice to validate, but do you see what I'm getting at?

    -matt

  21. #21
    SitePoint Enthusiast
    Join Date
    Apr 2004
    Location
    US
    Posts
    51
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I use paired params too, for easy conversion between url PATH/PARAM and accessing params, although it looks a bit more messy :-)

  22. #22
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So... this is more related to the code I posted. I don't mind anyone else "hijacking" the thread as this is all good and url related!

    Anyway, what about keeping the auto-routing I have in place for controllers and actions. But in the controller I create a new variable that defines the parameter mapping. Something like:

    PHP Code:
    class DefaultController {
        
        var 
    $param_mapping = array(
            
    'music' => array(
                
    ':id' => array('default' => 1'pattern' => '[0-9]+'),
                
    ':state' => array('default' => 'play''pattern' => 'play|info')
            )
        );
        
        function 
    action_index(& $request){
            
    // this would get the normal paired params...
        
    }
        
        function 
    action_music(& $request){
            
    // this would get the mapped params as defined by the $param_mapping var
        
    }

    ?

    EDIT: so it's a little more clear... the fragments of the url are defined by the order the params are set. So this url would be valid with the mapping above:

    default/music/3/info

    And the $request would have:

    $request->id == 3
    $request->state == 'info'

  23. #23
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You're moving very close into actually validating the input. I don't think you can do that with a pattern (regex) alone. If you really want to automate down to that level, you should probably use a programmatical approach rather than a declarative. One way could be to use callbacks, rather than patterns. Eg.:
    PHP Code:
    class DefaultController 
        function 
    DefaultController() {
            
    $this->param_mapping = array( 
                
    'music' => array( 
                    
    ':id' => array('default' => 1'condition' => 'is_numeric'), 
                    
    ':state' => array('default' => 'play''condition' => curry('preg_match''/play|info/')) 
                ) 
            ); 
        ) 
         
        function 
    action_index(& $request){ 
            
    // this would get the normal paired params... 
        

         
        function 
    action_music(& $request){ 
            
    // this would get the mapped params as defined by the $param_mapping var 
        



  24. #24
    SitePoint Member
    Join Date
    Nov 2005
    Location
    Poland
    Posts
    4
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In my older framework I did URLMapper as Filter. Firstly, URLMapper read address, write to context. Controller is starting action.

    ./application/$module/$action/(action/model/view).php
    for example:
    ./application/shop/show/(action/model/view).php

    PHP Code:
    class URLMapper implements IFilterComponent {
        
    /**
         * DOT => example: /
         *
         * @access private
         * @since  1.0
         * @type   string
         */
                
    private $dot THRORIN_DOT;
                
        
    /**
         * Using $_GET
         *
         * @access private
         * @since  1.0
         * @type   bool
         */
                
    private $uGET THRORIN_UGET;
                private 
    $link THRORIN_MAIN_LINK;
                
                
    /**
                * Execution method
                *
                * <br/><br/>
                *
                * <note>
                *     Function throwed by FilterChain
                * </note>
                *
                * @param Context    An object of HttpContext
                * @param chain    An object of FilterChain
                *
                * @access public
                * @since  1.0
                */                
                    
    public function execute(HttpContext $contextFilterChain $chain )
                    {
                        if(!
    $this->uGET) {
                            
    $arrParams = array();
                            
    $s  = (isset( $_SERVER['PATH_INFO'] )) ? $_SERVER['PATH_INFO'] : $this->link;
                            
    $arrParams explode$this->dotsubstr$s1, -5) );
                            
                            foreach ( 
    $arrParams as $wartosc ) {
                                
    $context->vars[] = $wartosc;
                            }
                            
                        } else {
                            foreach(
    $_GET AS $value) {
                                
    $context->vars[] = $value;
                            }
                        }
                        
                        
    # define
                        
                        
    $context->module = (isset($context->vars[0])) ? $context->vars[0] : THRORIN_MAIN_MODULE;
                        
    $context->method = (isset($context->vars[1])) ? $context->vars[1] : THRORIN_MAIN_METHOD;
                        
    $context->what = (isset($context->vars[2])) ? $context->vars[2] : THRORIN_MAIN_WHAT;
                        
                        
    # unseting
                        
                        
    unset($context->vars[0]);
                        unset(
    $context->vars[1]);
                        unset(
    $context->vars[2]);
                        
                        
    # sort

                        
    $context->vars array_values($context->vars);
                        
                        
    $tbl = array();
                        for(
    $i 0$size sizeof($context->vars); $i $size$i++ ) {
                            
    $tbl[$context->vars[$i]] = $context->vars[$i+1];
                            
    $i++;
                        }
                        
                        
    $context->vars $tbl;
                        
    $chain->nextExecute($context);
                    }


  25. #25
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by mwmitchell
    One thing I'm not clear on is how "stable" indexed parameters are compared to paired params? Example:

    /myapp/listview/per-page/4/sort-by/name

    Now, with indexed params:

    /myapp/listview/4/name

    Short and sweet... But what happens if the url changes: no per-page value? As in:

    /myapp/listview/name

    Doesn't "name" become the new per-page value? With paried params, this works fine:

    /myapp/listview/sort-by/name

    How is this dealt with? It seems like it's MORE work to validate the value type of each param than just using pairs. I know it's good practice to validate, but do you see what I'm getting at?

    -matt
    IMHO, I see no advantage of using paired params in the path, over using the query string. So /myapp/listview?sort-by=name&per-page=4.

    Perhaps using the defaults, sort-by=name and per-page=4 this would reduce to /myapp/listview.


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
  •