Splitting hook_menu into hook_menu and hook_router
Hi, We discussed renaming hook_menu and hook_router was a popular choice but as Gerhard says "I don't like to rename funtions just for the sake of renaming them" so it remained hook_menu . However, looking at my brain dump at http://drupal4hu.com/node/28 tells me that further down the road a split is needed. hook_router has these things: -- path as primary key. We use this as an array key, so an alter hook can easily be provided. -- access callback and arguments -- page callback and arguments -- map callback and arguments hook_menu has these: -- path. This is not unique. It's often requested that one path could have more than one visible link. -- parent. If you omit this, it can be autogenerated but for setting it to some arbitrary value, let's say MENU_ROOT can be used to indicate a new menu. With this (or via other means if someone has a better idea) we can put links into any menu. -- title. -- weight. -- expanded. With path being unique in one and not unique in the other, I fail to see how the two could be unified. And I fail to see the point as well. We could lose path being an array key and make it a property again in hook_router as it was in old hook_menu but then what shall happen if someone defines two router items to the same path? This is a mess. The above is nice and clean. Regards NK
On Tue, 2007-01-16 at 23:04 +0100, Karoly Negyesi wrote:
Hi,
We discussed renaming hook_menu and hook_router was a popular choice but as Gerhard says "I don't like to rename funtions just for the sake of renaming them" so it remained hook_menu .
However, looking at my brain dump at http://drupal4hu.com/node/28 tells me that further down the road a split is needed.
hook_router has these things:
-- path as primary key. We use this as an array key, so an alter hook can easily be provided. -- access callback and arguments -- page callback and arguments -- map callback and arguments
hook_menu has these:
-- path. This is not unique. It's often requested that one path could have more than one visible link. -- parent. If you omit this, it can be autogenerated but for setting it to some arbitrary value, let's say MENU_ROOT can be used to indicate a new menu. With this (or via other means if someone has a better idea) we can put links into any menu. -- title. -- weight. -- expanded.
With path being unique in one and not unique in the other, I fail to see how the two could be unified. And I fail to see the point as well. We could lose path being an array key and make it a property again in hook_router as it was in old hook_menu but then what shall happen if someone defines two router items to the same path? This is a mess. The above is nice and clean.
Regards
NK
double plus good. We can remove silly locked menu items after this split, no? What is the difference between page and map in hook_router?
double plus good. We can remove silly locked menu items after this split, no? What is the difference between page and map in hook_router?
In the http://drupal.org/node/34755 menu issue the documentation http://drupal.org/node/102338 is linked. Both the roadmap and the documentation predates the first patch. I have not jumped into this transition lightly. Locked down? MENU_DYNAMIC_ITEM? We have nothing like that. We do not even have a menu cache.
+1 for splitting them into hook_menu and hook_router.
Karoly Negyesi wrote:
Hi,
We discussed renaming hook_menu and hook_router was a popular choice but as Gerhard says "I don't like to rename funtions just for the sake of renaming them" so it remained hook_menu .
However, looking at my brain dump at http://drupal4hu.com/node/28 tells me that further down the road a split is needed.
hook_router has these things:
-- path as primary key. We use this as an array key, so an alter hook can easily be provided. -- access callback and arguments -- page callback and arguments -- map callback and arguments
hook_menu has these:
-- path. This is not unique. It's often requested that one path could have more than one visible link. -- parent. If you omit this, it can be autogenerated but for setting it to some arbitrary value, let's say MENU_ROOT can be used to indicate a new menu. With this (or via other means if someone has a better idea) we can put links into any menu. -- title. -- weight. -- expanded.
With path being unique in one and not unique in the other, I fail to see how the two could be unified. And I fail to see the point as well. We could lose path being an array key and make it a property again in hook_router as it was in old hook_menu but then what shall happen if someone defines two router items to the same path? This is a mess. The above is nice and clean.
+1 to all this. BTW: I still prefer hook_dispatch -- but that's because I've seen that term a lot in code I've worked with. Maybe it's just my history. =)
On 17 Jan 2007, at 8:21 AM, Earl Miles wrote:
-- path. This is not unique. It's often requested that one path could have more than one visible link. -- parent. If you omit this, it can be autogenerated but for setting it to some arbitrary value, let's say MENU_ROOT can be used to indicate a new menu. With this (or via other means if someone has a better idea) we can put links into any menu. -- title. -- weight. -- expanded. With path being unique in one and not unique in the other, I fail to see how the two could be unified. And I fail to see the point as well. We could lose path being an array key and make it a property again in hook_router as it was in old hook_menu but then what shall happen if someone defines two router items to the same path? This is a mess. The above is nice and clean. I think there are 2 paths involved in this. Menu path (where to display the link) and target path. I don't think there's a direct correlation between the menu path and the callback path, although it might default to that.
I think of the menu system as being a more evolved form of hook_link actually, which allows nesting. To me the key should be where it is displayed, and this might even include the menu it is being displayed in. This way it is easy for us to have an _alter hook, that allows us to change where menu items are. ie: $menu['node'] = array('path' => 'node', 'title' => 'Content'); $menu['primary:node'] = array('path' => 'node', 'title' => 'Home'); // two links to the same item, in separate trees. And then in menu_alter you could hide the elements ie: if ($menu['primary:node']) { unset($menu['primary:node']); // or $menu['primary:node']['type'] = MENU_DISABLED; } Maybe we should look at the similarities between hook_link and hook_menu some more.
On 17 Jan 2007, at 13:13, adrian rossouw wrote:
With path being unique in one and not unique in the other, I fail to see how the two could be unified. And I fail to see the point as well. We could lose path being an array key and make it a property again in hook_router as it was in old hook_menu but then what shall happen if someone defines two router items to the same path? This is a mess. The above is nice and clean.
I think there are 2 paths involved in this. Menu path (where to display the link) and target path. I don't think there's a direct correlation between the menu path and the callback path, although it might default to that.
Adrian, what do you mean with 'target path'? Care to clarify? -- Dries Buytaert :: http://www.buytaert.net/
On 17 Jan 2007, at 7:53 PM, Dries Buytaert wrote:
Adrian, what do you mean with 'target path'? Care to clarify?
Ok. there's 3 paths here. 1. the route path .. the router array is indexed via this $items['node/%/%'] = array( 'title' => t('View'), 'page callback' => 'node_page_view', 'page arguments' => array(1, 2), 'access callback' => '_comment_view_access', 'access arguments' => array(1, 2), 'type' => MENU_CALLBACK, ); 2. the target path of the menu item. IE: the EXACT PAGE, the menu item is pointing to. An example of this would be node/123.. When linking to node/123 using the menu item, you would need to resolve the target path from node/123 to the route path 'node/%/%', to be able to find out what the access permissions are. If this were the link hook, i would be referring to the 'href' element. (unless you pass the $routes to the menu hook and make it an explicit argument) 3. the menu path. ie: where in the menu this item is located. I think this is how i feel the menu data structure needs to be indexed, to be able to say where things are. Either that or we don't index the menu items at all , making them incredibly difficult to manipulate. (ie: no menu_alter hook where you could modify individual links). Also, keep in mind, that in all likelihood, we will need to have the menu item only inherit from the route. It should probably also be possible to override the access check for specific instances of that link.
3. the menu path. ie: where in the menu this item is located. Aye but definining this is quite hard... the only clue you have are menu titles and those can be quite dynamic, localized...
On 18 Jan 2007, at 2:42 PM, Karoly Negyesi wrote:
3. the menu path. ie: where in the menu this item is located.
Aye but definining this is quite hard... the only clue you have are menu titles and those can be quite dynamic, localized...
You mean like they are quite dynamic and localized in hook_link. hook_menu is essentially a nested hook_link, when you think about it. (when all the routing stuff has been removed)
On 16 Jan 2007, at 23:04, Karoly Negyesi wrote:
hook_router has these things:
-- path as primary key. We use this as an array key, so an alter hook can easily be provided. -- access callback and arguments -- page callback and arguments -- map callback and arguments
hook_menu has these:
-- path. This is not unique. It's often requested that one path could have more than one visible link. -- parent. If you omit this, it can be autogenerated but for setting it to some arbitrary value, let's say MENU_ROOT can be used to indicate a new menu. With this (or via other means if someone has a better idea) we can put links into any menu. -- title. -- weight. -- expanded.
With path being unique in one and not unique in the other ...
Care to give a concrete example of where it goes wrong? I think you'll want to elaborate on this a bit more. While you highlight some differences, it is not clear what the advantages are other than logical separation. While logical separation is a good thing, both a menu and a router would have to do access control. Looks like they might be some overlap in functionality, if you split them? Btw, the 'page callaback' vs 'map callback' is going to be a source of confusion. It is not very natural/intuitive. Is there a way to make it redundant or self-explanatory? Making the menu system accessible to developers is an important goal, so if we can brainstorm a bit more about that -- that would be great. Most people don't care all that much about memory usage and performance -- they care about clean APIs and code that is easy to grok. -- Dries Buytaert :: http://www.buytaert.net/
With path being unique in one and not unique in the other ...
Care to give a concrete example of where it goes wrong?
It's not easy because currently you can not have this. But let's suppose you want to have an 'About' page in your navigation block and as a primary link to. You just can't do this currently as the current menu and the hook_router both are keyed on path.
logical separation. While logical separation is a good thing, both a menu and a router would have to do access control. Looks like they might be some overlap in functionality, if you split them?
Menu does not do access control at all, it turns to the router for that. The functionality is... very close to zero. Maybe around the title we have some.
Btw, the 'page callaback' vs 'map callback' is going to be a source of confusion.
Sorry. Better names are welcome. But the 'map callback' is a very integral part now. It begun it's life as a convinience so that menu callbacks can act on objects instead of object ids but later on it became the main source of determining 404s for wildcarded paths. The documentation is also improved now, so it may be easier to understand. 'load callback' maybe? I thought on what Adrian suggested, and here is what I was able to create: We use $menu['navigation']['create content']['book page'] = array('title' => t('Book page'), 'weight' => 5); to define visible link. This might or might not work. The arbitrary array keys might give us grief. There is no way we can have the actual title as keys, because of location -- or do we want $menu[t('Navigation')]... all the time? I think not. I will give it some more thought.
On 18 Jan 2007, at 11:38, Karoly Negyesi wrote:
With path being unique in one and not unique in the other ...
Care to give a concrete example of where it goes wrong?
It's not easy because currently you can not have this. But let's suppose you want to have an 'About' page in your navigation block and as a primary link to. You just can't do this currently as the current menu and the hook_router both are keyed on path.
While I'm not opposed to the idea, I still fail to see the big win. Just because it provides logical separation or do you have a better reason? I guess a key reason is that the implementation drives both features apart. Still, I wonder why 5 people '+1'-ed the idea. I really like to understand so hopefully these people will motivate their vote so other can understand their reasoning/insights. Often times both functions go hand in hand: you'd need to implement one function to define the menu item, and one function to define the router. They share or cooperate with regard to access control, plus, sometimes you want to force both being connected -- i.e. you want the menu/breadcrumb to adhere to the URL path or vice versa. Isn't the trade-off that for 80% of the time, you need to learn two functions/ APIs instead of one to accomplish the same goal? I still think it would be useful to take one or two examples and to provide a 'before' and 'after'. Some practical examples will help us grok the problem at hand.
I thought on what Adrian suggested, and here is what I was able to create: We use
$menu['navigation']['create content']['book page'] = array('title' => t('Book page'), 'weight' => 5);
I like that because it is very intuitive. Although it is not clear what the difference is between 'book page' (array key) and 'Book page' (array title) or what happens when I have different 'book page's at different positions in the menu tree? Certainly an interesting idea though. -- Dries Buytaert :: http://www.buytaert.net/
$menu['navigation']['create content']['book page'] = array('title' => t('Book page'), 'weight' => 5);
I like that because it is very intuitive. Although it is not clear what the difference is between 'book page' (array key) and 'Book page' (array title) or what happens when I have different 'book page's at different positions in the menu tree?
Difference is that pesky t() in the title value. And no, it's not a solution that we throw everything that's title to t() because title can be basically anyhting. Yes, I have thought of this long. Or do you want title callback/ title arguments introduced? I have it in my mind, it would work quite nicely, but I fear I will be lynched if I introduce another callback :) Well, here it is: title callback defaults to t(), the first argument is actually title and additional arguments are in title arguments. The array keys are trying to describe the links you click through, so if it's somewhere else then the array keys are different.
On Thu, 2007-01-18 at 13:37 +0100, Dries Buytaert wrote:
Still, I wonder why 5 people '+1'-ed the idea. I really like to understand so hopefully these people will motivate their vote so other can understand their reasoning/insights.
There are several things that make me agree with the concept of splitting menu and router. 1) Lower Barrier to Entry for Developers, Self Documenting Hooks. Hook_menu currently does two things. URL to callback dispatching and defining module provided menu items. It's a little counter intuitive. I thin splitting the functionality would make it easier to understand how Drupal handles initial page loading, without having to get into the details of building a visible menu. Two simple self explanatory API's are better than one confusing API. 2) Improved memory usage. People might not care about memory and performance on the surface, but ISPs care about server resource usage, site maintainers worry about the number of visitors their site can support and their hardware needs in relation to supporting their community, and site visitor care about how quickly the page loads. 3) Lighter Bootstrap. For cases like private files and xml-rpc interactions where the visible menu is not needed, there is less data to crunch before we get to the workhorse callback. I haven't really put too much thought into the deeper implications of the map callbacks, and alter hooks, but they seem like good tools for the examplecom.module I'm writing for example.com so I don't have to hack core to customize the site behavior. I could probably come up with more reasons I like the concept if I weren't hung over. .darrel.
On 18 Jan 2007, at 20:30, Darrel O'Pry wrote:
1) Lower Barrier to Entry for Developers, Self Documenting Hooks.
Hook_menu currently does two things. URL to callback dispatching and defining module provided menu items. It's a little counter intuitive. I thin splitting the functionality would make it easier to understand how Drupal handles initial page loading, without having to get into the details of building a visible menu. Two simple self explanatory API's are better than one confusing API.
How many minutes does it take to explain the old/current menu system to someone? How many minutes does it take to explain the new/ proposed menu system to someone? That's the ultimate test. I think that the new one is easier to explain, but I haven't actually tried.
2) Improved memory usage.
People might not care about memory and performance on the surface, but ISPs care about server resource usage, site maintainers worry about the number of visitors their site can support and their hardware needs in relation to supporting their community, and site visitor care about how quickly the page loads.
Why would splitting the router and the menu reduce memory usage? Have you tested this? I'd think you end up with more arrays and some duplication.
3) Lighter Bootstrap.
For cases like private files and xml-rpc interactions where the visible menu is not needed, there is less data to crunch before we get to the workhorse callback.
The XML-RPC backend doesn't actually use the menu system so your example is moot. It has his own dispatch mechanism. Even if it would use the menu system, 99% of the time people are serving pages with menus. We should optimize for the common case. -- Dries Buytaert :: http://www.buytaert.net/
Dries Buytaert wrote:
2) Improved memory usage.
People might not care about memory and performance on the surface, but ISPs care about server resource usage, site maintainers worry about the number of visitors their site can support and their hardware needs in relation to supporting their community, and site visitor care about how quickly the page loads.
Why would splitting the router and the menu reduce memory usage? Have you tested this? I'd think you end up with more arrays and some duplication.
It is true that you will duplicate the 'path' string for every item where you have a visible menu. However, for every item where you don't have a visible menu, you'll eliminate all fields except for path, callback, callback arguments and access, and title. However x2, you won't load non-visible menu items that aren't being used *at all*; they will remain safely tucked away in the database, not eating memory except when used. Only the *visible* portion of the menu tree would be loaded. This, some saved memory. Some other good reasons: By disconnecting the visible menu from the router... 1) ...the menu title and the page title no longer need to be the same. 2) ...we will no longer have that very frustrating bug where adding a protected menu entry to the visible menu would remove all access controls to the item. 3) ...we make it easier to have multiple menu items go to the same place. Karoly has mentioned this several times, but I believe it is important to re-iterate, because it matters a great deal. 4) ...we make it easier to control where in the hierarchy your menu item actually falls. Right now that's all very automatic based upon the path. Which is all fine, but sometimes that's not what the developer wants, but the developer has no control over it. 5) ...we'll reduce the complexity of coding for tabs. Coding for tabs doesn't make a lot of sense right now, we're fairly limited in what we can do with them vs what users expect of them. Oh and creating a menu item that points to a tab will destroy the tab nature of the item. Kids love that trick.
On 18 Jan 2007, at 21:23, Earl Miles wrote:
However x2, you won't load non-visible menu items that aren't being used *at all*; they will remain safely tucked away in the database, not eating memory except when used. Only the *visible* portion of the menu tree would be loaded. This, some saved memory.
Yes! Good point, Earl. Two remarks though: 1. Do we have an idea of how many non-visible menu items there are? 2. You'd still need a little bit of information about the non- visible menu items. For example, for each visible menu item, you'll want to know if it has visible children that you have access to. You need that kind of information to determine whether the menu items is a leaf, or whether it can be folded/collapsed.
By disconnecting the visible menu from the router...
1) ...the menu title and the page title no longer need to be the same.
We choose to make page titles and menu titles identical because it is considered good practice from a usability point of view. This was suggested by usability experts. By forcing them to be the same, we enforce good behavior. It's one of the things I _really_ like about the current menu system. Decoupling both is a regression, and not a step forward.
2) ...we will no longer have that very frustrating bug where adding a protected menu entry to the visible menu would remove all access controls to the item.
Agreed.
3) ...we make it easier to have multiple menu items go to the same place. Karoly has mentioned this several times, but I believe it is important to re-iterate, because it matters a great deal.
In the current system, you'd just create a second menu item and point it to the same callback. How would this system make it easier? Simply because you'd need to duplicate less code? It would be great if we could see an actual example of how this becomes easier.
4) ...we make it easier to control where in the hierarchy your menu item actually falls. Right now that's all very automatic based upon the path. Which is all fine, but sometimes that's not what the developer wants, but the developer has no control over it.
This, too, encourages a consistent and structured URL schema. I like it when my navigation structure and URL schema are aligned. It makes for URLs that are easy to discover and remember. I'd hate it when the navigation structure and the paths would be "out-of-sync".
5) ...we'll reduce the complexity of coding for tabs. Coding for tabs doesn't make a lot of sense right now, we're fairly limited in what we can do with them vs what users expect of them.
I agree that creating tabs is somewhat cumbersome. I'd love to see an example of how you'd do tabs in the proposed system. I have a hard time imaging how it would work, and thus, why it would be better. -- Dries Buytaert :: http://www.buytaert.net/
Dries Buytaert wrote:
1. Do we have an idea of how many non-visible menu items there are?
A simple grep MENU_CALLBACK * | wc -l provides '67' as a first pass guess.
2. You'd still need a little bit of information about the non- visible menu items. For example, for each visible menu item, you'll want to know if it has visible children that you have access to. You need that kind of information to determine whether the menu items is a leaf, or whether it can be folded/collapsed.
For my purposes, I consider those to all be visible menu items; a further enhancement could eliminate the loading of items that are collapsed, which would be even better.
By disconnecting the visible menu from the router...
1) ...the menu title and the page title no longer need to be the same.
We choose to make page titles and menu titles identical because it is considered good practice from a usability point of view. This was suggested by usability experts. By forcing them to be the same, we enforce good behavior. It's one of the things I _really_ like about the current menu system. Decoupling both is a regression, and not a step forward.
This isn't fully true in our current system, at least with tabs. But even so, this is a philosophy, and should be enforced as such. i.e, code checked into Drupal core should match this philosophy, but should we actually force other people's sites into this mold? This is especially true if a site is choosing not to use breadcrumbs (...like most sites I know). For a completely mythical example, let's say I have an information page on my site that is properly named "The hoobar splotchets from the Village of Nom". That's fine for a page title, but boy that's a long menu title. Especially if my site's design has very little space for the menu. I have no quarrel with Drupal sticking to this as a philosophy in core and the like, but I am not so keen on forcing that philosophy on other people's sites.
3) ...we make it easier to have multiple menu items go to the same place. Karoly has mentioned this several times, but I believe it is important to re-iterate, because it matters a great deal.
In the current system, you'd just create a second menu item and point it to the same callback. How would this system make it easier? Simply because you'd need to duplicate less code? It would be great if we could see an actual example of how this becomes easier.
This is incorrect for two reasons. First, your solution creates two different places with the same content. We know from SEO work that google doesn't like this, but even without that...if the URLs are different, there are other factors that make it a different place. And you can't, in the current system, have the same path in the menu tree twice. Two, even if that works, I can't, via hook_menu(), put my items in the Primary Links navigation menu.
4) ...we make it easier to control where in the hierarchy your menu item actually falls. Right now that's all very automatic based upon the path. Which is all fine, but sometimes that's not what the developer wants, but the developer has no control over it.
This, too, encourages a consistent and structured URL schema. I like it when my navigation structure and URL schema are aligned. It makes for URLs that are easy to discover and remember. I'd hate it when the navigation structure and the paths would be "out-of-sync".
Except that node/* is automatically out of the schema of wherever we might want that content to be, just to grab an easy to see example. In this case, aliasing helps this somewhat, but not completely, and pathauto isn't part of core in any case. There are a lot of contrib modules that exist to address this as an issue. But sometimes, something might simply logically go in two places, because classification isn't always as clean as we want it. This is why we have two views for the administration page now. By Task and By Module.
5) ...we'll reduce the complexity of coding for tabs. Coding for tabs doesn't make a lot of sense right now, we're fairly limited in what we can do with them vs what users expect of them.
I agree that creating tabs is somewhat cumbersome. I'd love to see an example of how you'd do tabs in the proposed system. I have a hard time imaging how it would work, and thus, why it would be better.
I haven't given this enough thought to provide a truly good answer, but ideally with a proper parenting system, you'd largely have a setting that says "This is a tab of...", and the 'default' tab wouldn't need the 2 entries it does now. And without specifying a parent theoretically it could fall back on the URL for determining what the tab's parent would be. This needs more thinking than I have time to put into it now, unfortunately.
On 18 Jan 2007, at 23:03, Earl Miles wrote:
I have no quarrel with Drupal sticking to this as a philosophy in core and the like, but I am not so keen on forcing that philosophy on other people's sites.
I agree that we shouldn't limit what people can do. Remind that you can actually overwrite the page title with drupal_set_title(). We have 'good default behavior' combined with the ability to overwrite that. I'd like to keep that -- if possible.
3) ...we make it easier to have multiple menu items go to the same place. Karoly has mentioned this several times, but I believe it is important to re-iterate, because it matters a great deal. In the current system, you'd just create a second menu item and point it to the same callback. How would this system make it easier? Simply because you'd need to duplicate less code? It would be great if we could see an actual example of how this becomes easier.
This is incorrect for two reasons.
First, your solution creates two different places with the same content. We know from SEO work that google doesn't like this, but even without that...if the URLs are different, there are other factors that make it a different place. And you can't, in the current system, have the same path in the menu tree twice.
True, but this doesn't actually invalidate my statement. The obvious work-around is to do a drupal_goto() but let's not get into that. So, with the proposed system, it would just be slightly less code.
Two, even if that works, I can't, via hook_menu(), put my items in the Primary Links navigation menu.
True, but this doesn't actually invalidate my statement. Plus, as far as I can tell, this has nothing to do with separating the menu and router functionality in two functions. It just a shortcoming of the current menu system.
4) ...we make it easier to control where in the hierarchy your menu item actually falls. Right now that's all very automatic based upon the path. Which is all fine, but sometimes that's not what the developer wants, but the developer has no control over it. This, too, encourages a consistent and structured URL schema. I like it when my navigation structure and URL schema are aligned. It makes for URLs that are easy to discover and remember. I'd hate it when the navigation structure and the paths would be "out- of-sync".
Except that node/* is automatically out of the schema of wherever we might want that content to be, just to grab an easy to see example. In this case, aliasing helps this somewhat, but not completely, and pathauto isn't part of core in any case. There are a lot of contrib modules that exist to address this as an issue.
Af far as I can tell, the same would be true for the new menu system. With the current menu system. you can easily add nodes elsewhere in the menu tree. Having a default path for each node is convenient.
But sometimes, something might simply logically go in two places, because classification isn't always as clean as we want it. This is why we have two views for the administration page now. By Task and By Module.
Sure, but how would the router/menu separation simplify that compared to the current system. As far as I can tell, you'd still need two routers and two menu items.
5) ...we'll reduce the complexity of coding for tabs. Coding for tabs doesn't make a lot of sense right now, we're fairly limited in what we can do with them vs what users expect of them. I agree that creating tabs is somewhat cumbersome. I'd love to see an example of how you'd do tabs in the proposed system. I have a hard time imaging how it would work, and thus, why it would be better.
I haven't given this enough thought to provide a truly good answer, but ideally with a proper parenting system, you'd largely have a setting that says "This is a tab of...", and the 'default' tab wouldn't need the 2 entries it does now. And without specifying a parent theoretically it could fall back on the URL for determining what the tab's parent would be. This needs more thinking than I have time to put into it now, unfortunately.
Again, a shortcoming of the current menu system but not necessarily related to splitting the router/menu. Unless, maybe, I'm missing something. -- Dries Buytaert :: http://www.buytaert.net/
But sometimes, something might simply logically go in two places, because classification isn't always as clean as we want it. This is why we have two views for the administration page now. By Task and By Module.
Sure, but how would the router/menu separation simplify that compared to the current system. As far as I can tell, you'd still need two routers and two menu items.
You indeed need two router items for the 'by task' and the 'by module' pages. However, what Merlin says is that these two pages prove that sometimes two links eventually pointing to the same place are meaningful and needed. The current administration menu is a mirror of the 'by task' page and there is no way to have an 'administration by module' menu because one page, one visible menu link is the current possibility. This is not merely a minor shortcoming of the old menu or even the new menu patch, both of which use path as a primary key -- router items naturally have path as primary key as you just can't have two router items for the same path and this needs to be enforced. As a side effect, we gain the possibility of an easy and trivial hook_menu_alter.
On 18 Jan 2007, at 10:23 PM, Earl Miles wrote:
5) ...we'll reduce the complexity of coding for tabs. Coding for tabs doesn't make a lot of sense right now, we're fairly limited in what we can do with them vs what users expect of them. Oh and creating a menu item that points to a tab will destroy the tab nature of the item. Kids love that trick.
Yeah. tabs are crazy hard, and very easy to mess up.
On Thu, 2007-01-18 at 21:07 +0100, Dries Buytaert wrote:
On 18 Jan 2007, at 20:30, Darrel O'Pry wrote:
1) Lower Barrier to Entry for Developers, Self Documenting Hooks.
Hook_menu currently does two things. URL to callback dispatching and defining module provided menu items. It's a little counter intuitive. I thin splitting the functionality would make it easier to understand how Drupal handles initial page loading, without having to get into the details of building a visible menu. Two simple self explanatory API's are better than one confusing API.
How many minutes does it take to explain the old/current menu system to someone? How many minutes does it take to explain the new/ proposed menu system to someone? That's the ultimate test. I think that the new one is easier to explain, but I haven't actually tried.
The old one can be challenging to explain... The confusion seems to begin around 'type' => ...
2) Improved memory usage.
People might not care about memory and performance on the surface, but ISPs care about server resource usage, site maintainers worry about the number of visitors their site can support and their hardware needs in relation to supporting their community, and site visitor care about how quickly the page loads.
Why would splitting the router and the menu reduce memory usage? Have you tested this? I'd think you end up with more arrays and some duplication.
The only necessary duplication would be path/array keys. We would have a smaller memory footprint at ?router_execute? if we're only carrying callback information and none of the user created menu items. After that if we only load the visible menu items we have less things in memory. However we can't say for sure unless there is something to test.
3) Lighter Bootstrap.
For cases like private files and xml-rpc interactions where the visible menu is not needed, there is less data to crunch before we get to the workhorse callback.
The XML-RPC backend doesn't actually use the menu system so your example is moot. It has his own dispatch mechanism. Even if it would use the menu system, 99% of the time people are serving pages with menus. We should optimize for the common case.
So maybe XML-RPC was a bad example, private files still are. Maybe files just need there own .php which would also make my point moot. There maybe some other MENU_CALLBACK(~80)'s that don't need a menu, also anytime we find ourself at a drupal_goto(~50) we can probably live without having a menu. So the menu thing is only built on demand we have a few spots we can avoid building it.
Why would splitting the router and the menu reduce memory usage? Have you tested this? I'd think you end up with more arrays and some duplication.
Kindly please stop the memory discussion, it's pointless and it seems you guys think in old menu terms. There are no memory or performance affects of this split whatsoever. Read http://drupal4hu.com/node/28 for gory details. To sum up, one database query will select the pre-themed and aliased menu items in order and put them into lists. There is no change to this process whatever way we filled up the database table. We now focus on the build details, not something that happens on runtime. Nor hook_menu nor hook_router will be consulted on runtime. The current menu patch already does not look at hook_menu aside from build time, that's why I thought of moving them to .menu but that's for later.
On 19 Jan 2007, at 00:29, Darrel O'Pry wrote:
For cases like private files and xml-rpc interactions where the visible menu is not needed, there is less data to crunch before we get to the workhorse callback.
The XML-RPC backend doesn't actually use the menu system so your example is moot. It has his own dispatch mechanism. Even if it would use the menu system, 99% of the time people are serving pages with menus. We should optimize for the common case.
So maybe XML-RPC was a bad example, private files still are. Maybe files just need there own .php which would also make my point moot.
There maybe some other MENU_CALLBACK(~80)'s that don't need a menu, also anytime we find ourself at a drupal_goto(~50) we can probably live without having a menu. So the menu thing is only built on demand we have a few spots we can avoid building it.
Good points. These examples make sense to me. Thanks Darrel. I can start seeing some of the potential, but we'll want to back that up with real tests. Interesting stuff. -- Dries Buytaert :: http://www.buytaert.net/
While I'm not opposed to the idea, I still fail to see the big win. Just because it provides logical separation or do you have a better reason? Well... That is a reason enough in it's own right. Currently the menu hook has two concerns, menu placement and routing. While the init could benefit from one place - it is simpler. The logic of what happens later becomes too complicated leading to those annoying bugs/features like Access Denied for custom links in menu, etc...
It is simpler, at least has the potential to be simpler, in my book taht is better. Extra api? if the two apis are easier to understand than the current one I think it is better.
On 19 Jan 2007, at 10:28, Vladimir Zlatanov wrote:
While I'm not opposed to the idea, I still fail to see the big win. Just because it provides logical separation or do you have a better reason?
Well... That is a reason enough in it's own right. Currently the menu hook has two concerns, menu placement and routing. While the init could benefit from one place - it is simpler. The logic of what happens later becomes too complicated leading to those annoying bugs/features like Access Denied for custom links in menu, etc...
It is simpler, at least has the potential to be simpler, in my book taht is better. Extra api? if the two apis are easier to understand than the current one I think it is better.
I generally agree. It looks promising but it does have some drawbacks/regressions. It's difficult to weigh/evaluate these right now. We'll have to take this a step further and experiment with it. I'm positive about the outcome. :) -- Dries Buytaert :: http://www.buytaert.net/
Karoly Negyesi wrote something that sounds sensible: <snip> So is the proposal that we still have the same menu array with two different hooks acting on it? Possibly a third to do alterations? And does it still mean that we have the same menu table? The question really is that if we are differentiating 'routers' from 'menus' then shouldn't there be different objects stored in different places? andre
On Wed, 2007-01-17 at 13:52 -0500, Andre Molnar wrote:
Karoly Negyesi wrote something that sounds sensible: <snip>
So is the proposal that we still have the same menu array with two different hooks acting on it? Possibly a third to do alterations? And does it still mean that we have the same menu table?
The question really is that if we are differentiating 'routers' from 'menus' then shouldn't there be different objects stored in different places?
andre
I think we are talking distinct objects with this split. Router would create the 'path' / 'callback' / 'mapping' / 'access' grouping... the menu would probably query the router table for access control and use its own hierarchy to build menu structures (blocks and tabs). does this sound accurate chx?
hook_router has these things:
-- path as primary key. We use this as an array key, so an alter hook can easily be provided. -- access callback and arguments -- page callback and arguments -- map callback and arguments
hook_menu has these:
-- path. This is not unique. It's often requested that one path could have more than one visible link. -- parent. If you omit this, it can be autogenerated but for setting it to some arbitrary value, let's say MENU_ROOT can be used to indicate a new menu. With this (or via other means if someone has a better idea) we can put links into any menu. -- title. -- weight. -- expanded.
(I wrote a reply to this on my way home, ran out of battery and forgot my power supply at work. I'm using my wife's computer to reply. ;)) Can you elaborate some more on why this is good? Do you have a concrete use case with a before and after? It would help me understand ... I agree that a logically seperation is a good thing, but this in particular case, it seems as if there is some overlap. For example, both routers and menus would have to do access control ... -- Dries Buytaert :: http://buytaert.net/
On 17 Jan 2007, at 9:06 PM, Dries Buytaert wrote:
I agree that a logically seperation is a good thing, but this in particular case, it seems as if there is some overlap. For example, both routers and menus would have to do access control ... I also realized that the overlap isn't as much as you'd think
Menu items can point to user/1 or node/12345. These would still need to be mapped to the 'node/%s' router. Which then gets the access permission. Another idea I had was to pass the routes to the menu hook, and allow people to do the following: (i'm not sure what we are using as the wildcard now) function module_menu($routes) { $menu['wherever/too'] = drupal_menu('node/12345', $routes['node/% s'], $array_props); # or alternatively perhaps : $menu['wherever/this/is/shown'] = drupal_menu('user/12') // this could do the mapping and cache it. (without the need for recursion through the whole tree later) return $menu; }
On 16 Jan 2007, at 23:04, Karoly Negyesi wrote:
We discussed renaming hook_menu and hook_router was a popular choice but as Gerhard says "I don't like to rename funtions just for the sake of renaming them" so it remained hook_menu .
On a slightly related note. Rails 1.2 was released -- one of the changes includes a complete rewrite of their router code. Might be worth a closer look. "Action Pack has an all new implementation of Routes that’s both faster and more secure, but it’s also a little stricter. Semicolons and periods are separators, so a /download/:file route which used to match /download/history.txt doesn’t work any more. Use :requirements => { :file => /.*/ } to match the period." http://weblog.rubyonrails.com/2007/1/19/rails-1-2-rest-admiration- http-lovefest-and-utf-8-celebrations (The "formats and respond_to" feature is something I've wanted for 2 years now. In Drupal, that is.) -- Dries Buytaert :: http://www.buytaert.net/
participants (8)
-
adrian rossouw -
Andre Molnar -
Darrel O'Pry -
Dries Buytaert -
Earl Miles -
Karoly Negyesi -
Khalid B -
Vladimir Zlatanov