|
Hello all,
I just wanted to spread the word about something I've been working on and see what your opinions are on turning this into a proposal and possibly getting included into the framework. A couple weeks ago I sent out an email to the list about a "Ruby on Rails" patch for the RewriteRouter. I received a lot of great feedback from members of the list and was inspired to develop the idea further. I tried to get some of the work I did on this merged into the RewriteRouter but the author, Martel, preferred to keep his existing code as a base to make changes rather than accept a major rewrite of the Zend_Controller_Router_Route class. Because of this I decided to branch the RewriteRouter and introduce some new improvements that Zend Framework users may find extremely useful. http://framework.zend.com/wiki/display/ZFUSER/MJS_Controller_PathRouter+-+An+enhanced+RewriteRouter MJS_Controller_PathRouter improvements over Zend_Controller_RewriteRouter: 1. Cross platform. Works on apache/IIS, with or without mod_rewrite/ISAPI_Rewrite, PHP as cgi or SAPI 2. BasePath (RewriteBase) is set properly depending on whether or not you are using a rewrite module 3. Does not force you to use the default routes hard coded into the class 4. more accurately parses the incoming request to give more reliable URL matching MJS_Controller_Router_PathRoute improvements over Zend_Controller_Router_Route: 1. Matching engine is pure regex. This allows you to have the same fine-grained control over parsing your routes that you have in mod_rewrite 2. Support for controllers in subfolders 3. :variables can be defined anywhere and in any combination, not just between /'s. 4. :variables can be next to eachother 5. Any number of wildcards can be defined in your route and can capture entire strings of parameters. You are not limited to only a single wildcard at the end of the route capturing parameters in a /p1/value1/p2/value2 format like Zend_Controller_Router_Route 6. The ability to override variables after they are matched. This allows you to insert text before or after values pulled from the URL. This feature is used to support controllers in subfolders by prefixing the :controller with the subfolder after it is matched. 7. Less CPU/RAM usage. No processing occurs until it is needed. 8. Syntax and behavior is 100% backwards compatible with Zend_Controller_Router_Route On average, performance is the same or better than RewriteRouter despite all of these added features. My design philosophy behind these classes was to be as easy to use as possible for beginners and as powerful as needed for the experts. Just to put in perspective how easy it is to use and how compatible it is, you can take your existing code written for Router / RewriteRouter and change the class names to PathRouter / PathRoute and it will work out of the box. If you are in need of more compatible and industrial strength routing, please give PathRouter a try. For more information check out http://framework.zend.com/wiki/display/ZFUSER/MJS_Controller_PathRouter+-+An+enhanced+RewriteRouter which goes in depth about the classes, provides documentation, usage, examples, and benchmarks. Thanks for your time, Michael Sheakoski |
|
Hi Michael,
> 8. Syntax and behavior is 100% backwards compatible with > Zend_Controller_Router_Route Is there a need at this stage to be ensuring backwards compatibility, surely it should be about getting to the best solution? I understand why you have done it but it somehow gives me a foreboding sense of internal politics creeping in. My personal considerations for the controller/router: 1. Is it flexible enough to handle anything from the simplest url to more complex ones? e.g. By simplest I refer to the way Wordpress can manage urls like: www.myblog.com/my-post-that-is-static I may well be wrong but I cannot see a way to map the above url via a general controller to a row in a database, which means that I could not do a Wordpress to ZF conversion without resorting to using mod_rewrite (or creating multiple controller files). This always seemed to be a strange weakness in ZF so far considering how ubiquitous Wordpress is. 2. Can routes be stored together with and in a similar format to the other configuration info? Especially if development is being done in a team environment. This comment, which I agree with, was left on my article: "My reservation with your method of putting routes into the config file is that then you have to include the Zend_Controller_RewriteRouter file in your config file. I prefer to not to include code in my config file. Even aside from my personal preferences, this method can’t be used with XML or INI config files." http://www.ingredients.com.au/nick/2006/07/18/rewriterouter-and- zend_config-play-together/#comment-142 3. Does it cross the threshold by which time could be as well spent just using mod_rewrite. This includes the time spent learning the ZF way versus mod_rewrite (which would have use across several projects rather than just ZF based ones). Anyway, I need to give these proposed routers a test run. Nick |
|
Nick Lo wrote:
>> 8. Syntax and behavior is 100% backwards compatible with >> Zend_Controller_Router_Route > Is there a need at this stage to be ensuring backwards compatibility, > surely it should be about getting to the best solution? From the first glance at the proposed router I don't see how it is backwards compatible. I doesn't bind var => value parameters from URL - it leaves them in unparsed format according to the documentation (Cleveland/OH/44315). Yet it should be simple to do if you want it added. BUT, I agree with Nick. Why copy existing Router solution and add couple of functionalities you don't have to use most of the time? Maybe try to come up with something that approaches the problem at a completely different angle. So it will be useful for these people that find the current solution lacking. > e.g. By simplest I refer to the way Wordpress can manage urls like: > www.myblog.com/my-post-that-is-static > > I may well be wrong but I cannot see a way to map the above url via a > general controller to a row in a database, which means that I could > not do a Wordpress to ZF conversion without resorting to using > mod_rewrite (or creating multiple controller files). This always > seemed to be a strange weakness in ZF so far considering how > ubiquitous Wordpress is. Well, I don't see any problems here. Just define the route as ':name' and look for params['name'] in the database, Nick. Or am I missing something obvious? > 2. Can routes be stored together with and in a similar format to the > other configuration info? > Especially if development is being done in a team environment. You have to store the names, route maps, defaults and requirements for every single route. I'm willing to add the possibility to use a Zend_Config object with the RewriteRouter but I don't see how this can be conveniently stored in an ini file. I'm generaly biased in the direction of XML as I have a lot of experience working with those files. Maybe someone would be kind enough to contribute the neutral config structure for php, ini and XML config files? I mean to be possible to parse it with the same code in the hypothetic RewriteRouter method. > Nick -- Michael Minicki aka Martel Valgoerad | [hidden email] | http://aie.pl/martel.asc =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= "Finance is the art of passing money from hand to hand until it finally disappears." -- Robert W. Sarnoff |
|
>>> 8. Syntax and behavior is 100% backwards compatible with
>>> Zend_Controller_Router_Route >> Is there a need at this stage to be ensuring backwards >> compatibility, surely it should be about getting to the best >> solution? > > BUT, I agree with Nick. Why copy existing Router solution and add > couple of functionalities you don't have to use most of the time? > Maybe try to come up with something that approaches the problem at > a completely different angle. So it will be useful for these people > that find the current solution lacking. Well if this provides additional functionality then there should be a merge of solutions rather than a branch. I do however have the sense that Michael has done it this way in order to sidestep directly treading on your toes Martel which is what I meant by politics. At this point I think I'd expect some of the Zend hierarchy to step in and cast some judgement. >> e.g. By simplest I refer to the way Wordpress can manage urls like: >> www.myblog.com/my-post-that-is-static >> I may well be wrong but I cannot see a way to map the above url >> via a general controller to a row in a database, which means that >> I could not do a Wordpress to ZF conversion without resorting to >> using mod_rewrite (or creating multiple controller files). This >> always seemed to be a strange weakness in ZF so far considering >> how ubiquitous Wordpress is. > > Well, I don't see any problems here. Just define the route as > ':name' and look for params['name'] in the database, Nick. Or am I > missing something obvious? No it may well be me missing the obvious ...it was a while ago that I even though about how to do this and likely before RewriteRouter was released. Presumably the only option is to have it default to indexAction in indexController? However by then you are already in the controller and would presumably have to redirect or have some control structure to deal with it within indexAction. I think I'd like to see it routed to say a StaticPostController or such like. I don't actually have need for it right now and I suspect it would have some issues with scale/naming conflicts but I did want to use it as an example nonetheless. More detail for non Wordpress users: In Wordpress you can add a "Page" which is really just a post like any other but has a value "static". So as an example: a post is made via admin called "About Us" and is set as a "Page" ...it can then be automatically found via yourblog.com/about-us/. Clearly Wordpress must be querying its database whenever a unrecognised/non-system url is called but either way it is a good example of a simple url mapping in use across a lot of sites. > >> 2. Can routes be stored together with and in a similar format to >> the other configuration info? >> Especially if development is being done in a team environment. > > You have to store the names, route maps, defaults and requirements > for every single route. I'm willing to add the possibility to use a > Zend_Config object with the RewriteRouter but I don't see how this > can be conveniently stored in an ini file. I'm generaly biased in > the direction of XML as I have a lot of experience working with > those files. > > Maybe someone would be kind enough to contribute the neutral config > structure for php, ini and XML config files? I mean to be possible > to parse it with the same code in the hypothetic RewriteRouter method. Well from looking at the various routes implementations I agree that ini may well be too optimistic. Nick |
|
> No it may well be me missing the obvious ...it was a while ago that
> I even though about how to do this and likely before RewriteRouter > was released. Presumably the only option is to have it default to > indexAction in indexController? However by then you are already in > the controller and would presumably have to redirect or have some > control structure to deal with it within indexAction. I think I'd > like to see it routed to say a StaticPostController or such like. I > don't actually have need for it right now and I suspect it would > have some issues with scale/naming conflicts but I did want to use > it as an example nonetheless. > > More detail for non Wordpress users: In Wordpress you can add a > "Page" which is really just a post like any other but has a value > "static". So as an example: a post is made via admin called "About > Us" and is set as a "Page" ...it can then be automatically found > via yourblog.com/about-us/. Clearly Wordpress must be querying its > database whenever a unrecognised/non-system url is called but > either way it is a good example of a simple url mapping in use > across a lot of sites. Hi Nick You're not limited to using your IndexController:- $router->addRoute('wordpress', ':article', array('article' => 'default', 'controller' => 'page', 'action' => 'view')); This will map to: class PageController { function viewAction() { $article = $this->_getParam('article'); // defaults to 'default'; ...your code... } } -- Simon Mundy | Director | PEPTOLAB """ " "" """""" "" "" """"""" " "" """"" " """"" " """""" "" " 202/258 Flinders Lane | Melbourne | Victoria | Australia | 3000 Voice +61 (0) 3 9654 4324 | Mobile 0438 046 061 | Fax +61 (0) 3 9654 4124 http://www.peptolab.com |
|
In reply to this post by Martel
Hi Martel
>> 2. Can routes be stored together with and in a similar format to >> the other configuration info? >> Especially if development is being done in a team environment. > > You have to store the names, route maps, defaults and requirements > for every single route. I'm willing to add the possibility to use a > Zend_Config object with the RewriteRouter but I don't see how this > can be conveniently stored in an ini file. I'm generaly biased in > the direction of XML as I have a lot of experience working with > those files. > > Maybe someone would be kind enough to contribute the neutral config > structure for php, ini and XML config files? I mean to be possible > to parse it with the same code in the hypothetic RewriteRouter method. Here's an idea for that:- ==================================== Config file (as .ini) route.archive.route = news/:year/:month route.archive.defaults.year = 2006 route.archive.defaults.month = 1 route.archive.reqs.year = \d+ route.archive.reqs.month = \d+ or as .xml <route> <archive> <route>news/:year</route> <defaults> <year>2006</year> <month>1</month > </defaults> <reqs> <year>\d+</year> <month>\d+</month> </reqs> </archive> </route> ==================================== A new method for Zend_Controller_RewriteRouter:- public function addConfig(Zend_Config $config, $section) { if (is_null($config->{$section})) { throw new exception("no router configuration in section '{$section}'"); } foreach ($config->{$section} as $name => $info) { $this->addRoute($name, new Zend_Controller_Router_Route ($info->route, $info->defaults->asArray(), $info->reqs->asArray())); } } ==================================== And then your bootstrap file would simply contain:- $config = new Zend_Config(new Zend_Config_Ini('/my/path/config.ini', 'development')); $router = new Zend_Controller_RewriteRouter(); $router->addConfig($config, 'route'); ==================================== Even if this doesn't qualify as a feature request for RewriteRouter (one could argue it is not an essential method), it at least serves to show how flexible the existing components are! :) Cheers -- Simon Mundy | Director | PEPTOLAB """ " "" """""" "" "" """"""" " "" """"" " """"" " """""" "" " 202/258 Flinders Lane | Melbourne | Victoria | Australia | 3000 Voice +61 (0) 3 9654 4324 | Mobile 0438 046 061 | Fax +61 (0) 3 9654 4124 http://www.peptolab.com |
|
In reply to this post by Nick Lo
Nick Lo wrote:
> Hi Michael, > >> 8. Syntax and behavior is 100% backwards compatible with >> Zend_Controller_Router_Route > > Is there a need at this stage to be ensuring backwards compatibility, > surely it should be about getting to the best solution? I understand > why you have done it but it somehow gives me a foreboding sense of > internal politics creeping in. Well, originally lack of backwards compatibility was one of the reasons my patches were not considered. It wasn't too hard to do and by being compatible it means that all of the good ideas Martel thought of are included. > My personal considerations for the controller/router: > > 1. Is it flexible enough to handle anything from the simplest url to > more complex ones? > > e.g. By simplest I refer to the way Wordpress can manage urls like: > > www.myblog.com/my-post-that-is-static > > I may well be wrong but I cannot see a way to map the above url via a > general controller to a row in a database, which means that I could > not do a Wordpress to ZF conversion without resorting to using > mod_rewrite (or creating multiple controller files). This always > seemed to be a strange weakness in ZF so far considering how > ubiquitous Wordpress is. YES! This was my whole point in creating it. You can handle URLs from the simplest strings to the most complex regular expressions, just like mod_rewrite for apache. Your above example would be: $router->addRouter('wordpress', new MJS_Controller_Router_PathRoute(':post', array('controller' => 'posts', 'action' => 'view'))); > 2. Can routes be stored together with and in a similar format to the > other configuration info? This could easily be added to PathRouter / RewriteRouter. It will definitely load slower than defining your routes directly in php code though. I even experimented with storing cached versions of the routes with all arrays and regular expressions generated and it was slower due to the larger file size than just processing them on the fly. > 3. Does it cross the threshold by which time could be as well spent > just using mod_rewrite. > > This includes the time spent learning the ZF way versus mod_rewrite > (which would have use across several projects rather than just ZF > based ones). > > Anyway, I need to give these proposed routers a test run. > > Nick The reason someone would use PathRouter / RewriteRouter is to have a solution that works with or without mod_rewrite and on any web server. This would ensure that their application just works out of the box. For someone who wants the most speed possible they would most likely make their own specialized routing method specific to their software and hardware setup. |
|
In reply to this post by Martel
Martel Valgoerad wrote:
> From the first glance at the proposed router I don't see how it is > backwards compatible. I doesn't bind var => value parameters from URL > - it leaves them in unparsed format according to the documentation > (Cleveland/OH/44315). Yet it should be simple to do if you want it added. You are correct, that particular route captures the parameters as a string to be parsed by the business logic. Not every set of params SHOULD be a var/value combination. If you put a /* at the end of the route it would indeed capture everything at the end in a var/value combination though, just like the current RewriteRouter. > BUT, I agree with Nick. Why copy existing Router solution and add > couple of functionalities you don't have to use most of the time? > Maybe try to come up with something that approaches the problem at a > completely different angle. So it will be useful for these people that > find the current solution lacking. You make it sound like this is just a couple lines of code changed. Router_PathRoute DOES approach the problem at a completely different angle. People that find the current solution lacking are already using it. I've gotten many emails and feedback for it. The other classes are mostly smaller patches for compatibility and convenience but improvements nonetheless. Rather than reinvent the wheel I have been trying to work with you and your already great code. |
|
In reply to this post by Simon Mundy
Agh, yes it is glaringly, shamefully obvious after having a good
nights sleep! I think I just had that one left over from thinking about it before RewriteRouter was introduced and it has just stuck. Anyway, it is still a good example of a simple url mapping that I was referring to (quietly backs out of room...!). Thanks, Nick >> No it may well be me missing the obvious ...it was a while ago >> that I even though about how to do this and likely before >> RewriteRouter was released. Presumably the only option is to have >> it default to indexAction in indexController? However by then you >> are already in the controller and would presumably have to >> redirect or have some control structure to deal with it within >> indexAction. I think I'd like to see it routed to say a >> StaticPostController or such like. I don't actually have need for >> it right now and I suspect it would have some issues with scale/ >> naming conflicts but I did want to use it as an example nonetheless. > > Hi Nick > > You're not limited to using your IndexController:- > > $router->addRoute('wordpress', ':article', array('article' => > 'default', 'controller' => 'page', 'action' => 'view')); > > This will map to: > > class PageController > { > function viewAction() > { > $article = $this->_getParam('article'); // defaults to > 'default'; > ...your code... > } > } > > -- > > Simon Mundy | Director | PEPTOLAB > > """ " "" """""" "" "" """"""" " "" """"" " """"" " """""" "" " > 202/258 Flinders Lane | Melbourne | Victoria | Australia | 3000 > Voice +61 (0) 3 9654 4324 | Mobile 0438 046 061 | Fax +61 (0) 3 > 9654 4124 > http://www.peptolab.com > > > > |
|
In reply to this post by Simon Mundy
Purely throwing out rough ideas here but how about something like...
routes.articles.route = articles/:category routes.articles.defaults = articles/all routes.articles.required = articles/[a-z_]+ <routes> <articles> <route>articles/:category</route> <defaults>articles/all </defaults> <required>articles/[a-z_]+</required> </articles> </routes> ...which is equivalent to... $config['routes']['articles'] = new Zend_Controller_Router_Route('articles/:category', array('category' => 'all', 'controller' => 'articles', 'action' => 'index' ), array('category' => '[a-z_]+') ); ...and uses the same / separator to delimit each parameter. To me that would be easier to explain, setup, visualise, etc. and perhaps you could use the : in the defaults as in... routes.articles.defaults = articles:news/: ...which is equivalent to... array('category' => '', 'controller' => 'articles', 'action' => 'news' ) ...poor example that one but I hope the idea is clear. Nick > Here's an idea for that:- > > ==================================== > > Config file (as .ini) > > route.archive.route = news/:year/:month > route.archive.defaults.year = 2006 > route.archive.defaults.month = 1 > route.archive.reqs.year = \d+ > route.archive.reqs.month = \d+ > > or as .xml > > <route> > <archive> > <route>news/:year</route> > <defaults> > <year>2006</year> > <month>1</month > > </defaults> > <reqs> > <year>\d+</year> > <month>\d+</month> > </reqs> > </archive> > </route> > > ==================================== > > A new method for Zend_Controller_RewriteRouter:- > > public function addConfig(Zend_Config $config, $section) { > if (is_null($config->{$section})) { > throw new exception("no router configuration in section > '{$section}'"); > } > foreach ($config->{$section} as $name => $info) { > $this->addRoute($name, new Zend_Controller_Router_Route > ($info->route, > > $info->defaults->asArray(), > > $info->reqs->asArray())); > } > } > > ==================================== > > And then your bootstrap file would simply contain:- > > $config = new Zend_Config(new Zend_Config_Ini('/my/path/ > config.ini', 'development')); > $router = new Zend_Controller_RewriteRouter(); > $router->addConfig($config, 'route'); > > ==================================== > > Even if this doesn't qualify as a feature request for RewriteRouter > (one could argue it is not an essential method), it at least serves > to show how flexible the existing components are! :) > > Cheers > > -- > > Simon Mundy | Director | PEPTOLAB > > """ " "" """""" "" "" """"""" " "" """"" " """"" " """""" "" " > 202/258 Flinders Lane | Melbourne | Victoria | Australia | 3000 > Voice +61 (0) 3 9654 4324 | Mobile 0438 046 061 | Fax +61 (0) 3 > 9654 4124 > http://www.peptolab.com > > > > |
|
Nick Lo wrote:
> Purely throwing out rough ideas here but how about something like... > > routes.articles.route = articles/:category > routes.articles.defaults = articles/all > routes.articles.required = articles/[a-z_]+ It will require a lot of string parsing which I would like to avoid. Remember it will be called on every single request so it should be as fast as possible. Router is already parsing maps on every request and you wish to parse three such strings instead of one (per route of course :). I know you would like to make it very easy for a programmer to write such a configuration but it wasn't so easy to comprehend what you have meant at the first glance. Simon's solution looks clearer to me (not to mention faster of course). But I agree there is a smaller volume of markup with your idea. -- Michael Minicki aka Martel Valgoerad | [hidden email] | http://aie.pl/martel.asc =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= "Generosity is giving more than you can, and pride is taking less than you need." -- Kahlil Gibran |
|
In reply to this post by Simon Mundy
Simon Mundy wrote:
> Even if this doesn't qualify as a feature request for RewriteRouter > (one could argue it is not an essential method), it at least serves > to show how flexible the existing components are! :) Simon, brilliant work! I'm going to incorporate it into the code without any changes, if that's ok with you. > Simon Mundy | Director | PEPTOLAB -- Michael Minicki aka Martel Valgoerad | [hidden email] | http://aie.pl/martel.asc =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= "I am not young enough to know everything." -- Oscar Wilde |
|
In reply to this post by Martel
Hi Michael,
Yep no problem, as I said, just tossing ideas onto the table. I was aware it would require some string parsing though without digging into your code I had no real idea how intensive that was. I am surprised you did not find it easy to comprehend as it's a relatively straightforward mimicking of the url itself. If you are going to use the ini and xml versions I presume an array version would follow the same pattern as suggested by Simon?: $config['route']['archive']['route'] = 'news/:year/:month' $config['route']['archive']['defaults']['year'] = 2006 $config['route']['archive']['defaults']['month'] = 1 $config['route']['archive']['reqs']['year'] = '\d+' $config['route']['archive']['reqs']['month'] = '\d+' Nick > Nick Lo wrote: > >> Purely throwing out rough ideas here but how about something like... >> routes.articles.route = articles/:category >> routes.articles.defaults = articles/all >> routes.articles.required = articles/[a-z_]+ > > It will require a lot of string parsing which I would like to > avoid. Remember it will be called on every single request so it > should be as fast as possible. > Router is already parsing maps on every request and you wish to > parse three such strings instead of one (per route of course :). > > I know you would like to make it very easy for a programmer to > write such a configuration but it wasn't so easy to comprehend what > you have meant at the first glance. Simon's solution looks clearer > to me (not to mention faster of course). But I agree there is a > smaller volume of markup with your idea. > > -- > Michael Minicki aka Martel Valgoerad | [hidden email] | http:// > aie.pl/martel.asc > =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- > =-=-=-=-=-= > "Generosity is giving more than you can, and pride is taking less > than you > need." -- Kahlil Gibran > > |
|
Nick Lo wrote:
> Yep no problem, as I said, just tossing ideas onto the table. I was > aware it would require some string parsing though without digging > into your code I had no real idea how intensive that was. I have briefly analyzed it in my head. I'll try to dig deeper when I will have some free time but for now I will just use the Simon's code. > I am surprised you did not find it easy to comprehend as it's a relatively > straightforward mimicking of the url itself. That's because you have thrown examples before the explanation and I automatically started to analyze the code while reading. I have caught the idea while doing so but it just wasn't clearly evident from the very beginning. That's all. All in all, it seems as a very nice idea :) > If you are going to use the ini and xml versions I presume an array > version would follow the same pattern as suggested by Simon?: Yes, I guess. I haven't yet used Zend_Config_Array myself but it looks like it would work. > Nick -- Michael Minicki aka Martel Valgoerad | [hidden email] | http://aie.pl/martel.asc =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= "Finance is the art of passing money from hand to hand until it finally disappears." -- Robert W. Sarnoff |
|
In reply to this post by Nick Lo
On 7/25/06, Nick Lo <[hidden email]> wrote:
> <routes> > <articles> > <route>articles/:category</route> > <defaults>articles/all </defaults> > <required>articles/[a-z_]+</required> > </articles> > </routes> > I'm wet-behind-the-ears new to this list, so forgive me if I'm speaking out of turn. I'm also wet-behind-the-ears new to the ZF, but I'm fairly enchanted with it, and the work I've done with it in the past couple of nights is relevant to this topic, so I thought I'd chime in. What I've done is establish a pattern for describing routes in a Zend_Config 'compatible' file, and then extended the Zend_Controller_Front class to automate the process of receiving Zend_Config objects with route info and passing them through to the front controller's router property. Using XML as an example, routing configuration would look like this (includes a rewritebase setting, both ways of establishing default routing, and then an example of a user/:username routing, as taken from the ZF docs): <config> <production> <router> <rewritebase>/projects/myapp</rewritebase> <routes> <default comment="Default routing."> <url /> <controller>index</controller> <action>index</action> </default> <compat comment="Default routing compatibility"> <url>:controller/:action</url> <controller>index</controller> <action>index</action> </compat> <user> <url>user/:username</url> <controller>user</controller> <action>lookup</action> <variables> <username> <default>someuser</default> <validate>\w+</validate> </username> </variables> </user> </routes> </router> </production> </config> With that loaded up into a Zend_Config object, I then pass the nested router Zend_Config object off to my extended class, Phrappe_Controller_Front. It of course implements the same interface to the Zend_Controller_Front class, so an HTTP request can simply be dispatched like so: $config = new Zend_Config(Zend_Config_Xml::load('path/to/config.xml', 'production')); Phrappe_Controller_Front::run($zendConfigRouter, $zendConfigDirectory); Note: the $zendConfigDirectory passed as the second parameter to Phrappe_Controller_Front is also a Zend_Config object, which gives directory location/structure info for the application install. I'm still hashing this method out, but in my experience it has been helpful to pull this information into config files as different shared hosting allow different setup, so it's all in the name of flexibility right? Anyway the directory node in the config file would look very simple, like this: <config> <production> <directory> <controllers>path/to/controllers</controllers> </directory> </production> </config> Instead of pasting the entire code of my Phrappe_Controller_Front class into this email, here's a link to download it. The zip file includes my class file, and 3 different config files to test with, one for each style of config file allowed (xml/ini/array). http://www.johndwells.com/downloads/phrappe_controller_front.zip The source code is well-documented, so it should be straightforward as to what it's doing. I'm also trying to write up some thoughts about it for my blog. Coming shortly. I'm very curious about the implications of speed for this approach, as Martel has mentioned. Is the Zend_Config object particularly slow? Is one type of Zend_Config option faster than the next? Seems to me that application configurations are to an extent a necessary evil. Perhaps it can be up to the programmer which approach to take: if speed is paramount, then include a php file with route info hard-coded, but if there's some room for automation, then something like this might be helpful. Looking forward to feedback. John W |
|
John Wells wrote:
> Seems to me that application configurations are to an extent a necessary > evil. Perhaps it can be up to the programmer which approach to take: if > speed is paramount, then include a php file with route info hard-coded, but > if there's some room for automation, then something like this might be > helpful. Let me start with the last paragraph. I think that's what Zend Framework is designed in mind - a lot of loosely coupled components which you can choose to use or not. That's why I'm not sure if such a tight link between an original Front Controller and a Zend_Config is desirable (I can't speak for Zend here). Since it in fact refers to setting options for a third component - the Router. Your idea to extend the Front Controller is the way it should be done in my opinion. But you don't have to do so much work there. When I commit Simon's changes you will be required to extend run method only: static public function run(Zend_Config $cfg) { $router = new Zend_Controller_RewriteRouter(); $router->addConfig($config, 'routes'); $ctrl = self::getInstance(); $ctrl->setRouter($router); $ctrl->setControllerDirectory($cfg->directory); $ctrl->dispatch(); } It's not so hard to do on user part, is it? And now for the rest: > Instead of pasting the entire code of my Phrappe_Controller_Front class into > this email, here's a link to download it. The zip file includes my class > file, and 3 different config files to test with, one for each style of > config file allowed (xml/ini/array). You're checking if rewrite base is not null and not empty in setRouter. Empty string is a correct base for an absolute root (like for root of virtual host) so you may simply strike that out. > I'm very curious about the implications of speed for this approach, as > Martel has mentioned. Is the Zend_Config object particularly slow? Is one > type of Zend_Config option faster than the next? It's not my code so it would probably be a good idea to ask the author of Zend_Config himself. Rob? :) > John W -- Michael Minicki aka Martel Valgoerad | [hidden email] | http://aie.pl/martel.asc =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= "The purpose of life is to fight maturity." -- Dick Werthimer |
|
On 7/25/06, Martel Valgoerad <[hidden email]> wrote:
> Your idea to extend the Front Controller is the way it should be done in my > opinion. But you don't have to do so much work there. When I commit Simon's > changes you will be required to extend run method only: I hadn't seen Simon's changes yet (ZF wiki is not responding so I can't get to Archives), but it sounds like they are spot on. Very cool. > It's not so hard to do on user part, is it? Nope. Loving the simplicity. > You're checking if rewrite base is not null and not empty in setRouter. Empty > string is a correct base for an absolute root (like for root of virtual host) > so you may simply strike that out. Thanks for the feedback, an all points. Cheers! |
|
In reply to this post by John Wells-7
Hey John,
I like the idea, but would like to see the mappings set from outside the controller or router classes. A RouteLoader (or something similar) as a helper to setup the routes keeps the other classes nicely in the dark. --j On 7/25/06 2:27 AM, "John Wells" <[hidden email]> wrote: > On 7/25/06, Nick Lo <[hidden email]> wrote: >> <routes> >> <articles> >> <route>articles/:category</route> >> <defaults>articles/all </defaults> >> <required>articles/[a-z_]+</required> >> </articles> >> </routes> >> > > I'm wet-behind-the-ears new to this list, so forgive me if I'm > speaking out of turn. I'm also wet-behind-the-ears new to the ZF, but > I'm fairly enchanted with it, and the work I've done with it in the > past couple of nights is relevant to this topic, so I thought I'd > chime in. > > What I've done is establish a pattern for describing routes in a > Zend_Config 'compatible' file, and then extended the > Zend_Controller_Front class to automate the process of receiving > Zend_Config objects with route info and passing them through to the > front controller's router property. > > Using XML as an example, routing configuration would look like this > (includes a rewritebase setting, both ways of establishing default > routing, and then an example of a user/:username routing, as taken > from the ZF docs): > > <config> > <production> > <router> > <rewritebase>/projects/myapp</rewritebase> > <routes> > <default comment="Default routing."> > <url /> > <controller>index</controller> > <action>index</action> > </default> > <compat comment="Default routing compatibility"> > <url>:controller/:action</url> > <controller>index</controller> > <action>index</action> > </compat> > <user> > <url>user/:username</url> > <controller>user</controller> > <action>lookup</action> > <variables> > <username> > <default>someuser</default> > <validate>\w+</validate> > </username> > </variables> > </user> > </routes> > </router> > </production> > </config> > > > With that loaded up into a Zend_Config object, I then pass the nested > router Zend_Config object off to my extended class, > Phrappe_Controller_Front. It of course implements the same interface > to the Zend_Controller_Front class, so an HTTP request can simply be > dispatched like so: > > $config = new Zend_Config(Zend_Config_Xml::load('path/to/config.xml', > 'production')); > Phrappe_Controller_Front::run($zendConfigRouter, $zendConfigDirectory); > > Note: the $zendConfigDirectory passed as the second parameter to > Phrappe_Controller_Front is also a Zend_Config object, which gives > directory location/structure info for the application install. I'm > still hashing this method out, but in my experience it has been > helpful to pull this information into config files as different shared > hosting allow different setup, so it's all in the name of flexibility > right? Anyway the directory node in the config file would look very > simple, like this: > > <config> > <production> > <directory> > <controllers>path/to/controllers</controllers> > </directory> > </production> > </config> > > Instead of pasting the entire code of my Phrappe_Controller_Front > class into this email, here's a link to download it. The zip file > includes my class file, and 3 different config files to test with, one > for each style of config file allowed (xml/ini/array). > > http://www.johndwells.com/downloads/phrappe_controller_front.zip > > The source code is well-documented, so it should be straightforward as > to what it's doing. I'm also trying to write up some thoughts about > it for my blog. Coming shortly. > > I'm very curious about the implications of speed for this approach, as > Martel has mentioned. Is the Zend_Config object particularly slow? Is > one type of Zend_Config option faster than the next? > > Seems to me that application configurations are to an extent a > necessary evil. Perhaps it can be up to the programmer which approach > to take: if speed is paramount, then include a php file with route > info hard-coded, but if there's some room for automation, then > something like this might be helpful. > > Looking forward to feedback. > > John W > |
|
In reply to this post by Martel
At this point, backwards compatibility can be broken for better solutions.
We are not locking in API compatibility yet as it will inhibit useful changes. We should be careful and thoughtful, but still allow change. As for copying the existing router and making it better, that's fine as well if we are getting to a cleaner and more functional solution that is still easy to use for the simple cases. Other approaches to routing are good to explore in proposals as well but I don't think that is what Michael was wanting to do here. So let's consider what he's put onto the table here. --j On 7/24/06 4:51 AM, "Martel Valgoerad" <[hidden email]> wrote: > Nick Lo wrote: > >>> 8. Syntax and behavior is 100% backwards compatible with >>> Zend_Controller_Router_Route >> Is there a need at this stage to be ensuring backwards compatibility, >> surely it should be about getting to the best solution? > > From the first glance at the proposed router I don't see how it is backwards > compatible. I doesn't bind var => value parameters from URL - it leaves them > in > unparsed format according to the documentation (Cleveland/OH/44315). Yet it > should be simple to do if you want it added. > > BUT, I agree with Nick. Why copy existing Router solution and add couple of > functionalities you don't have to use most of the time? Maybe try to come up > with something that approaches the problem at a completely different angle. So > it will be useful for these people that find the current solution lacking. > >> e.g. By simplest I refer to the way Wordpress can manage urls like: >> www.myblog.com/my-post-that-is-static >> >> I may well be wrong but I cannot see a way to map the above url via a >> general controller to a row in a database, which means that I could >> not do a Wordpress to ZF conversion without resorting to using >> mod_rewrite (or creating multiple controller files). This always >> seemed to be a strange weakness in ZF so far considering how >> ubiquitous Wordpress is. > > Well, I don't see any problems here. Just define the route as ':name' and look > for params['name'] in the database, Nick. Or am I missing something obvious? > >> 2. Can routes be stored together with and in a similar format to the >> other configuration info? >> Especially if development is being done in a team environment. > > You have to store the names, route maps, defaults and requirements for every > single route. I'm willing to add the possibility to use a Zend_Config object > with the RewriteRouter but I don't see how this can be conveniently stored in > an ini file. I'm generaly biased in the direction of XML as I have a lot of > experience working with those files. > > Maybe someone would be kind enough to contribute the neutral config structure > for php, ini and XML config files? I mean to be possible to parse it with the > same code in the hypothetic RewriteRouter method. > >> Nick |
|
In reply to this post by Jayson Minard (ZF)
On 7/25/06, Jayson Minard <[hidden email]> wrote:
> Hey John, > > I like the idea, but would like to see the mappings set from outside the > controller or router classes. A RouteLoader (or something similar) as a > helper to setup the routes keeps the other classes nicely in the dark. > > --j > Hi J, I like the idea of a "loader". And yes, as I put it together the first time, I recognized the tight coupling I was falling into. Question then: One approach would be like you said, create a Helper class, something like: Phrappe_Controller_Router_Helper_RouteLoader. Alternatively, what about an abstract ConfigLoader, that RouterLoader then extends? Like: Phrappe_ConfigLoader_Abstract Phrappe_ConfigLoader_RewriteRouter With this approach, a Phrappe_ConfigLoader_PathRouter could quickly be created for MJS_Controller_PathRouter, as well as other config options that might bubble up in the future (like DB connection options?). Or is there another approach I don't see? Cheers, John W |
| Powered by Nabble | Edit this page |
