I was just browsing the mozilla.com site and noticed their url's had a pretty neat structure.
https://addons.mozilla.org/en-US/firefox/browse/type:1/cat:22/sort:popul...
Specifically I am mentioning the /Key:Value/ structure.
Would this be a good thing to support in the controller, Key Value pairs for the zone and page params? I would think this would be well received. What do you all think?
It would free us from a few of the limitations of the current method, and would easily be backwards compatible (if no ":" is in the string, process the previous method).
John, Rick, Others: How hard do you think this would be to implement?
BC
It would be a backwards compatibility issue. As of now, url params can contain ":" with no side effects. In addition, we need to add escaping, which would break more the BC. We can add a per-zone configuration(which would have to initially default to off).
zone_something extends zone { var $paramsHaveKeys = 1; ... function pageDefault($p, $z) { //url is index.php/something/itsa:pizza/default/pizza:pie assert($z['itsa'] == 'pizza'); assert($p['pizza'] == 'pie'); //leave current methods in place as well... assert($p[1] == 'pie'); //or should old methods not involve the keys? assert($p[1] == 'pizza:pie'; } }It also means that there needs to be a method of escaping the :, so that the parameters can still contain a :.
function urlparamescape($param) { return str_replace(':', '[:]', str_replace(']', ']]', str_replace('[', '[[', $param))); }And there also needs to be a method of unescaping...
function urlparamunescape($param) { return str_replace(']]', ']', str_replace('[[', '[', str_replace('[:]', ':', $param))); }And now, when you build an url, you need to make sure that if your param _can_ contain a '[', ']', or ':', then you _must_ escape it.
zone_something extends zone { function zone_something() { $this->setZoneParams(array('itsa')); } function makePath($param1) { return '/something/' . urlparamescape('itsa') . ':' . urlparamescape($param1); } function makePageParams($params) { $answer = ''; foreach($params as $key => $value) { $answer .= '/' . urlparamescape($key) . ':' . urlparamescape($value); } return $answer; } }Is it worth all the escaping that needs doing? Well most of it can be encapsulated. In fact, makePath should be defined in zone, so that it doesn't require someone to redefine it all the time. makePageParams could also be in zone, so it wouldn't need to be defined. The big change would be using those functions instead of typing urls out directly.
Another approach to named page parameters
To me, the biggest advantage of the key:value parameter is that it allows named page parameters. Zone parameters are already named, but page parameters are not. I realized that I had already implemented a way of doing named page parameters in a more ad-hoc fashion.
function getParamMap($params) { $searchValues = array(); for($i = 1; $i + 1 < count($params); $i+=2) { $searchValues[$params[$i]] = $params[$i+1]; } return $searchValues; } function pageDefault($params) { //url is index.php/something/default/itsa/pizza/pizza/pie $params = getParamMap($params); assert($params['itsa'] == 'pizza'); assert($params['pizza'] == 'pie'); }This doesn't have the same aesthetic value as key:value, but it also does not require as much work, either as the user, or in the framework.
Is there an argument that the above is not sufficient? should getParamMap be in app/utils.php, or in zone/zone.php?
Counterpoint
There are a few advantages of having the key:value pairing for page parameters.
The two most obvious ones I see are flexibility and flexibility.
With keys the order becomes irrelevant.
Additionally the number of page params could also be irrelevant, as the key delimiter would determine if the next value in the url string is a param or page/zone name.
Obviously both of those approaches are not easily transitioned to, but allow for a much more flexible controller than currently in use.
Your solution also would work in a similar manner, but it is more confusing, not in use, but in viewing the url, it isn't clear what is a key and what is a value, or what is a subzone... etc.
----------------------------------
Co-Author of Zoop Framework
experimental
This seems like it would be a good candidate for rick's experimental branch. The benefits are substantial, however, the wrapping that would need to be done to keep BC is more than it would be worth in the current controller. By rolling it out with the new controller, we can define more strictly the syntax for url parameters, and allow users to migrate.
Our offline discussion about this topic.
(1:48:34 PM) John: Are you envisioning something like:
(1:48:53 PM) John: index.php/user/edit/userId:1/pageParam:3
(1:49:02 PM) John: where userId is a zone param and pageParam is a page parameter?
(1:49:25 PM) Steve Francia: I would think it would be index.php/userId:1/edit/pageParam:3
(1:49:31 PM) John: ok, that's good
(1:49:33 PM) Steve Francia: still separate the two
(1:49:56 PM) Steve Francia: then we can say whatever is between the zone and the subzone or page is a zone param
(1:50:04 PM) Steve Francia: and whatever is after the page is a page param
(1:50:27 PM) John: At which point there is the possibility of required zone params, and optional zoneparams
(1:50:34 PM) Steve Francia: right
(1:50:50 PM) Steve Francia: and the order no longer matters
(1:51:04 PM) Steve Francia: because right now you just need to know which order to expect it in
(1:51:26 PM) John: although, you're going to be creating urls programmatically, so order might not matter, but it's going to be consistent.
(1:51:35 PM) Steve Francia: yeah
(1:53:07 PM) John: Everytime we have started building urls manually in our apps, we have come to regret it when we needed to shift things around, and then had to go back, and switch all those places.
(1:53:21 PM) Steve Francia: we should have always done it programatically
(1:53:35 PM) John: At the moment, there's no built-in helpers to do that.
(1:53:49 PM) Steve Francia: this approach also lets you use a function (in both php and smarty) called getUrl
(1:53:56 PM) Steve Francia: which takes a zone required
(1:54:01 PM) Steve Francia: page optional
(1:54:09 PM) Steve Francia: and hash optional
(1:54:21 PM) Steve Francia: and will create the url for you
(1:54:31 PM) Steve Francia: sorry two hashes
(1:54:49 PM) John: getUrl($zone, $zparams, $page, $pparams)
(1:54:58 PM) Steve Francia: perhaps zone is also optional, and defaults to current zone and current zone params
(1:55:14 PM) Steve Francia: probably two different helper functions
(1:55:29 PM) Steve Francia: getCurZoneUrl( $page, $pparams)
(1:55:46 PM) John: zone_user::makePath($zparams, $page, $pparams)
(1:56:03 PM) Steve Francia: sure, could do that as well, but that wouldn't work as well in smarty
(1:56:23 PM) John: We already have $this->getPath(), which gets you the current path
(1:57:37 PM) John: or rather, $this->getZonePath()/$this->getZoneUrl()
(1:58:17 PM) John: $this->makePath($zparams, $page, $pparams);
(2:02:31 PM) John: {makepath zone="user" zparams=$zparams page=$page pparams=$pparams}
(2:02:41 PM) Steve Francia: that works fine
(2:04:35 PM) Steve Francia: {$SCRIPT_URL} shouldn't be necessary anymore, but I don't see how we can avoid it
(2:07:08 PM) John: as for {$SCRIPT_URL}, it might be safe, if you did "index.php/stuff", but with mod_rewrite, that would immediately break.
(2:07:23 PM) Steve Francia: yeah, i would prefer if make_url did all that
(2:07:32 PM) Steve Francia: or something simpler, but like i said i don't see how
(2:08:26 PM) John: {makeurl} != {makepath}, we could have {makeurl zone="base" zparams=$zparams}/{makepath zone="admin" page="sysadmin"}
(2:08:29 PM) Steve Francia: but requiring a base at the beginning of each url seems to me to be unnecessary
(2:08:43 PM) Steve Francia: i like that better
(2:08:51 PM) Steve Francia: make it all programmatic
(2:08:55 PM) Steve Francia: then changes are simpler
(2:09:15 PM) John: it can be more confusing, as makeurl must only be used for the first zone in the url.
(2:09:45 PM) John: but most people only use one zone in the url.
(2:09:48 PM) Steve Francia: i just don't like referencing a variable each time you create a url
(2:09:50 PM) Steve Francia: right
(2:11:53 PM) John: just realized, we don't need the slash between makeurl and makepath.
(2:11:59 PM) John: every path begins with a /
(2:12:01 PM) Steve Francia: yup
(2:12:10 PM) Steve Francia: this would solve that issue as well
(2:12:40 PM) Steve Francia: probably a good thing to implement now so that later transitioning to the key:value approach is seamless
(2:18:53 PM) John: ok, so I have created a zone::makePath($z, $page, $p), a zone::makeUrl($z, $page, $p), and a makePath($zone, $z, $page, $p)
(2:19:07 PM) John: the smarty functions can use those functions.
(2:19:17 PM) John: and the zones can use them cleanly too.
----------------------------------
Co-Author of Zoop Framework