The SitePoint Forums have moved.

You can now find them here.
This forum is now closed to new posts, but you can browse existing content.
You can find out more information about the move and how to open a new account (if necessary) here.
If you get stuck you can get support by emailing forums@sitepoint.com

If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

I'm a little late to this party, so excuse me if I reiterate some points, but since my name came up I thought I'd just add a few clarifications.

Originally Posted by allspiritseve

Having a hierarchy of controllers also opens up opportunities for code reuse. A parent controller could be setting a datasource for a child controller, which means you could have the same child controller work for many parent controllers. I'm sure there are a lot more benefits than this, but wysiwyg or kyberfabrikken would probably be able to explain them better than I could.

One of the things that works well with hierarchical controllers, is that it forms a coherent presentational unit. Amongst other things, this makes for a practical way of managing urls and url-propagated state in a transparent way to the rest of the application. It's a different way of cutting the presentation layer, than frontcontroller + mvc. Controllers (or components, as they are called in Konstrukt) tend to be smaller and control only part of the rendering of the page, while having a tighter coupling between controller and view layer. This means that you can't as easily change the view of your application, without touching the controller layer, but the benefit is that you gain a much tighter control of the http-level interaction. In many types of applications, I find that trade worthwhile, since it makes it easier to create a good end-to-end user interaction. It also does away with some (in some cases) redundant abstractions.

Originally Posted by matthijsA

The fact is that in the end it's always one controller and one action that are responsible for the response. So the question is, do you get to that controller/action set in one go or through several steps? In that last case controller A gets the first part of the URL. Can I handle it? No, forward to next controller. That one checks if it has to handle it as well. No? Forward again. Etc etc.

With hierarchical controllers, you can spread the handling out over multiple controllers. In a Konstrukt application, you would usually have one "final" handler, which corresponds to the "action" of Rails. However, you would often have several parent handlers, which add a bit of rendering (Navigation for example) or provide contextual model level access for the final handler. This roughly corresponds to Rails "layouts", except that you're not restricted to one, and it isn't just for rendering the view.

Originally Posted by matthijsA

On one side it seems simple to use, but at the same time I wonder what happens if you want to restructure your whole URL scheme. If you have the scheme in a central place, it's easy to change. If it's decentralized, you have to change every part of it.

Since components are completely contextual, it is quite easy to move them around. URLs are generated by refering to the parent component, so when a component is moved the urls will automatically change. In fact, you could use the same component in multiple places in your application at the same time. This is especially useful if you want to combine different applications, that weren't written for each other, because they won't fight over the same global resource (the route). In general, it's a more flexible and modular design; The problems with it is rather that it is slightly more abstracted. As a developer, you can't go to a single place and get an overview of all possible urls in the application.

It's an interesting approach and different from what you see in most frameworks like Zends. I guess there are certain advantages and disadvantages (as always) and which is more important depends on the kind of webapp you build

One thing I do wonder about, if each parent handler is responsible for a certain part of the rendering (the layout with header and navigation for example), how do you feed back information from a child to its parent? For example the child controller will have information about the "current page or section", information that is needed in the parent to display in the navigation menu ("the currently selected menu item")

It's an interesting approach and different from what you see in most frameworks like Zends. I guess there are certain advantages and disadvantages (as always) and which is more important depends on the kind of webapp you build

Certainly. I'd say it shines most with a fairly complex, hierarchical interface. That generally means guis for applications, rather than web sites.

Originally Posted by matthijsA

One thing I do wonder about, if each parent handler is responsible for a certain part of the rendering (the layout with header and navigation for example), how do you feed back information from a child to its parent? For example the child controller will have information about the "current page or section", information that is needed in the parent to display in the navigation menu ("the currently selected menu item")

A component knows the "remainder" part of the url (Called subspace), so you'd usually render the navigation in the component immediately parent to the final handler. I've build some applications with a gui that consisted of layered "tabs", where each component in the chain rendered a wrapping around each other. Works really well, because the graphical presentation mimics the logical structure of the application, making it easy to navigate in.

I think so. But you should start by asking yourself: is that actually a Resource Locator, or are you throwing parameters (that should be in the query string) in the URL's path? A URL in my application would look like: /hotels/england/london/?date=16-03-2009&guests=2.

Not exactly. The default behaviour is that each segment is handled by it's own component, but you can override that so that basically only one component handles the whole chain. But as webaddictz wrote, the last segments there should really be query strings and not segments.

Well that URL is just an example, but I can think of more URLs with multiple arguments which could be defined as "query strings", but at the same time look better as segments.

Just think of the average weblog with
/category/php/2007/10/08/cool-routing

Those arguments php, 2007, 10, 08 could all be defined as query string. But at the same time they could be a resource as well so
/category/php/2007/10/shows all posts in category php from 2007 / 10

I think I would prefer to write a single controller for handling archives, which would take the arguments for category, year, month, day and postname (or something like that) over having 6 controllers for each segment. Of course I am not familiar enough with Konstrukt to know how it works. But having 6 controllers each making a call to the "posts" model instead of having one controller making a call to the same model but then with different arguments doesn't sound too attractive to me.

I do understand that the way Konstrukt handles things forces one to rethink and sometimes simplify the URLs. But I can also see situations in which you just want a different, more flexible and free URL scheme

The default approach in Konstrukt is not to let all components call your model layer, as that would be terribly inefficient. You'd usually only let the final component call the model layer, as it knows that it's the final component. Or, you'd let a higher level component call the model layer, and the lower level components queries the higher level component for those objects.

I absolutly agree that "/category/php/2007/10/08/" is a good url. Let's look at the differences of having one controller to handle all of the possible situations with that url, and having multiple.

If you only have one, you'd have to have some conditional logic to check if the url is /category/php/2007/, or /category/php/2007/10/, or /category/php/2007/10/08/, as those three would require different views because they present different things.

If you use three different components for this, you can place common logic in a higher level component, and let the Month component worry about months, etc.

Besides, there's no requirement that each segment is handled by a unique component. It could be three objects from the same class, with some conditional logic inside to check for date parts.

But I can also see situations in which you just want a different, more flexible and free URL scheme

I actually feel quite the opposite. I see Konstrukts routing logic as the most flexible since your url mapping is based on logic instead of rules. And if you'd like, you can always let one component handle more than one segment (even though I've never found myself in a situation where that would be useful).

I actually feel quite the opposite. I see Konstrukts routing logic as the most flexible since your url mapping is based on logic instead of rules. And if you'd like, you can always let one component handle more than one segment (even though I've never found myself in a situation where that would be useful).

I absolutly agree that "/category/php/2007/10/08/" is a good url. Let's look at the differences of having one controller to handle all of the possible situations with that url, and having multiple.

If you only have one, you'd have to have some conditional logic to check if the url is /category/php/2007/, or /category/php/2007/10/, or /category/php/2007/10/08/, as those three would require different views because they present different things.

In this case I don't think there's any conditional logic needed or more then one view. You have one method in one controller which handles those parameters (probably as a bunch of "where X=Y" calls to the model layer)

Originally Posted by wysiwyg

I actually feel quite the opposite. I see Konstrukts routing logic as the most flexible since your url mapping is based on logic instead of rules. And if you'd like, you can always let one component handle more than one segment (even though I've never found myself in a situation where that would be useful).

Well maybe I don't understand Konstrukt's ideas well enough. I've read the two tutorials on Konstrukt's site but yet fail to understand the philosophy/why behind the way it is set up (not saying its good/bad, just that I don't understand it yet)

In this case I don't think there's any conditional logic needed or more then one view. You have one method in one controller which handles those parameters (probably as a bunch of "where X=Y" calls to the model layer)

If the url only has a year, would you display that the same way as if the url had a year, month and day? That could be a very long list. And you'd probably want to write out the months as headlines above that months entries, which you wouldn't if the url contained a full date.

I know that the concept behind Konstrukt isn't always that easy to understand (I know, because I was a user of Konstrukt before I was a contributor). But when I understood how it all worked, I basically never wanted to do it any other way.

If the url only has a year, would you display that the same way as if the url had a year, month and day? That could be a very long list. And you'd probably want to write out the months as headlines above that months entries, which you wouldn't if the url contained a full date.

I know that the concept behind Konstrukt isn't always that easy to understand (I know, because I was a user of Konstrukt before I was a contributor). But when I understood how it all worked, I basically never wanted to do it any other way.

The thing that has helped me a lot when learning Konstrukt's way of work is the reference to REST. When I started looking up articles on REST it hit me: every URL is a Resource and in Konstrukt, every Resource is a Component. It's really simple once you've got the hang of it.

I have been thinking about a different approach to mvc for web lately. Don't know if this idea is good or bad. I'll lay it out and then you can judge for yourselves.

Key point:
- When routing everything to one file you have to mess with the normal flow of a webapplication. You add a front-controller which with the help of a router implementation figure out which controllers to load. One also oftentimes add a .htaccess file for creating pretty urls. In other words, you add complexity. Is it neccessary?

Alternate approach:
- Folders determine structure (categories, modules etc)
- When calling a controller action, one calls a file directly (/app/articles/edit.php) and in that file is the logic for that controller action
- Each controller-file include optional parent files such as configuration, db-connection, template, authorization and module-specific pre-dispatch logic. These are usually grouped together into a single include-file which is included at the top of each controller-file
- For each module in your app, you can create a different include file for your controller actions, so that you can have module-specific logic passed on to each controller-action in your module
- Use autoloading for library-classes and model-classes

Pros with this approach:
- No need to mess with urls and translate them into something meaningful
- Easy to see what's going on, and how things fit together.
- No need for .htaccess
- Unlimited categories/modules/subcategories
- Easy to create actions/pages that needs to be different (like ajax responses, csv responses, upload script for images etc..)
- Easy to move modules around.

Cons:
- Not suitable for cases where you have dynamic urls (like a website that get its content and structure from a database)
- If you really don't want to have .php in your url.

You can save /app/articles/edit.php as /app/articles/edit/index.php to get around that problem.

What you're describing is basically what Fowler calls a page controller (As opposed to a front controller). It has its merits, but it certainly has some limitations as you mention. The biggest benefit of it today, as far as I see it, is that it's the default modus for PHP, which means that you can expect almost anyone with prior PHP experience to understand it. That could have some value, especially in open source projects. And actually, that still seems to be the default for the popular open source PHP applications out there.

I have been thinking about a different approach to mvc for web lately. Don't know if this idea is good or bad. I'll lay it out and then you can judge for yourselves...

I've done my fair share of this, and it definitely has its advantages and disadvantages. The simplicity is very nice, and it makes starting a new project take almost no time. Likewise, it makes for code that is very easy to follow.

You do lose something by not piping all of your requests through one file, though. Manually including core.inc.php and your view files gets old quickly, for example. You also can't catch any uncaught exceptions in a central place and give an error message. Instead, your script will stop executing and either display an error or go silent (depending on display_errors, of course).

There are really quite a few pros and cons to every setup. I've got to say, though, I'm starting to like this hierarchical idea.

When I started a recent project, I wanted to get things up and running as quickly as possible and so this was almost exactly the approach that I took. However, instead of putting the controller stuff in the global level, I put action handler functions in the page controller file. The global include file ('core.inc.php' in your case) would determine which action function to call from the request uri and would look throughout the module path for a 'module.init.php' file that it would load as well as a similar, but global 'site.init.php'. This has worked pretty well so far, however, the major drawback has been the difficulty of internal redirects.

Regardless, for smaller-scoped projects, I've found the approach to be very simple for rapid prototyping and even development.

For the type of links discussed above, however, you will find that the page-controller approach is unrealistic. For example /blog/2009/03/ would necessitate a controller for each month of each year, all identical. Perhaps a simple .htaccess rule in the /blog/ subdirectory would suffice to remap the year and month as GET arguments. Anyway, I encourage you to try it out. At the minimum you will start with something that gets the job done and each iteration of functionality and refactoring that you add will improve your product. This is in contrast to trying to engineer everything in advance and never even starting the project itself (my problem).

I implement routes in a similar way to the majority of frameworks out there. I store all defined specific/generic/remapped routes in an object and use that same object to try to match the current URI against one of those routes. Here are some examples of how routes are stored:

The parser uses a few nifty tricks to match the longest route that it can. It ends up returning an array of what directory the file is located at, what the file name is, and then any other extra info. So, in essence, the structure of a route is:

Each route that is added is split into two parts: everything up to, but excluding, the first generic part, for example: ( : year), and then everything that follows the start of the generic parts. This is the longest prefix of the route, and allows multiple routes of a common prefix to be grouped together (note: all routes without prefixes are also grouped together). Within these prefix groups, the variable part of the routes are sorted in descending order of their length, so that we try to match the remainder of the route against the longest regular expressions we can.

Given a URI, U, split U into a queue, Q, of non-empty parts by the regular expression ~\s*/+\s*~. Let S be an empty string, representing our current longest prefix found so far.

Code:

While (Q is not empty) and (S+first(Q) exists as a longest prefix):
S := S+shift(Q).

The result S is the longest prefix for the URI. We join the remaining parts in Q by a '/' and then iterate over the regular expressions and try to match the longest one.

Mastodont, this is either not solved using route re-mappings (i.e. the route parser just figures out the deepest that it can go to get a controller file, and accepts it), or it is solved using either generic or specific route re-mappings.

For the most part, the route re-mappings have the following uses:
- Limiting the number of arguments that get passed to the actions
- Making an action appear to be a controller
- Dealing with very variable routes, especially ones with common prefixes.